[clang] [clang][analyzer] Add note tags to alpha.unix.BlockInCriticalSection (PR #80029)

2024-02-07 Thread Balázs Kéri via cfe-commits


@@ -57,6 +61,12 @@ class BlockInCriticalSectionChecker : public 
Checker {
 const CallEvent ,
 CheckerContext ) const;
 
+  CritSectionMarker getCriticalSectionMarker(const CallEvent ,
+ CheckerContext ) const;
+  const NoteTag *
+  createCriticalSectionNote(const CritSectionMarker ,
+CheckerContext ) const;

balazske wrote:

I do not know if it is sufficient to store the set of all found lock calls 
until the last unlock happens. Probably in the following situation it does not 
work:
```
std::mutex m, n, k;
m.lock();
n.lock();
n.unlock();
k.lock();
k.unlock();
sleep(1);
m.unlock();
```
It looks better to store all locked mutex objects somehow (not the lock calls), 
and remove one at unlock. Then the mutex counter is not needed.

https://github.com/llvm/llvm-project/pull/80029
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][AArch64] Warn when calling streaming/non-streaming about vect… (PR #79842)

2024-02-07 Thread Dinar Temirbulatov via cfe-commits


@@ -7513,6 +7516,44 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
   }
 }
 
+auto *CallerFD = dyn_cast(CurContext);
+if (FD && CallerFD && Context.getTargetInfo().hasFeature("sme") &&
+!FD->getBuiltinID()) {
+  // If the callee has an AArch64 SME __arm_locally_streaming attribute
+  // warn if this function returns VL-based value or pass any such 
argument,
+  // the streaming and non-streaming vector lengths may be different.
+  ArmStreamingType CalleeFnType = getArmStreamingFnType(FD);
+  ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD);
+  if (FD->hasAttr()) {
+if (AnyScalableArgs)
+  Diag(Loc, diag::warn_sme_locally_streaming_has_vl_args);
+if (FD->getReturnType()->isSizelessVectorType())
+  Diag(Loc, diag::warn_sme_locally_streaming_returns_vl);
+  }

dtemirbulatov wrote:

Done.

https://github.com/llvm/llvm-project/pull/79842
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][AArch64] Warn when calling streaming/non-streaming about vect… (PR #79842)

2024-02-07 Thread Dinar Temirbulatov via cfe-commits


@@ -7513,6 +7516,44 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
   }
 }
 
+auto *CallerFD = dyn_cast(CurContext);
+if (FD && CallerFD && Context.getTargetInfo().hasFeature("sme") &&
+!FD->getBuiltinID()) {
+  // If the callee has an AArch64 SME __arm_locally_streaming attribute
+  // warn if this function returns VL-based value or pass any such 
argument,
+  // the streaming and non-streaming vector lengths may be different.
+  ArmStreamingType CalleeFnType = getArmStreamingFnType(FD);
+  ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD);
+  if (FD->hasAttr()) {
+if (AnyScalableArgs)
+  Diag(Loc, diag::warn_sme_locally_streaming_has_vl_args);
+if (FD->getReturnType()->isSizelessVectorType())
+  Diag(Loc, diag::warn_sme_locally_streaming_returns_vl);
+  }
+  // If the caller is a non-streaming function and the callee has a
+  // streaming attribute. If it passed any VL-based arguments or return
+  // VL-based value, then warn that the streaming and non-streaming vector
+  // lengths may be different.
+  if (CallerFnType != ArmStreaming) {
+if (CalleeFnType == ArmStreaming) {
+  if (AnyScalableArgs)
+Diag(Loc,
+ diag::warn_sme_non_streaming_caller_pass_args_to_streaming);
+  if (FD->getReturnType()->isSizelessVectorType())
+Diag(Loc, 
diag::warn_sme_non_streaming_caller_returns_to_streaming);
+}
+  } else if (!FD->hasAttr()) {

dtemirbulatov wrote:

Done.

https://github.com/llvm/llvm-project/pull/79842
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,273 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-cpu x86-64-v4 
-std=c23 -O1 -ffreestanding -emit-llvm -o - %s | FileCheck %s
+
+// This test sanity checks calling a variadic function with the expansion 
transform disabled.
+// The IR test cases {arch}/expand-variadic-call-*.ll correspond to IR 
generated from this test case.
+
+typedef __builtin_va_list va_list;
+#define va_copy(dest, src) __builtin_va_copy(dest, src)
+#define va_start(ap, ...) __builtin_va_start(ap, 0)
+#define va_end(ap) __builtin_va_end(ap)
+#define va_arg(ap, type) __builtin_va_arg(ap, type)
+
+// 32 bit x86 alignment uses getTypeStackAlign for special cases
+// Whitebox testing.
+// Needs a type >= 16 which is either a simd or a struct containing a simd
+// darwinvectorabi should force 4 bytes
+// linux vectors with align 16/32/64 return that alignment
+
+
+void wrapped(va_list);
+
+// CHECK-LABEL: @codegen_for_copy(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[CP:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
+// CHECK-NEXT:call void @llvm.lifetime.start.p0(i64 24, ptr nonnull 
[[CP]]) #[[ATTR7:[0-9]+]]
+// CHECK-NEXT:call void @llvm.va_copy(ptr nonnull [[CP]], ptr [[X:%.*]])
+// CHECK-NEXT:call void @wrapped(ptr noundef nonnull [[CP]]) 
#[[ATTR8:[0-9]+]]
+// CHECK-NEXT:call void @llvm.va_end(ptr [[CP]])
+// CHECK-NEXT:call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[CP]]) 
#[[ATTR7]]
+// CHECK-NEXT:ret void
+//
+void codegen_for_copy(va_list x)
+{
+  va_list cp;
+  va_copy(cp, x);
+  wrapped(cp);
+  va_end(cp);
+}
+
+
+// CHECK-LABEL: @vararg(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[VA:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
+// CHECK-NEXT:call void @llvm.lifetime.start.p0(i64 24, ptr nonnull 
[[VA]]) #[[ATTR7]]
+// CHECK-NEXT:call void @llvm.va_start(ptr nonnull [[VA]])
+// CHECK-NEXT:call void @wrapped(ptr noundef nonnull [[VA]]) #[[ATTR8]]
+// CHECK-NEXT:call void @llvm.va_end(ptr [[VA]])
+// CHECK-NEXT:call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[VA]]) 
#[[ATTR7]]
+// CHECK-NEXT:ret void
+//
+ void vararg(...)
+{
+  va_list va;
+  __builtin_va_start(va, 0);
+  wrapped(va);
+  va_end(va);
+}
+
+// vectors with alignment 16/32/64 are natively aligned on linux x86
+// v32f32 would be a m1024 type, larger than x64 defines at time of writing
+typedef int i32;
+typedef float v4f32 __attribute__((__vector_size__(16), __aligned__(16)));
+typedef float v8f32 __attribute__((__vector_size__(32), __aligned__(32)));
+typedef float v16f32 __attribute__((__vector_size__(64), __aligned__(64)));
+typedef float v32f32 __attribute__((__vector_size__(128), __aligned__(128)));
+
+
+// Pass a single value to wrapped() via vararg(...)
+// CHECK-LABEL: @single_i32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:tail call void (...) @vararg(i32 noundef [[X:%.*]]) 
#[[ATTR9:[0-9]+]]
+// CHECK-NEXT:ret void
+//
+void single_i32(i32 x)
+{
+  vararg(x);
+}
+
+// CHECK-LABEL: @single_double(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:tail call void (...) @vararg(double noundef [[X:%.*]]) 
#[[ATTR9]]
+// CHECK-NEXT:ret void
+//
+void single_double(double x)
+{
+  vararg(x);
+}
+
+// CHECK-LABEL: @single_v4f32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:tail call void (...) @vararg(<4 x float> noundef [[X:%.*]]) 
#[[ATTR9]]
+// CHECK-NEXT:ret void
+//
+void single_v4f32(v4f32 x)
+{
+  vararg(x);
+}
+
+// CHECK-LABEL: @single_v8f32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:tail call void (...) @vararg(<8 x float> noundef [[X:%.*]]) 
#[[ATTR9]]
+// CHECK-NEXT:ret void
+//
+void single_v8f32(v8f32 x)
+{
+  vararg(x);
+}
+
+// CHECK-LABEL: @single_v16f32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:tail call void (...) @vararg(<16 x float> noundef [[X:%.*]]) 
#[[ATTR9]]
+// CHECK-NEXT:ret void
+//
+void single_v16f32(v16f32 x)
+{
+  vararg(x);
+}
+
+// CHECK-LABEL: @single_v32f32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[INDIRECT_ARG_TEMP:%.*]] = alloca <32 x float>, align 128
+// CHECK-NEXT:[[X:%.*]] = load <32 x float>, ptr [[TMP0:%.*]], align 128, 
!tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT:store <32 x float> [[X]], ptr [[INDIRECT_ARG_TEMP]], align 
128, !tbaa [[TBAA2]]
+// CHECK-NEXT:tail call void (...) @vararg(ptr noundef nonnull byval(<32 x 
float>) align 128 [[INDIRECT_ARG_TEMP]]) #[[ATTR9]]
+// CHECK-NEXT:ret void
+//
+void single_v32f32(v32f32 x)
+{
+  vararg(x);
+}
+
+
+
+// CHECK-LABEL: @i32_double(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:tail call void (...) @vararg(i32 noundef [[X:%.*]], double 
noundef [[Y:%.*]]) #[[ATTR9]]
+// CHECK-NEXT:ret void
+//
+void i32_double(i32 x, double y)
+{
+  vararg(x, y);
+}
+
+// CHECK-LABEL: @double_i32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:tail call void (...) @vararg(double noundef [[X:%.*]], i32 
noundef [[Y:%.*]]) 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -Wno-varargs -O1 
-disable-llvm-passes -emit-llvm -o - %s | opt --passes=instcombine | opt 
-passes="expand-variadics,default" -S | FileCheck %s 
--check-prefixes=CHECK,X86Linux

arsenm wrote:

can do this in one opt run?

https://github.com/llvm/llvm-project/pull/81058
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][AArch64] Warn when calling streaming/non-streaming about vect… (PR #79842)

2024-02-07 Thread Dinar Temirbulatov via cfe-commits


@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme 
-fsyntax-only -verify %s
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme 
-fsyntax-only -verify=expected-cpp -x c++ %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -fsyntax-only -verify=expected-cpp -x c++ %s
+#include 

dtemirbulatov wrote:

Done.

https://github.com/llvm/llvm-project/pull/79842
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][AArch64] Warn when calling streaming/non-streaming about vect… (PR #79842)

2024-02-07 Thread Dinar Temirbulatov via cfe-commits

https://github.com/dtemirbulatov updated 
https://github.com/llvm/llvm-project/pull/79842

>From af323998a63a72f569d543cf5167d5d28e784682 Mon Sep 17 00:00:00 2001
From: Dinar Temirbulatov 
Date: Mon, 29 Jan 2024 14:43:13 +
Subject: [PATCH 1/3] [Clang][AArch64] Warn when calling
 streaming/non-streaming about vector size might be different.

The compiler doesn't know in advance if the streaming and non-streaming
vector-lengths are different, so it should be safe to give a warning diagnostic
to warn the user about possible undefined behaviour. If the user knows
the vector lengths are equal, they can disable the warning separately.
---
 .../clang/Basic/DiagnosticSemaKinds.td| 24 +++
 clang/lib/Sema/SemaChecking.cpp   | 42 
 clang/test/Sema/aarch64-sme-func-attrs.c  | 68 ++-
 3 files changed, 132 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 24d32cb87c89e2..37fea5746936c7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3717,6 +3717,30 @@ def err_sme_definition_using_za_in_non_sme_target : 
Error<
   "function using ZA state requires 'sme'">;
 def err_sme_definition_using_zt0_in_non_sme2_target : Error<
   "function using ZT0 state requires 'sme2'">;
+def warn_sme_streaming_caller_pass_args_to_non_streaming : Warning<
+  "streaming caller passes a VL-dependent argument to non-streaming callee, "
+  "the streaming and non-streaming vector lengths may be different">,
+  InGroup;
+def warn_sme_non_streaming_callee_returns_to_streaming : Warning<
+  "non-streaming callee returns a VL-dependent value to streaming caller, "
+  "the streaming and non-streaming vector lengths may be different">,
+  InGroup;
+def warn_sme_non_streaming_caller_pass_args_to_streaming : Warning<
+  "non-streaming caller passes a VL-dependent argument to streaming callee, "
+  "the streaming and non-streaming vector lengths may be different">,
+  InGroup;
+def warn_sme_non_streaming_caller_returns_to_streaming : Warning<
+  "non-streaming callee returns a VL-dependent value to streaming caller, "
+  "the streaming and non-streaming vector lengths may be different">,
+  InGroup;
+def warn_sme_locally_streaming_has_vl_args : Warning<
+  "non-streaming callee receives a VL-dependent argument and the callee has an 
arm_locally_streaming attribute, "
+  "the streaming and non-streaming vector lengths may be different">,
+  InGroup;
+def warn_sme_locally_streaming_returns_vl : Warning<
+  "non-streaming callee returns a VL-dependent value and the callee has an 
arm_locally_streaming attribute, "
+  "the streaming and non-streaming vector lengths may be different">,
+  InGroup;
 def err_conflicting_attributes_arm_state : Error<
   "conflicting attributes for state '%0'">;
 def err_unknown_arm_state : Error<
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 502b24bcdf8b42..e668a45c69e5f9 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -7480,6 +7480,7 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
 // For variadic functions, we may have more args than parameters.
 // For some K functions, we may have less args than parameters.
 const auto N = std::min(Proto->getNumParams(), Args.size());
+bool AnyScalableArgs = false;
 for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
   // Args[ArgIdx] can be null in malformed code.
   if (const Expr *Arg = Args[ArgIdx]) {
@@ -7493,6 +7494,8 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
   checkAIXMemberAlignment((Arg->getExprLoc()), Arg);
 
 QualType ParamTy = Proto->getParamType(ArgIdx);
+if (ParamTy->isSizelessVectorType())
+  AnyScalableArgs = true;
 QualType ArgTy = Arg->getType();
 CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1),
   ArgTy, ParamTy);
@@ -7513,6 +7516,45 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
   }
 }
 
+auto *CallerFD = dyn_cast(CurContext);
+if (FD && CallerFD && Context.getTargetInfo().hasFeature("sme") &&
+!FD->getBuiltinID()) {
+  // If the callee has an AArch64 SME __arm_locally_streaming attribute
+  // warn if this function returns VL-based value or pass any such 
argument,
+  // the streaming and non-streaming vector lengths may be different.
+  ArmStreamingType CalleeFnType = getArmStreamingFnType(FD);
+  ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD);
+  if (FD->hasAttr() &&
+  CallerFnType != ArmStreaming) {
+if (AnyScalableArgs)
+  Diag(Loc, diag::warn_sme_locally_streaming_has_vl_args);
+if (FD->getReturnType()->isSizelessVectorType())
+  Diag(Loc, 

[clang] [clang][dataflow] Add support for `CXXRewrittenBinaryOperator`. (PR #81086)

2024-02-07 Thread via cfe-commits

https://github.com/martinboehme closed 
https://github.com/llvm/llvm-project/pull/81086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] a446c9b - [clang][dataflow] Add support for `CXXRewrittenBinaryOperator`. (#81086)

2024-02-07 Thread via cfe-commits

Author: martinboehme
Date: 2024-02-08T08:38:35+01:00
New Revision: a446c9bf69b4797da329977366ca62e55a429a90

URL: 
https://github.com/llvm/llvm-project/commit/a446c9bf69b4797da329977366ca62e55a429a90
DIFF: 
https://github.com/llvm/llvm-project/commit/a446c9bf69b4797da329977366ca62e55a429a90.diff

LOG: [clang][dataflow] Add support for `CXXRewrittenBinaryOperator`. (#81086)

This occurs in rewritten candidates for binary operators (a C++20
feature).

The patch modifies UncheckedOptionalAccessModelTest to run in C++20 mode
(as
well as C++17 mode, as before) and to use rewritten candidates. The
modified
test fails without the newly added support for
`CXXRewrittenBinaryOperator`.

Added: 


Modified: 
clang/lib/Analysis/FlowSensitive/Transfer.cpp
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Removed: 




diff  --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp 
b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index bb3aec763c29ca..a098471d0ee905 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -545,6 +545,10 @@ class TransferVisitor : public 
ConstStmtVisitor {
 VisitCallExpr(S);
   }
 
+  void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) {
+propagateValue(*RBO->getSemanticForm(), *RBO, Env);
+  }
+
   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
 if (S->getCastKind() == CK_ConstructorConversion) {
   const Expr *SubExpr = S->getSubExpr();

diff  --git 
a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
index 73fb4063d92be9..b6e4973fd7cb2b 100644
--- 
a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ 
b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -770,12 +770,17 @@ constexpr bool operator!=(const optional , const 
optional );
 
 template 
 constexpr bool operator==(const optional , nullopt_t);
+
+// C++20 and later do not define the following overloads because they are
+// provided by rewritten candidates instead.
+#if __cplusplus < 202002L
 template 
 constexpr bool operator==(nullopt_t, const optional );
 template 
 constexpr bool operator!=(const optional , nullopt_t);
 template 
 constexpr bool operator!=(nullopt_t, const optional );
+#endif  // __cplusplus < 202002L
 
 template 
 constexpr bool operator==(const optional , const U );
@@ -1289,6 +1294,15 @@ class UncheckedOptionalAccessTest
   template 
   void ExpectDiagnosticsFor(std::string SourceCode,
 FuncDeclMatcher FuncMatcher) {
+// Run in C++17 and C++20 mode to cover 
diff erences in the AST between modes
+// (e.g. C++20 can contain `CXXRewrittenBinaryOperator`).
+for (const char *CxxMode : {"-std=c++17", "-std=c++20"})
+  ExpectDiagnosticsFor(SourceCode, FuncMatcher, CxxMode);
+  }
+
+  template 
+  void ExpectDiagnosticsFor(std::string SourceCode, FuncDeclMatcher 
FuncMatcher,
+const char *CxxMode) {
 ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
 ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
 
@@ -1332,7 +1346,7 @@ class UncheckedOptionalAccessTest
   llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
 })
 .withASTBuildArgs(
-{"-fsyntax-only", "-std=c++17", "-Wno-undefined-inline"})
+{"-fsyntax-only", CxxMode, "-Wno-undefined-inline"})
 .withASTBuildVirtualMappedFiles(
 tooling::FileContentMappings(Headers.begin(), Headers.end())),
 /*VerifyResults=*/[](



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] require template arg list after template kw (PR #80801)

2024-02-07 Thread Erick Velez via cfe-commits

https://github.com/evelez7 updated 
https://github.com/llvm/llvm-project/pull/80801

>From fd07c0a15eb45c3e7eb400026ea7702ae909a11e Mon Sep 17 00:00:00 2001
From: Erick Velez 
Date: Mon, 5 Feb 2024 21:26:07 -0800
Subject: [PATCH 1/3] [clang] require template arg list after template kw

Require a template argument list after an identifier prefixed by the
template keyword. Introduced by CWG 96.

Fixes #53095
---
 .../clang/Basic/DiagnosticParseKinds.td   |  3 ++
 clang/lib/Parse/ParseExprCXX.cpp  | 23 
 clang/test/CXX/drs/dr0xx.cpp  |  2 +-
 .../cxx1y-variable-templates_in_class.cpp |  6 ++--
 .../test/SemaCXX/template-specialization.cpp  |  2 +-
 clang/test/SemaTemplate/dependent-names.cpp   |  6 ++--
 clang/test/SemaTemplate/template-id-expr.cpp  | 36 +--
 .../SemaTemplate/template-id-printing.cpp | 13 ---
 8 files changed, 46 insertions(+), 45 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index a30ab27566ec3e..159600f3e26dc0 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -868,6 +868,9 @@ def err_requires_expr_in_simple_requirement : Error<
   "requires expression in requirement body; did "
   "you intend to place it in a nested requirement? (add another 'requires' "
   "before the expression)">;
+def err_missing_template_arg_list_after_template_kw : Error<
+  "a template argument list is expected after a name prefixed by the template "
+  "keyword">;
 
 def err_missing_dependent_template_keyword : Error<
   "use 'template' keyword to treat '%0' as a dependent template name">;
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index fd262ff31e661a..b3a1a6f6cf80d0 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/TemplateKinds.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Parse/ParseDiagnostic.h"
@@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec , 
ParsedType ObjectType,
   SS, ObjectType, ObjectHadErrors,
   TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc,
   EnteringContext, Result, TemplateSpecified);
-else if (TemplateSpecified &&
- Actions.ActOnTemplateName(
- getCurScope(), SS, *TemplateKWLoc, Result, ObjectType,
- EnteringContext, Template,
- /*AllowInjectedClassName*/ true) == TNK_Non_template)
-  return true;
 
+if (TemplateSpecified) {
+  TemplateNameKind TNK =
+  Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result,
+ObjectType, EnteringContext, Template,
+/*AllowInjectedClassName*/ true);
+  if (TNK == TNK_Non_template)
+return true;
+
+  // C++ [template.names]p6
+  // A name prefixed by the keyword template shall be followed by a 
template
+  // argument list or refer to a class template or an alias template.
+  if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name 
||
+   TNK == TNK_Var_template) &&
+  !Tok.is(tok::less))
+Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw);
+}
 return false;
   }
 
diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp
index 5959f0a0c8dd65..127d45be5bda97 100644
--- a/clang/test/CXX/drs/dr0xx.cpp
+++ b/clang/test/CXX/drs/dr0xx.cpp
@@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no
 // FIXME: This is ill-formed, because 'f' is not a template-id and does not
 // name a class template.
 // FIXME: What about alias templates?
-int k2 = a.template f(1);
+int k2 = a.template f(1); // expected-error {{a template argument list is 
expected after a name prefixed by the template keyword}}
 A::template S s;
 B b;
   }
diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp 
b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index af121a8b75d512..37dbe0b212eb6a 100644
--- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -384,16 +384,16 @@ namespace dependent_static_var_template {
   struct A {
 template static int n; // expected-note 2{{here}}
   };
-  int  = A::template n; // expected-error {{use of variable template 'n' 
requires template arguments}}
+  int  = A::template n; // expected-error {{use of variable template 'n' 
requires template arguments}} expected-error {{a template argument list is 
expected after a name prefixed by the template keyword}}
 
   template
-  int () { return T::template n; } // 

[clang] [llvm] [AMDGPU] Introduce GFX9/10.1/10.3/11 Generic Targets (PR #76955)

2024-02-07 Thread Pierre van Houtryve via cfe-commits

Pierre-vh wrote:

@t-tye Can you please approve then? Otherwise the diff still shows a red 
"Changes requested" warning :) Thanks
@arsenm Please also approve if there are no more comments

https://github.com/llvm/llvm-project/pull/76955
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix a regression in dumping the config (PR #80628)

2024-02-07 Thread via cfe-commits

llvmbot wrote:

/pull-request llvm/llvm-project#81096

https://github.com/llvm/llvm-project/pull/80628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix a regression in dumping the config (PR #80628)

2024-02-07 Thread Owen Pan via cfe-commits

owenca wrote:

/cherry-pick 8f6e13e6da84

https://github.com/llvm/llvm-project/pull/80628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix a regression in dumping the config (PR #80628)

2024-02-07 Thread Owen Pan via cfe-commits

https://github.com/owenca milestoned 
https://github.com/llvm/llvm-project/pull/80628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] GH70601 (PR #81095)

2024-02-07 Thread Younan Zhang via cfe-commits

https://github.com/zyn0217 created 
https://github.com/llvm/llvm-project/pull/81095

Testing libc++'s CI.

>From 906fbf5b0796a85bf54028dfaa8e6343ea441a51 Mon Sep 17 00:00:00 2001
From: Younan Zhang 
Date: Thu, 8 Feb 2024 15:07:47 +0800
Subject: [PATCH] GH70601

---
 clang/include/clang/Sema/Sema.h   | 15 ++--
 clang/lib/Sema/SemaTemplate.cpp   | 83 ++-
 clang/lib/Sema/SemaTemplateInstantiate.cpp| 21 +++--
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 12 ++-
 clang/test/SemaTemplate/concepts-lambda.cpp   | 19 +
 5 files changed, 92 insertions(+), 58 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 3c26003b5bda7..afc74f1a64551 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8343,12 +8343,14 @@ class Sema final {
 ConceptDecl *NamedConcept,
 const TemplateArgumentListInfo *TemplateArgs,
 TemplateTypeParmDecl *ConstrainedParameter,
-SourceLocation EllipsisLoc);
+SourceLocation EllipsisLoc,
+bool EvaluateConstraint = true);
 
   bool AttachTypeConstraint(AutoTypeLoc TL,
 NonTypeTemplateParmDecl *NewConstrainedParm,
 NonTypeTemplateParmDecl *OrigConstrainedParm,
-SourceLocation EllipsisLoc);
+SourceLocation EllipsisLoc,
+bool EvaluateConstraint = true);
 
   bool RequireStructuralType(QualType T, SourceLocation Loc);
 
@@ -8479,11 +8481,11 @@ class Sema final {
 const TemplateArgumentListInfo *TemplateArgs);
 
   ExprResult
-  CheckConceptTemplateId(const CXXScopeSpec ,
- SourceLocation TemplateKWLoc,
+  CheckConceptTemplateId(const CXXScopeSpec , SourceLocation TemplateKWLoc,
  const DeclarationNameInfo ,
  NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
- const TemplateArgumentListInfo *TemplateArgs);
+ const TemplateArgumentListInfo *TemplateArgs,
+ bool EvaluateConstraint = true);
 
   void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
 
@@ -10518,7 +10520,8 @@ class Sema final {
 
   bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint 
*TC,
const MultiLevelTemplateArgumentList ,
-   bool EvaluateConstraint);
+   bool RebuildConstraint,
+   bool EvaluateConstraints = true);
 
   bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
   ParmVarDecl *Param);
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index cf781e0e1bf3f..9c7a936aac1d6 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1176,13 +1176,13 @@ bool Sema::BuildTypeConstraint(const CXXScopeSpec ,
   ConstrainedParameter, EllipsisLoc);
 }
 
-template
+template 
 static ExprResult formImmediatelyDeclaredConstraint(
 Sema , NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
 ConceptDecl *NamedConcept, SourceLocation LAngleLoc,
 SourceLocation RAngleLoc, QualType ConstrainedType,
 SourceLocation ParamNameLoc, ArgumentLocAppender Appender,
-SourceLocation EllipsisLoc) {
+SourceLocation EllipsisLoc, bool EvaluateConstraint) {
 
   TemplateArgumentListInfo ConstraintArgs;
   ConstraintArgs.addArgument(
@@ -1233,7 +1233,8 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS,
 ConceptDecl *NamedConcept,
 const TemplateArgumentListInfo *TemplateArgs,
 TemplateTypeParmDecl *ConstrainedParameter,
-SourceLocation EllipsisLoc) {
+SourceLocation EllipsisLoc,
+bool EvaluateConstraint) {
   // C++2a [temp.param]p4:
   // [...] If Q is of the form C, then let E' be
   // C. Otherwise, let E' be C. [...]
@@ -1243,17 +1244,17 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc 
NS,
 
   QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);
 
-  ExprResult ImmediatelyDeclaredConstraint =
-  formImmediatelyDeclaredConstraint(
-  *this, NS, NameInfo, NamedConcept,
-  TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(),
-  TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(),
-  ParamAsArgument, ConstrainedParameter->getLocation(),
-  [&] (TemplateArgumentListInfo ) {
-if (TemplateArgs)
-  for (const auto  : TemplateArgs->arguments())
- 

[clang] [llvm] Reapply "InstCombine: Introduce SimplifyDemandedUseFPClass"" (PR #74056)

2024-02-07 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw approved this pull request.

LGTM. Thanks!

https://github.com/llvm/llvm-project/pull/74056
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Rename option AlwaysBreakTemplateDeclarations (PR #81093)

2024-02-07 Thread Owen Pan via cfe-commits

https://github.com/owenca updated 
https://github.com/llvm/llvm-project/pull/81093

>From b9463c6664227edd6e579840292389909be04ab2 Mon Sep 17 00:00:00 2001
From: Owen Pan 
Date: Wed, 7 Feb 2024 22:43:15 -0800
Subject: [PATCH 1/2] [clang-format] Rename option
 AlwaysBreakTemplateDeclarations

Drop the "Always" prefix to remove the self-contradiction.
---
 clang/docs/ClangFormatStyleOptions.rst | 117 +++--
 clang/docs/tools/dump_format_style.py  |   7 ++
 clang/include/clang/Format/Format.h|   7 +-
 clang/lib/Format/Format.cpp|   6 +-
 clang/unittests/Format/ConfigParseTest.cpp |  13 +++
 5 files changed, 91 insertions(+), 59 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 0a8cc18c5b4cb5..f3da652e691451 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1659,62 +1659,8 @@ the configuration (without a prefix: ``Auto``).
 
 .. _AlwaysBreakTemplateDeclarations:
 
-**AlwaysBreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) 
:versionbadge:`clang-format 3.4` :ref:`¶ `
-  The template declaration breaking style to use.
-
-  Possible values:
-
-  * ``BTDS_Leave`` (in configuration: ``Leave``)
-Do not change the line breaking before the declaration.
-
-.. code-block:: c++
-
-   template 
-   T foo() {
-   }
-   template  T foo(int a,
-   int b) {
-   }
-
-  * ``BTDS_No`` (in configuration: ``No``)
-Do not force break before declaration.
-``PenaltyBreakTemplateDeclaration`` is taken into account.
-
-.. code-block:: c++
-
-   template  T foo() {
-   }
-   template  T foo(int a,
-   int b) {
-   }
-
-  * ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
-Force break after template declaration only when the following
-declaration spans multiple lines.
-
-.. code-block:: c++
-
-   template  T foo() {
-   }
-   template 
-   T foo(int a,
- int b) {
-   }
-
-  * ``BTDS_Yes`` (in configuration: ``Yes``)
-Always break after template declaration.
-
-.. code-block:: c++
-
-   template 
-   T foo() {
-   }
-   template 
-   T foo(int a,
- int b) {
-   }
-
-
+**AlwaysBreakTemplateDeclarations** (``deprecated``) 
:versionbadge:`clang-format 3.4` :ref:`¶ `
+  This option is renamed to ``BreakTemplateDeclarations``.
 
 .. _AttributeMacros:
 
@@ -3014,6 +2960,65 @@ the configuration (without a prefix: ``Auto``).
  string x =
  "veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString";
 
+.. _BreakTemplateDeclarations:
+
+**BreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) 
:versionbadge:`clang-format 19` :ref:`¶ `
+  The template declaration breaking style to use.
+
+  Possible values:
+
+  * ``BTDS_Leave`` (in configuration: ``Leave``)
+Do not change the line breaking before the declaration.
+
+.. code-block:: c++
+
+   template 
+   T foo() {
+   }
+   template  T foo(int a,
+   int b) {
+   }
+
+  * ``BTDS_No`` (in configuration: ``No``)
+Do not force break before declaration.
+``PenaltyBreakTemplateDeclaration`` is taken into account.
+
+.. code-block:: c++
+
+   template  T foo() {
+   }
+   template  T foo(int a,
+   int b) {
+   }
+
+  * ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
+Force break after template declaration only when the following
+declaration spans multiple lines.
+
+.. code-block:: c++
+
+   template  T foo() {
+   }
+   template 
+   T foo(int a,
+ int b) {
+   }
+
+  * ``BTDS_Yes`` (in configuration: ``Yes``)
+Always break after template declaration.
+
+.. code-block:: c++
+
+   template 
+   T foo() {
+   }
+   template 
+   T foo(int a,
+ int b) {
+   }
+
+
+
 .. _ColumnLimit:
 
 **ColumnLimit** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`¶ 
`
diff --git a/clang/docs/tools/dump_format_style.py 
b/clang/docs/tools/dump_format_style.py
index e41891f07de2e3..203e9450ed3767 100755
--- a/clang/docs/tools/dump_format_style.py
+++ b/clang/docs/tools/dump_format_style.py
@@ -308,6 +308,7 @@ class State:
 enum = None
 nested_struct = None
 version = None
+deprecated = False
 
 for line in self.header:
 self.lineno += 1
@@ -327,6 +328,8 @@ class State:
 match = re.match(r"/// 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,589 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: -p --function-signature
+; RUN: opt -S --passes=expand-variadics < %s | FileCheck %s
+target datalayout = 
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; The types show the call frames
+; CHECK: %single_i32.vararg = type <{ i32 }>
+; CHECK: %single_double.vararg = type <{ double }>
+; CHECK: %single_v4f32.vararg = type <{ <4 x float> }>
+; CHECK: %single_v8f32.vararg = type <{ <8 x float> }>
+; CHECK: %single_v16f32.vararg = type <{ <16 x float> }>
+; CHECK: %single_v32f32.vararg = type <{ <32 x float> }>
+; CHECK: %i32_double.vararg = type <{ i32, [4 x i8], double }>
+; CHECK: %double_i32.vararg = type <{ double, i32 }>
+; CHECK: %i32_v4f32.vararg = type <{ i32, [12 x i8], <4 x float> }>
+; CHECK: %v4f32_i32.vararg = type <{ <4 x float>, i32 }>
+; CHECK: %i32_v8f32.vararg = type <{ i32, [28 x i8], <8 x float> }>
+; CHECK: %v8f32_i32.vararg = type <{ <8 x float>, i32 }>
+; CHECK: %i32_v16f32.vararg = type <{ i32, [60 x i8], <16 x float> }>
+; CHECK: %v16f32_i32.vararg = type <{ <16 x float>, i32 }>
+; CHECK: %i32_v32f32.vararg = type <{ i32, [124 x i8], <32 x float> }>
+; CHECK: %v32f32_i32.vararg = type <{ <32 x float>, i32 }>
+
+%struct.__va_list_tag = type { i32, i32, ptr, ptr }
+%struct.libcS = type { i8, i16, i32, i64, float, double }
+
+define dso_local void @codegen_for_copy(ptr noundef %x) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@codegen_for_copy(ptr noundef %x) 
local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:%cp = alloca [1 x %struct.__va_list_tag], align 16
+; CHECK-NEXT:call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %cp) #6
+; CHECK-NEXT:call void @llvm.va_copy(ptr nonnull %cp, ptr %x)
+; CHECK-NEXT:call void @wrapped(ptr noundef nonnull %cp) #7
+; CHECK-NEXT:call void @llvm.va_end(ptr %cp)
+; CHECK-NEXT:call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %cp) #6
+; CHECK-NEXT:ret void
+;
+entry:
+  %cp = alloca [1 x %struct.__va_list_tag], align 16
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %cp) #5
+  call void @llvm.va_copy(ptr nonnull %cp, ptr %x)
+  call void @wrapped(ptr noundef nonnull %cp) #6
+  call void @llvm.va_end(ptr %cp)
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %cp) #5
+  ret void
+}
+
+declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+
+declare void @llvm.va_copy(ptr, ptr) #2
+
+declare void @wrapped(ptr noundef) local_unnamed_addr #3
+
+declare void @llvm.va_end(ptr) #2
+
+declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
+
+define dso_local void @vararg(...) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@vararg(...) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:%va = alloca [1 x %struct.__va_list_tag], align 16
+; CHECK-NEXT:call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %va) #6
+; CHECK-NEXT:call void @llvm.va_start(ptr nonnull %va)
+; CHECK-NEXT:call void @wrapped(ptr noundef nonnull %va) #7
+; CHECK-NEXT:call void @llvm.va_end(ptr %va)
+; CHECK-NEXT:call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %va) #6
+; CHECK-NEXT:ret void
+;
+entry:
+  %va = alloca [1 x %struct.__va_list_tag], align 16
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %va) #5
+  call void @llvm.va_start(ptr nonnull %va)
+  call void @wrapped(ptr noundef nonnull %va) #6
+  call void @llvm.va_end(ptr %va)
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %va) #5
+  ret void
+}
+
+declare void @llvm.va_start(ptr) #2
+
+define dso_local void @single_i32(i32 noundef %x) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@single_i32(i32 noundef %x) local_unnamed_addr 
#0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:%vararg_buffer = alloca %single_i32.vararg, align 8
+; CHECK-NEXT:%0 = getelementptr inbounds %single_i32.vararg, ptr 
%vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:store i32 %x, ptr %0, align 4
+; CHECK-NEXT:%va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:%gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr 
}], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:%fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr 
}], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:%overfow_arg_area = getelementptr inbounds [1 x { i32, i32, 
ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:%reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, 
ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:ret void
+;
+entry:
+  tail 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,589 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: -p --function-signature
+; RUN: opt -S --passes=expand-variadics < %s | FileCheck %s
+target datalayout = 
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; The types show the call frames
+; CHECK: %single_i32.vararg = type <{ i32 }>
+; CHECK: %single_double.vararg = type <{ double }>
+; CHECK: %single_v4f32.vararg = type <{ <4 x float> }>
+; CHECK: %single_v8f32.vararg = type <{ <8 x float> }>
+; CHECK: %single_v16f32.vararg = type <{ <16 x float> }>
+; CHECK: %single_v32f32.vararg = type <{ <32 x float> }>
+; CHECK: %i32_double.vararg = type <{ i32, [4 x i8], double }>
+; CHECK: %double_i32.vararg = type <{ double, i32 }>
+; CHECK: %i32_v4f32.vararg = type <{ i32, [12 x i8], <4 x float> }>
+; CHECK: %v4f32_i32.vararg = type <{ <4 x float>, i32 }>
+; CHECK: %i32_v8f32.vararg = type <{ i32, [28 x i8], <8 x float> }>
+; CHECK: %v8f32_i32.vararg = type <{ <8 x float>, i32 }>
+; CHECK: %i32_v16f32.vararg = type <{ i32, [60 x i8], <16 x float> }>
+; CHECK: %v16f32_i32.vararg = type <{ <16 x float>, i32 }>
+; CHECK: %i32_v32f32.vararg = type <{ i32, [124 x i8], <32 x float> }>
+; CHECK: %v32f32_i32.vararg = type <{ <32 x float>, i32 }>
+
+%struct.__va_list_tag = type { i32, i32, ptr, ptr }
+%struct.libcS = type { i8, i16, i32, i64, float, double }
+
+define dso_local void @codegen_for_copy(ptr noundef %x) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@codegen_for_copy(ptr noundef %x) 
local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:%cp = alloca [1 x %struct.__va_list_tag], align 16
+; CHECK-NEXT:call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %cp) #6
+; CHECK-NEXT:call void @llvm.va_copy(ptr nonnull %cp, ptr %x)
+; CHECK-NEXT:call void @wrapped(ptr noundef nonnull %cp) #7
+; CHECK-NEXT:call void @llvm.va_end(ptr %cp)
+; CHECK-NEXT:call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %cp) #6
+; CHECK-NEXT:ret void
+;
+entry:
+  %cp = alloca [1 x %struct.__va_list_tag], align 16
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %cp) #5
+  call void @llvm.va_copy(ptr nonnull %cp, ptr %x)
+  call void @wrapped(ptr noundef nonnull %cp) #6
+  call void @llvm.va_end(ptr %cp)
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %cp) #5
+  ret void
+}
+
+declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+
+declare void @llvm.va_copy(ptr, ptr) #2
+
+declare void @wrapped(ptr noundef) local_unnamed_addr #3
+
+declare void @llvm.va_end(ptr) #2
+
+declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
+
+define dso_local void @vararg(...) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@vararg(...) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:%va = alloca [1 x %struct.__va_list_tag], align 16
+; CHECK-NEXT:call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %va) #6
+; CHECK-NEXT:call void @llvm.va_start(ptr nonnull %va)
+; CHECK-NEXT:call void @wrapped(ptr noundef nonnull %va) #7
+; CHECK-NEXT:call void @llvm.va_end(ptr %va)
+; CHECK-NEXT:call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %va) #6
+; CHECK-NEXT:ret void
+;
+entry:
+  %va = alloca [1 x %struct.__va_list_tag], align 16
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %va) #5
+  call void @llvm.va_start(ptr nonnull %va)
+  call void @wrapped(ptr noundef nonnull %va) #6
+  call void @llvm.va_end(ptr %va)
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %va) #5
+  ret void
+}
+
+declare void @llvm.va_start(ptr) #2
+
+define dso_local void @single_i32(i32 noundef %x) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@single_i32(i32 noundef %x) local_unnamed_addr 
#0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:%vararg_buffer = alloca %single_i32.vararg, align 8
+; CHECK-NEXT:%0 = getelementptr inbounds %single_i32.vararg, ptr 
%vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:store i32 %x, ptr %0, align 4
+; CHECK-NEXT:%va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:%gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr 
}], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:%fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr 
}], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:%overfow_arg_area = getelementptr inbounds [1 x { i32, i32, 
ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:%reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, 
ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:ret void
+;
+entry:
+  tail 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,589 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: -p --function-signature
+; RUN: opt -S --passes=expand-variadics < %s | FileCheck %s
+target datalayout = 
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; The types show the call frames
+; CHECK: %single_i32.vararg = type <{ i32 }>
+; CHECK: %single_double.vararg = type <{ double }>
+; CHECK: %single_v4f32.vararg = type <{ <4 x float> }>
+; CHECK: %single_v8f32.vararg = type <{ <8 x float> }>
+; CHECK: %single_v16f32.vararg = type <{ <16 x float> }>
+; CHECK: %single_v32f32.vararg = type <{ <32 x float> }>
+; CHECK: %i32_double.vararg = type <{ i32, [4 x i8], double }>
+; CHECK: %double_i32.vararg = type <{ double, i32 }>
+; CHECK: %i32_v4f32.vararg = type <{ i32, [12 x i8], <4 x float> }>
+; CHECK: %v4f32_i32.vararg = type <{ <4 x float>, i32 }>
+; CHECK: %i32_v8f32.vararg = type <{ i32, [28 x i8], <8 x float> }>
+; CHECK: %v8f32_i32.vararg = type <{ <8 x float>, i32 }>
+; CHECK: %i32_v16f32.vararg = type <{ i32, [60 x i8], <16 x float> }>
+; CHECK: %v16f32_i32.vararg = type <{ <16 x float>, i32 }>
+; CHECK: %i32_v32f32.vararg = type <{ i32, [124 x i8], <32 x float> }>
+; CHECK: %v32f32_i32.vararg = type <{ <32 x float>, i32 }>
+
+%struct.__va_list_tag = type { i32, i32, ptr, ptr }
+%struct.libcS = type { i8, i16, i32, i64, float, double }
+
+define dso_local void @codegen_for_copy(ptr noundef %x) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@codegen_for_copy(ptr noundef %x) 
local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:%cp = alloca [1 x %struct.__va_list_tag], align 16
+; CHECK-NEXT:call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %cp) #6
+; CHECK-NEXT:call void @llvm.va_copy(ptr nonnull %cp, ptr %x)
+; CHECK-NEXT:call void @wrapped(ptr noundef nonnull %cp) #7
+; CHECK-NEXT:call void @llvm.va_end(ptr %cp)
+; CHECK-NEXT:call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %cp) #6
+; CHECK-NEXT:ret void
+;
+entry:
+  %cp = alloca [1 x %struct.__va_list_tag], align 16
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %cp) #5
+  call void @llvm.va_copy(ptr nonnull %cp, ptr %x)
+  call void @wrapped(ptr noundef nonnull %cp) #6
+  call void @llvm.va_end(ptr %cp)
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %cp) #5
+  ret void
+}
+
+declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+
+declare void @llvm.va_copy(ptr, ptr) #2
+
+declare void @wrapped(ptr noundef) local_unnamed_addr #3
+
+declare void @llvm.va_end(ptr) #2
+
+declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
+
+define dso_local void @vararg(...) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@vararg(...) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:%va = alloca [1 x %struct.__va_list_tag], align 16
+; CHECK-NEXT:call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %va) #6
+; CHECK-NEXT:call void @llvm.va_start(ptr nonnull %va)
+; CHECK-NEXT:call void @wrapped(ptr noundef nonnull %va) #7
+; CHECK-NEXT:call void @llvm.va_end(ptr %va)
+; CHECK-NEXT:call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %va) #6
+; CHECK-NEXT:ret void
+;
+entry:
+  %va = alloca [1 x %struct.__va_list_tag], align 16
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %va) #5
+  call void @llvm.va_start(ptr nonnull %va)
+  call void @wrapped(ptr noundef nonnull %va) #6
+  call void @llvm.va_end(ptr %va)
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %va) #5
+  ret void
+}
+
+declare void @llvm.va_start(ptr) #2
+
+define dso_local void @single_i32(i32 noundef %x) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@single_i32(i32 noundef %x) local_unnamed_addr 
#0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:%vararg_buffer = alloca %single_i32.vararg, align 8
+; CHECK-NEXT:%0 = getelementptr inbounds %single_i32.vararg, ptr 
%vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:store i32 %x, ptr %0, align 4
+; CHECK-NEXT:%va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:%gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr 
}], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:%fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr 
}], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:%overfow_arg_area = getelementptr inbounds [1 x { i32, i32, 
ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:%reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, 
ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:ret void
+;
+entry:
+  tail 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);

arsenm wrote:

I'd expect this to use 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [clang-format] Rename option AlwaysBreakTemplateDeclarations (PR #81093)

2024-02-07 Thread via cfe-commits

github-actions[bot] wrote:




:warning: Python code formatter, darker found issues in your code. :warning:



You can test this locally with the following command:


``bash
darker --check --diff -r 
8f6e13e6da84510c8321717860fd506e12118514...b9463c6664227edd6e579840292389909be04ab2
 clang/docs/tools/dump_format_style.py
``





View the diff from darker here.


``diff
--- dump_format_style.py2024-02-08 06:43:15.00 +
+++ dump_format_style.py2024-02-08 06:50:18.679534 +
@@ -346,11 +346,11 @@
 line = line[len(prefix) :]
 state = State.InStruct
 field_type, field_name = re.match(
 r"([<>:\w(,\s)]+)\s+(\w+);", line
 ).groups()
-if (deprecated):
+if deprecated:
 field_type = "deprecated"
 deprecated = False
 
 if not version:
 self.__warning(f"missing version for {field_name}", 
line)

``




https://github.com/llvm/llvm-project/pull/81093
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Rename option AlwaysBreakTemplateDeclarations (PR #81093)

2024-02-07 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-format

Author: Owen Pan (owenca)


Changes

Drop the "Always" prefix to remove the self-contradiction.

---
Full diff: https://github.com/llvm/llvm-project/pull/81093.diff


5 Files Affected:

- (modified) clang/docs/ClangFormatStyleOptions.rst (+61-56) 
- (modified) clang/docs/tools/dump_format_style.py (+7) 
- (modified) clang/include/clang/Format/Format.h (+6-1) 
- (modified) clang/lib/Format/Format.cpp (+4-2) 
- (modified) clang/unittests/Format/ConfigParseTest.cpp (+13) 


``diff
diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 0a8cc18c5b4cb5..f3da652e691451 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1659,62 +1659,8 @@ the configuration (without a prefix: ``Auto``).
 
 .. _AlwaysBreakTemplateDeclarations:
 
-**AlwaysBreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) 
:versionbadge:`clang-format 3.4` :ref:`¶ `
-  The template declaration breaking style to use.
-
-  Possible values:
-
-  * ``BTDS_Leave`` (in configuration: ``Leave``)
-Do not change the line breaking before the declaration.
-
-.. code-block:: c++
-
-   template 
-   T foo() {
-   }
-   template  T foo(int a,
-   int b) {
-   }
-
-  * ``BTDS_No`` (in configuration: ``No``)
-Do not force break before declaration.
-``PenaltyBreakTemplateDeclaration`` is taken into account.
-
-.. code-block:: c++
-
-   template  T foo() {
-   }
-   template  T foo(int a,
-   int b) {
-   }
-
-  * ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
-Force break after template declaration only when the following
-declaration spans multiple lines.
-
-.. code-block:: c++
-
-   template  T foo() {
-   }
-   template 
-   T foo(int a,
- int b) {
-   }
-
-  * ``BTDS_Yes`` (in configuration: ``Yes``)
-Always break after template declaration.
-
-.. code-block:: c++
-
-   template 
-   T foo() {
-   }
-   template 
-   T foo(int a,
- int b) {
-   }
-
-
+**AlwaysBreakTemplateDeclarations** (``deprecated``) 
:versionbadge:`clang-format 3.4` :ref:`¶ `
+  This option is renamed to ``BreakTemplateDeclarations``.
 
 .. _AttributeMacros:
 
@@ -3014,6 +2960,65 @@ the configuration (without a prefix: ``Auto``).
  string x =
  "veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString";
 
+.. _BreakTemplateDeclarations:
+
+**BreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) 
:versionbadge:`clang-format 19` :ref:`¶ `
+  The template declaration breaking style to use.
+
+  Possible values:
+
+  * ``BTDS_Leave`` (in configuration: ``Leave``)
+Do not change the line breaking before the declaration.
+
+.. code-block:: c++
+
+   template 
+   T foo() {
+   }
+   template  T foo(int a,
+   int b) {
+   }
+
+  * ``BTDS_No`` (in configuration: ``No``)
+Do not force break before declaration.
+``PenaltyBreakTemplateDeclaration`` is taken into account.
+
+.. code-block:: c++
+
+   template  T foo() {
+   }
+   template  T foo(int a,
+   int b) {
+   }
+
+  * ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
+Force break after template declaration only when the following
+declaration spans multiple lines.
+
+.. code-block:: c++
+
+   template  T foo() {
+   }
+   template 
+   T foo(int a,
+ int b) {
+   }
+
+  * ``BTDS_Yes`` (in configuration: ``Yes``)
+Always break after template declaration.
+
+.. code-block:: c++
+
+   template 
+   T foo() {
+   }
+   template 
+   T foo(int a,
+ int b) {
+   }
+
+
+
 .. _ColumnLimit:
 
 **ColumnLimit** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`¶ 
`
diff --git a/clang/docs/tools/dump_format_style.py 
b/clang/docs/tools/dump_format_style.py
index e41891f07de2e3..203e9450ed3767 100755
--- a/clang/docs/tools/dump_format_style.py
+++ b/clang/docs/tools/dump_format_style.py
@@ -308,6 +308,7 @@ class State:
 enum = None
 nested_struct = None
 version = None
+deprecated = False
 
 for line in self.header:
 self.lineno += 1
@@ -327,6 +328,8 @@ class State:
 match = re.match(r"/// \\version\s*(?P[0-9.]+)*", 
line)
 if match:
 version = match.group("version")
+elif line.startswith("/// 

[clang] [clang-format] Rename option AlwaysBreakTemplateDeclarations (PR #81093)

2024-02-07 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Owen Pan (owenca)


Changes

Drop the "Always" prefix to remove the self-contradiction.

---
Full diff: https://github.com/llvm/llvm-project/pull/81093.diff


5 Files Affected:

- (modified) clang/docs/ClangFormatStyleOptions.rst (+61-56) 
- (modified) clang/docs/tools/dump_format_style.py (+7) 
- (modified) clang/include/clang/Format/Format.h (+6-1) 
- (modified) clang/lib/Format/Format.cpp (+4-2) 
- (modified) clang/unittests/Format/ConfigParseTest.cpp (+13) 


``diff
diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 0a8cc18c5b4cb5..f3da652e691451 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1659,62 +1659,8 @@ the configuration (without a prefix: ``Auto``).
 
 .. _AlwaysBreakTemplateDeclarations:
 
-**AlwaysBreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) 
:versionbadge:`clang-format 3.4` :ref:`¶ `
-  The template declaration breaking style to use.
-
-  Possible values:
-
-  * ``BTDS_Leave`` (in configuration: ``Leave``)
-Do not change the line breaking before the declaration.
-
-.. code-block:: c++
-
-   template 
-   T foo() {
-   }
-   template  T foo(int a,
-   int b) {
-   }
-
-  * ``BTDS_No`` (in configuration: ``No``)
-Do not force break before declaration.
-``PenaltyBreakTemplateDeclaration`` is taken into account.
-
-.. code-block:: c++
-
-   template  T foo() {
-   }
-   template  T foo(int a,
-   int b) {
-   }
-
-  * ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
-Force break after template declaration only when the following
-declaration spans multiple lines.
-
-.. code-block:: c++
-
-   template  T foo() {
-   }
-   template 
-   T foo(int a,
- int b) {
-   }
-
-  * ``BTDS_Yes`` (in configuration: ``Yes``)
-Always break after template declaration.
-
-.. code-block:: c++
-
-   template 
-   T foo() {
-   }
-   template 
-   T foo(int a,
- int b) {
-   }
-
-
+**AlwaysBreakTemplateDeclarations** (``deprecated``) 
:versionbadge:`clang-format 3.4` :ref:`¶ `
+  This option is renamed to ``BreakTemplateDeclarations``.
 
 .. _AttributeMacros:
 
@@ -3014,6 +2960,65 @@ the configuration (without a prefix: ``Auto``).
  string x =
  "veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString";
 
+.. _BreakTemplateDeclarations:
+
+**BreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) 
:versionbadge:`clang-format 19` :ref:`¶ `
+  The template declaration breaking style to use.
+
+  Possible values:
+
+  * ``BTDS_Leave`` (in configuration: ``Leave``)
+Do not change the line breaking before the declaration.
+
+.. code-block:: c++
+
+   template 
+   T foo() {
+   }
+   template  T foo(int a,
+   int b) {
+   }
+
+  * ``BTDS_No`` (in configuration: ``No``)
+Do not force break before declaration.
+``PenaltyBreakTemplateDeclaration`` is taken into account.
+
+.. code-block:: c++
+
+   template  T foo() {
+   }
+   template  T foo(int a,
+   int b) {
+   }
+
+  * ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
+Force break after template declaration only when the following
+declaration spans multiple lines.
+
+.. code-block:: c++
+
+   template  T foo() {
+   }
+   template 
+   T foo(int a,
+ int b) {
+   }
+
+  * ``BTDS_Yes`` (in configuration: ``Yes``)
+Always break after template declaration.
+
+.. code-block:: c++
+
+   template 
+   T foo() {
+   }
+   template 
+   T foo(int a,
+ int b) {
+   }
+
+
+
 .. _ColumnLimit:
 
 **ColumnLimit** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`¶ 
`
diff --git a/clang/docs/tools/dump_format_style.py 
b/clang/docs/tools/dump_format_style.py
index e41891f07de2e3..203e9450ed3767 100755
--- a/clang/docs/tools/dump_format_style.py
+++ b/clang/docs/tools/dump_format_style.py
@@ -308,6 +308,7 @@ class State:
 enum = None
 nested_struct = None
 version = None
+deprecated = False
 
 for line in self.header:
 self.lineno += 1
@@ -327,6 +328,8 @@ class State:
 match = re.match(r"/// \\version\s*(?P[0-9.]+)*", 
line)
 if match:
 version = match.group("version")
+elif line.startswith("/// 

[clang] [clang-format] Rename option AlwaysBreakTemplateDeclarations (PR #81093)

2024-02-07 Thread Owen Pan via cfe-commits

https://github.com/owenca created 
https://github.com/llvm/llvm-project/pull/81093

Drop the "Always" prefix to remove the self-contradiction.

>From b9463c6664227edd6e579840292389909be04ab2 Mon Sep 17 00:00:00 2001
From: Owen Pan 
Date: Wed, 7 Feb 2024 22:43:15 -0800
Subject: [PATCH] [clang-format] Rename option AlwaysBreakTemplateDeclarations

Drop the "Always" prefix to remove the self-contradiction.
---
 clang/docs/ClangFormatStyleOptions.rst | 117 +++--
 clang/docs/tools/dump_format_style.py  |   7 ++
 clang/include/clang/Format/Format.h|   7 +-
 clang/lib/Format/Format.cpp|   6 +-
 clang/unittests/Format/ConfigParseTest.cpp |  13 +++
 5 files changed, 91 insertions(+), 59 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 0a8cc18c5b4cb5..f3da652e691451 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1659,62 +1659,8 @@ the configuration (without a prefix: ``Auto``).
 
 .. _AlwaysBreakTemplateDeclarations:
 
-**AlwaysBreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) 
:versionbadge:`clang-format 3.4` :ref:`¶ `
-  The template declaration breaking style to use.
-
-  Possible values:
-
-  * ``BTDS_Leave`` (in configuration: ``Leave``)
-Do not change the line breaking before the declaration.
-
-.. code-block:: c++
-
-   template 
-   T foo() {
-   }
-   template  T foo(int a,
-   int b) {
-   }
-
-  * ``BTDS_No`` (in configuration: ``No``)
-Do not force break before declaration.
-``PenaltyBreakTemplateDeclaration`` is taken into account.
-
-.. code-block:: c++
-
-   template  T foo() {
-   }
-   template  T foo(int a,
-   int b) {
-   }
-
-  * ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
-Force break after template declaration only when the following
-declaration spans multiple lines.
-
-.. code-block:: c++
-
-   template  T foo() {
-   }
-   template 
-   T foo(int a,
- int b) {
-   }
-
-  * ``BTDS_Yes`` (in configuration: ``Yes``)
-Always break after template declaration.
-
-.. code-block:: c++
-
-   template 
-   T foo() {
-   }
-   template 
-   T foo(int a,
- int b) {
-   }
-
-
+**AlwaysBreakTemplateDeclarations** (``deprecated``) 
:versionbadge:`clang-format 3.4` :ref:`¶ `
+  This option is renamed to ``BreakTemplateDeclarations``.
 
 .. _AttributeMacros:
 
@@ -3014,6 +2960,65 @@ the configuration (without a prefix: ``Auto``).
  string x =
  "veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString";
 
+.. _BreakTemplateDeclarations:
+
+**BreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) 
:versionbadge:`clang-format 19` :ref:`¶ `
+  The template declaration breaking style to use.
+
+  Possible values:
+
+  * ``BTDS_Leave`` (in configuration: ``Leave``)
+Do not change the line breaking before the declaration.
+
+.. code-block:: c++
+
+   template 
+   T foo() {
+   }
+   template  T foo(int a,
+   int b) {
+   }
+
+  * ``BTDS_No`` (in configuration: ``No``)
+Do not force break before declaration.
+``PenaltyBreakTemplateDeclaration`` is taken into account.
+
+.. code-block:: c++
+
+   template  T foo() {
+   }
+   template  T foo(int a,
+   int b) {
+   }
+
+  * ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
+Force break after template declaration only when the following
+declaration spans multiple lines.
+
+.. code-block:: c++
+
+   template  T foo() {
+   }
+   template 
+   T foo(int a,
+ int b) {
+   }
+
+  * ``BTDS_Yes`` (in configuration: ``Yes``)
+Always break after template declaration.
+
+.. code-block:: c++
+
+   template 
+   T foo() {
+   }
+   template 
+   T foo(int a,
+ int b) {
+   }
+
+
+
 .. _ColumnLimit:
 
 **ColumnLimit** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`¶ 
`
diff --git a/clang/docs/tools/dump_format_style.py 
b/clang/docs/tools/dump_format_style.py
index e41891f07de2e3..203e9450ed3767 100755
--- a/clang/docs/tools/dump_format_style.py
+++ b/clang/docs/tools/dump_format_style.py
@@ -308,6 +308,7 @@ class State:
 enum = None
 nested_struct = None
 version = None
+deprecated = False
 
 for line in self.header:
 self.lineno += 1
@@ -327,6 +328,8 @@ class State:

[clang] [llvm] Reapply "InstCombine: Introduce SimplifyDemandedUseFPClass"" (PR #74056)

2024-02-07 Thread Yingwei Zheng via cfe-commits


@@ -1877,3 +1877,139 @@ Value 
*InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
 
   return MadeChange ? I : nullptr;
 }
+
+/// For floating-point classes that resolve to a single bit pattern, return 
that
+/// value.
+static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
+  switch (Mask) {
+  case fcPosZero:
+return ConstantFP::getZero(Ty);
+  case fcNegZero:
+return ConstantFP::getZero(Ty, true);
+  case fcPosInf:
+return ConstantFP::getInfinity(Ty);
+  case fcNegInf:
+return ConstantFP::getInfinity(Ty, true);
+  case fcNone:
+return PoisonValue::get(Ty);
+  default:
+return nullptr;
+  }
+}
+
+Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
+Value *V, const FPClassTest DemandedMask, KnownFPClass ,
+unsigned Depth, Instruction *CxtI) {
+  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+  Type *VTy = V->getType();
+
+  assert(Known == KnownFPClass() && "expected uninitialized state");
+
+  if (DemandedMask == fcNone)
+return isa(V) ? nullptr : PoisonValue::get(VTy);
+
+  if (Depth == MaxAnalysisRecursionDepth)
+return nullptr;
+
+  Instruction *I = dyn_cast(V);
+  if (!I) {
+// Handle constants and arguments
+Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
+Value *FoldedToConst =
+getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses);
+return FoldedToConst == V ? nullptr : FoldedToConst;
+  }
+
+  if (!I->hasOneUse())
+return nullptr;
+
+  // TODO: Should account for nofpclass/FastMathFlags on current instruction
+  switch (I->getOpcode()) {
+  case Instruction::FNeg: {
+if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
+Depth + 1))
+  return I;
+Known.fneg();
+break;
+  }
+  case Instruction::Call: {
+CallInst *CI = cast(I);
+switch (CI->getIntrinsicID()) {
+case Intrinsic::fabs:
+  if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), 
Known,
+  Depth + 1))
+return I;
+  Known.fabs();
+  break;
+case Intrinsic::arithmetic_fence:
+  if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+return I;
+  break;
+case Intrinsic::copysign: {
+  // Flip on more potentially demanded classes
+  const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
+  if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
+return I;
+
+  if ((DemandedMask & fcPositive) == fcNone) {
+// Roundabout way of replacing with fneg(fabs)
+I->setOperand(1, ConstantFP::get(VTy, -1.0));
+return I;
+  }
+
+  if ((DemandedMask & fcNegative) == fcNone) {
+// Roundabout way of replacing with fabs
+I->setOperand(1, ConstantFP::getZero(VTy));
+return I;
+  }
+
+  KnownFPClass KnownSign =
+  computeKnownFPClass(I->getOperand(1), fcAllFlags, CxtI, Depth + 1);
+  Known.copysign(KnownSign);
+  break;
+}
+default:
+  Known = computeKnownFPClass(I, ~DemandedMask, CxtI, Depth + 1);

dtcxzyw wrote:

Oh, I had mistakenly thought that `computeKnownFPClass` returns the subset of 
`~DemandedMask` :(


https://github.com/llvm/llvm-project/pull/74056
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [X86] Support APXF to enable __builtin_cpu_supports. (PR #80636)

2024-02-07 Thread Freddy Ye via cfe-commits


@@ -1845,6 +1845,7 @@ bool sys::getHostCPUFeatures(StringMap ) {
   Features["prefetchi"]  = HasLeaf7Subleaf1 && ((EDX >> 14) & 1);
   Features["usermsr"]  = HasLeaf7Subleaf1 && ((EDX >> 15) & 1);
   Features["avx10.1-256"] = HasLeaf7Subleaf1 && ((EDX >> 19) & 1);
+  Features["apxf"] = HasLeaf7Subleaf1 && ((EDX >> 21) & 1);

FreddyLeaf wrote:

Yeah, that's another problem. For attribute/target, it seems more reasonable to 
enable as "egpr" instead of "apxf" because apx needs such fine-grained 
enabling. We need to discuss with gcc on this.

https://github.com/llvm/llvm-project/pull/80636
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Reapply "InstCombine: Introduce SimplifyDemandedUseFPClass"" (PR #74056)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -1877,3 +1877,139 @@ Value 
*InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
 
   return MadeChange ? I : nullptr;
 }
+
+/// For floating-point classes that resolve to a single bit pattern, return 
that
+/// value.
+static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
+  switch (Mask) {
+  case fcPosZero:
+return ConstantFP::getZero(Ty);
+  case fcNegZero:
+return ConstantFP::getZero(Ty, true);
+  case fcPosInf:
+return ConstantFP::getInfinity(Ty);
+  case fcNegInf:
+return ConstantFP::getInfinity(Ty, true);
+  case fcNone:
+return PoisonValue::get(Ty);
+  default:
+return nullptr;
+  }
+}
+
+Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
+Value *V, const FPClassTest DemandedMask, KnownFPClass ,
+unsigned Depth, Instruction *CxtI) {
+  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+  Type *VTy = V->getType();
+
+  assert(Known == KnownFPClass() && "expected uninitialized state");
+
+  if (DemandedMask == fcNone)
+return isa(V) ? nullptr : PoisonValue::get(VTy);
+
+  if (Depth == MaxAnalysisRecursionDepth)
+return nullptr;
+
+  Instruction *I = dyn_cast(V);
+  if (!I) {
+// Handle constants and arguments
+Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
+Value *FoldedToConst =
+getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses);
+return FoldedToConst == V ? nullptr : FoldedToConst;
+  }
+
+  if (!I->hasOneUse())
+return nullptr;
+
+  // TODO: Should account for nofpclass/FastMathFlags on current instruction
+  switch (I->getOpcode()) {
+  case Instruction::FNeg: {
+if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
+Depth + 1))
+  return I;
+Known.fneg();
+break;
+  }
+  case Instruction::Call: {
+CallInst *CI = cast(I);
+switch (CI->getIntrinsicID()) {
+case Intrinsic::fabs:
+  if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), 
Known,
+  Depth + 1))
+return I;
+  Known.fabs();
+  break;
+case Intrinsic::arithmetic_fence:
+  if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+return I;
+  break;
+case Intrinsic::copysign: {
+  // Flip on more potentially demanded classes
+  const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
+  if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
+return I;
+
+  if ((DemandedMask & fcPositive) == fcNone) {
+// Roundabout way of replacing with fneg(fabs)
+I->setOperand(1, ConstantFP::get(VTy, -1.0));
+return I;
+  }
+
+  if ((DemandedMask & fcNegative) == fcNone) {
+// Roundabout way of replacing with fabs
+I->setOperand(1, ConstantFP::getZero(VTy));
+return I;
+  }
+
+  KnownFPClass KnownSign =
+  computeKnownFPClass(I->getOperand(1), fcAllFlags, CxtI, Depth + 1);
+  Known.copysign(KnownSign);
+  break;
+}
+default:
+  Known = computeKnownFPClass(I, ~DemandedMask, CxtI, Depth + 1);

arsenm wrote:

You're only interested in the cases you don't already know

https://github.com/llvm/llvm-project/pull/74056
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Reapply "InstCombine: Introduce SimplifyDemandedUseFPClass"" (PR #74056)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -1877,3 +1877,139 @@ Value 
*InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
 
   return MadeChange ? I : nullptr;
 }
+
+/// For floating-point classes that resolve to a single bit pattern, return 
that
+/// value.
+static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
+  switch (Mask) {
+  case fcPosZero:
+return ConstantFP::getZero(Ty);
+  case fcNegZero:
+return ConstantFP::getZero(Ty, true);
+  case fcPosInf:
+return ConstantFP::getInfinity(Ty);
+  case fcNegInf:
+return ConstantFP::getInfinity(Ty, true);
+  case fcNone:
+return PoisonValue::get(Ty);
+  default:
+return nullptr;
+  }
+}
+
+Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
+Value *V, const FPClassTest DemandedMask, KnownFPClass ,
+unsigned Depth, Instruction *CxtI) {
+  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+  Type *VTy = V->getType();
+
+  assert(Known == KnownFPClass() && "expected uninitialized state");
+
+  if (DemandedMask == fcNone)
+return isa(V) ? nullptr : PoisonValue::get(VTy);
+
+  if (Depth == MaxAnalysisRecursionDepth)
+return nullptr;
+
+  Instruction *I = dyn_cast(V);
+  if (!I) {
+// Handle constants and arguments
+Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
+Value *FoldedToConst =
+getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses);
+return FoldedToConst == V ? nullptr : FoldedToConst;
+  }
+
+  if (!I->hasOneUse())
+return nullptr;
+
+  // TODO: Should account for nofpclass/FastMathFlags on current instruction
+  switch (I->getOpcode()) {
+  case Instruction::FNeg: {
+if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
+Depth + 1))
+  return I;
+Known.fneg();
+break;
+  }
+  case Instruction::Call: {
+CallInst *CI = cast(I);
+switch (CI->getIntrinsicID()) {
+case Intrinsic::fabs:
+  if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), 
Known,
+  Depth + 1))
+return I;
+  Known.fabs();
+  break;
+case Intrinsic::arithmetic_fence:
+  if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+return I;
+  break;
+case Intrinsic::copysign: {
+  // Flip on more potentially demanded classes
+  const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
+  if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
+return I;
+
+  if ((DemandedMask & fcPositive) == fcNone) {
+// Roundabout way of replacing with fneg(fabs)
+I->setOperand(1, ConstantFP::get(VTy, -1.0));
+return I;
+  }
+
+  if ((DemandedMask & fcNegative) == fcNone) {

arsenm wrote:

Ditto 

https://github.com/llvm/llvm-project/pull/74056
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Reapply "InstCombine: Introduce SimplifyDemandedUseFPClass"" (PR #74056)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -1877,3 +1877,139 @@ Value 
*InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
 
   return MadeChange ? I : nullptr;
 }
+
+/// For floating-point classes that resolve to a single bit pattern, return 
that
+/// value.
+static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
+  switch (Mask) {
+  case fcPosZero:
+return ConstantFP::getZero(Ty);
+  case fcNegZero:
+return ConstantFP::getZero(Ty, true);
+  case fcPosInf:
+return ConstantFP::getInfinity(Ty);
+  case fcNegInf:
+return ConstantFP::getInfinity(Ty, true);
+  case fcNone:
+return PoisonValue::get(Ty);
+  default:
+return nullptr;
+  }
+}
+
+Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
+Value *V, const FPClassTest DemandedMask, KnownFPClass ,
+unsigned Depth, Instruction *CxtI) {
+  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+  Type *VTy = V->getType();
+
+  assert(Known == KnownFPClass() && "expected uninitialized state");
+
+  if (DemandedMask == fcNone)
+return isa(V) ? nullptr : PoisonValue::get(VTy);
+
+  if (Depth == MaxAnalysisRecursionDepth)
+return nullptr;
+
+  Instruction *I = dyn_cast(V);
+  if (!I) {
+// Handle constants and arguments
+Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
+Value *FoldedToConst =
+getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses);
+return FoldedToConst == V ? nullptr : FoldedToConst;
+  }
+
+  if (!I->hasOneUse())
+return nullptr;
+
+  // TODO: Should account for nofpclass/FastMathFlags on current instruction
+  switch (I->getOpcode()) {
+  case Instruction::FNeg: {
+if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
+Depth + 1))
+  return I;
+Known.fneg();
+break;
+  }
+  case Instruction::Call: {
+CallInst *CI = cast(I);
+switch (CI->getIntrinsicID()) {
+case Intrinsic::fabs:
+  if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), 
Known,
+  Depth + 1))
+return I;
+  Known.fabs();
+  break;
+case Intrinsic::arithmetic_fence:
+  if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+return I;
+  break;
+case Intrinsic::copysign: {
+  // Flip on more potentially demanded classes
+  const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
+  if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
+return I;
+
+  if ((DemandedMask & fcPositive) == fcNone) {

arsenm wrote:

This is unnecessarily conservative, copysign/fabs/fneg preserve the sign of nan 

https://github.com/llvm/llvm-project/pull/74056
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Driver] Remove "-android" from compiler-rt library names for legacy LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=off (PR #81044)

2024-02-07 Thread via cfe-commits

pirama-arumuga-nainar wrote:

(The linux libraries use the new layout but still have symlinks from the old 
names since even that migration is still pending better integration with the 
Android build system).

https://github.com/llvm/llvm-project/pull/81044
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Driver] Remove "-android" from compiler-rt library names for legacy LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=off (PR #81044)

2024-02-07 Thread via cfe-commits

pirama-arumuga-nainar wrote:

The AOSP clang toolchain uses the new layout+names for targeting linux but 
hasn't migrated for compiler-rt libs targeting Android.  See 
https://android.googlesource.com/platform/prebuilts/clang/host/linux-x86/+/refs/heads/main/clang-r510928/lib/clang/18/lib/linux/
 for `-android-`.

Will post an estimate on this migration but I expect it to be in the order of 
months rather than weeks.

https://github.com/llvm/llvm-project/pull/81044
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnosis for constexpr constructor not initializing a union member (PR #81042)

2024-02-07 Thread via cfe-commits


@@ -224,6 +224,9 @@ struct TemplateInit {
   };
   // FIXME: This is ill-formed (no diagnostic required). We should diagnose it.
   constexpr TemplateInit() {} // desired-error {{must initialize all members}}
+#ifndef CXX2A

mahtohappy wrote:

yes, I'm here just following the convention in that file and didn't want to 
change the run command
https://github.com/llvm/llvm-project/blob/main/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp

https://github.com/llvm/llvm-project/pull/81042
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Consider aggregate bases when checking if an InitListExpr is constant (PR #80519)

2024-02-07 Thread Shafik Yaghmour via cfe-commits

shafik wrote:

@AaronBallman since this involves compound literals a C-ism, I would like you 
to review this as well.

https://github.com/llvm/llvm-project/pull/80519
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Parser] Have the depth of the abbreviated generic lambdas inside a requires clause differ from the surrounding generic lambda (PR #80656)

2024-02-07 Thread Shafik Yaghmour via cfe-commits


@@ -1385,6 +1385,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
   Diag(RAngleLoc,
diag::err_lambda_template_parameter_list_empty);
 } else {
+  // We increase the template depth before recursing into a 
requires-clause.
+  // The abbreviated generic lambdas thereof could have different template
+  // depths, avoiding substituting into wrong template parameters during 
the

shafik wrote:

Can you point to where the use of `TemplateParameterDepth` happens? This makes 
sense but I am curious where this happens in this case.

https://github.com/llvm/llvm-project/pull/80656
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Parser] Have the depth of the abbreviated generic lambdas inside a requires clause differ from the surrounding generic lambda (PR #80656)

2024-02-07 Thread Shafik Yaghmour via cfe-commits


@@ -168,3 +168,30 @@ auto lambda4 = [] requires(sizeof(char) == 1){}; // 
expected-error {{expected bo
 #if __cplusplus <= 202002L
 // expected-warning@-2{{lambda without a parameter clause is a C++23 
extension}}
 #endif
+
+namespace GH78524 {
+
+template  T Foo;
+
+template  auto C(Foo);
+
+template  struct D {
+  decltype(T()(C)) Type;
+};
+
+template  D G(T, U) { return {}; }
+
+struct E {};
+
+void F() {
+  G([]
+// ~~ T: 0,0

shafik wrote:

In these context of this PR these comments about depth make sense but for 
someone coming to this test outside of this context they won't. Can you add 
more "depth" to the comment :-)

https://github.com/llvm/llvm-project/pull/80656
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Parser] Have the depth of the abbreviated generic lambdas inside a requires clause differ from the surrounding generic lambda (PR #80656)

2024-02-07 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik edited https://github.com/llvm/llvm-project/pull/80656
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Parser] Have the depth of the abbreviated generic lambdas inside a requires clause differ from the surrounding generic lambda (PR #80656)

2024-02-07 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik commented:

I think this makes sense but I would like @cor3ntin to approve.

https://github.com/llvm/llvm-project/pull/80656
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Fix a regression in dumping the config (PR #80628)

2024-02-07 Thread Owen Pan via cfe-commits

https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/80628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 8f6e13e - [clang-format] Fix a regression in dumping the config (#80628)

2024-02-07 Thread via cfe-commits

Author: Owen Pan
Date: 2024-02-07T21:35:43-08:00
New Revision: 8f6e13e6da84510c8321717860fd506e12118514

URL: 
https://github.com/llvm/llvm-project/commit/8f6e13e6da84510c8321717860fd506e12118514
DIFF: 
https://github.com/llvm/llvm-project/commit/8f6e13e6da84510c8321717860fd506e12118514.diff

LOG: [clang-format] Fix a regression in dumping the config (#80628)

Commit d813af73f70f addressed a regression introduced by commit
3791b3fca6ea
but caused `clang-format -dump-config` to "hang".

This patch reverts changes to ClangFormat.cpp by both commits and
reworks the cleanup.

Fixes #80621.

Added: 


Modified: 
clang/test/Format/dump-config-objc-stdin.m
clang/test/Format/verbose.cpp
clang/tools/clang-format/ClangFormat.cpp

Removed: 




diff  --git a/clang/test/Format/dump-config-objc-stdin.m 
b/clang/test/Format/dump-config-objc-stdin.m
index b22ff7b3328ca..d81711a84d79b 100644
--- a/clang/test/Format/dump-config-objc-stdin.m
+++ b/clang/test/Format/dump-config-objc-stdin.m
@@ -1,5 +1,8 @@
+// RUN: clang-format -assume-filename=foo.m -dump-config | FileCheck %s
+
 // RUN: clang-format -dump-config - < %s | FileCheck %s
 
 // CHECK: Language: ObjC
+
 @interface Foo
 @end

diff  --git a/clang/test/Format/verbose.cpp b/clang/test/Format/verbose.cpp
index dd625e3f67e55..4ab03d8f62aef 100644
--- a/clang/test/Format/verbose.cpp
+++ b/clang/test/Format/verbose.cpp
@@ -1,12 +1,6 @@
-// RUN: clang-format %s  2> %t.stderr
+// RUN: clang-format -verbose 2> %t.stderr
 // RUN: not grep "Formatting" %t.stderr
-// RUN: clang-format %s -verbose 2> %t.stderr
-// RUN: grep -E "Formatting (.*)verbose.cpp(.*)" %t.stderr
-// RUN: clang-format %s -verbose=false 2> %t.stderr
-// RUN: not grep "Formatting" %t.stderr
-
-int a;
-// RUN: clang-format %s  2> %t.stderr
+// RUN: clang-format %s 2> %t.stderr
 // RUN: not grep "Formatting" %t.stderr
 // RUN: clang-format %s -verbose 2> %t.stderr
 // RUN: grep -E "Formatting (.*)verbose.cpp(.*)" %t.stderr

diff  --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index 5ee6092bb9bb7..e122cea50f726 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -399,7 +399,8 @@ class ClangFormatDiagConsumer : public DiagnosticConsumer {
 };
 
 // Returns true on error.
-static bool format(StringRef FileName, bool IsSTDIN) {
+static bool format(StringRef FileName) {
+  const bool IsSTDIN = FileName == "-";
   if (!OutputXML && Inplace && IsSTDIN) {
 errs() << "error: cannot use -i when reading from stdin.\n";
 return false;
@@ -545,24 +546,25 @@ static void PrintVersion(raw_ostream ) {
 }
 
 // Dump the configuration.
-static int dumpConfig(bool IsSTDIN) {
+static int dumpConfig() {
   std::unique_ptr Code;
-
-  // `FileNames` must have at least "-" in it even if no file was specified.
-  assert(!FileNames.empty());
-
-  // Read in the code in case the filename alone isn't enough to detect the
-  // language.
-  ErrorOr> CodeOrErr =
-  MemoryBuffer::getFileOrSTDIN(FileNames[0]);
-  if (std::error_code EC = CodeOrErr.getError()) {
-llvm::errs() << EC.message() << "\n";
-return 1;
+  // We can't read the code to detect the language if there's no file name.
+  if (!FileNames.empty()) {
+// Read in the code in case the filename alone isn't enough to detect the
+// language.
+ErrorOr> CodeOrErr =
+MemoryBuffer::getFileOrSTDIN(FileNames[0]);
+if (std::error_code EC = CodeOrErr.getError()) {
+  llvm::errs() << EC.message() << "\n";
+  return 1;
+}
+Code = std::move(CodeOrErr.get());
   }
-  Code = std::move(CodeOrErr.get());
-
   llvm::Expected FormatStyle =
-  clang::format::getStyle(Style, IsSTDIN ? AssumeFileName : FileNames[0],
+  clang::format::getStyle(Style,
+  FileNames.empty() || FileNames[0] == "-"
+  ? AssumeFileName
+  : FileNames[0],
   FallbackStyle, Code ? Code->getBuffer() : "");
   if (!FormatStyle) {
 llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n";
@@ -682,11 +684,8 @@ int main(int argc, const char **argv) {
 return 0;
   }
 
-  if (FileNames.empty())
-FileNames.push_back("-");
-
   if (DumpConfig)
-return dumpConfig(FileNames[0] == "-");
+return dumpConfig();
 
   if (!Files.empty()) {
 std::ifstream ExternalFileOfFiles{std::string(Files)};
@@ -699,7 +698,10 @@ int main(int argc, const char **argv) {
 errs() << "Clang-formating " << LineNo << " files\n";
   }
 
-  if (FileNames.size() != 1 &&
+  if (FileNames.empty())
+return clang::format::format("-");
+
+  if (FileNames.size() > 1 &&
   (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty())) {
 errs() << "error: -offset, -length and -lines can only be used for "
   "single file.\n";
@@ 

[clang] [clang][ExtractAPI] improve template argument name deduction (PR #77716)

2024-02-07 Thread Erick Velez via cfe-commits

evelez7 wrote:

ping

https://github.com/llvm/llvm-project/pull/77716
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Add support for `CXXRewrittenBinaryOperator`. (PR #81086)

2024-02-07 Thread Gábor Horváth via cfe-commits

https://github.com/Xazax-hun approved this pull request.


https://github.com/llvm/llvm-project/pull/81086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][C++23] Implement P1774R8: Portable assumptions (PR #81014)

2024-02-07 Thread via cfe-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/81014

>From 5ba669011752b6ea6e6fe5f6141c4af66ca7ccbf Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 7 Feb 2024 17:25:10 +0100
Subject: [PATCH 01/17] [Clang] Parsing and Sema for C++23's `assume` attribute

---
 clang/include/clang/Basic/Attr.td |  9 
 clang/include/clang/Basic/DiagnosticGroups.td |  4 +-
 .../clang/Basic/DiagnosticParseKinds.td   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 +++
 clang/include/clang/Parse/Parser.h|  7 +++
 clang/lib/Parse/ParseDeclCXX.cpp  | 54 ++-
 clang/lib/Parse/ParseExpr.cpp | 13 +
 clang/lib/Sema/SemaStmtAttr.cpp   | 34 
 clang/test/Parser/cxx23-assume.cpp| 27 ++
 9 files changed, 156 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Parser/cxx23-assume.cpp

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b2d5309e142c1a..2804ff1aea005f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1564,6 +1564,15 @@ def Unlikely : StmtAttr {
 }
 def : MutualExclusions<[Likely, Unlikely]>;
 
+def Assume : StmtAttr {
+  let Spellings = [CXX11<"", "assume", 202302>];
+  let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">;
+  // The standard only allows a conditional-expression here, but we ought
+  // to get better results by handling that in Sema.
+  let Args = [ExprArgument<"Assumption">];
+  let Documentation = [AssumptionDocs];
+}
+
 def NoMerge : DeclOrStmtAttr {
   let Spellings = [Clang<"nomerge">];
   let Documentation = [NoMergeDocs];
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 6765721ae7002c..192b081404a827 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1124,9 +1124,11 @@ def NonGCC : DiagGroup<"non-gcc",
 def CXX14Attrs : DiagGroup<"c++14-attribute-extensions">;
 def CXX17Attrs : DiagGroup<"c++17-attribute-extensions">;
 def CXX20Attrs : DiagGroup<"c++20-attribute-extensions">;
+def CXX23Attrs : DiagGroup<"c++23-attribute-extensions">;
 def FutureAttrs : DiagGroup<"future-attribute-extensions", [CXX14Attrs,
 CXX17Attrs,
-CXX20Attrs]>;
+CXX20Attrs,
+CXX23Attrs]>;
 
 def CXX23AttrsOnLambda : DiagGroup<"c++23-lambda-attributes">;
 
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index a30ab27566ec3e..9ecfdab3617e05 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -783,6 +783,9 @@ def err_ms_property_expected_comma_or_rparen : Error<
 def err_ms_property_initializer : Error<
   "property declaration cannot have a default member initializer">;
 
+def err_assume_attr_expects_cond_expr : Error<
+  "use of this expression in an 'assume' attribute requires parentheses">;
+
 def warn_cxx20_compat_explicit_bool : Warning<
   "this expression will be parsed as explicit(bool) in C++20">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b4dc4feee8e63a..847168af288622 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9083,6 +9083,8 @@ def ext_cxx17_attr : Extension<
   "use of the %0 attribute is a C++17 extension">, InGroup;
 def ext_cxx20_attr : Extension<
   "use of the %0 attribute is a C++20 extension">, InGroup;
+def ext_cxx23_attr : Extension<
+  "use of the %0 attribute is a C++23 extension">, InGroup;
 
 def warn_unused_comparison : Warning<
   "%select{equality|inequality|relational|three-way}0 comparison result 
unused">,
@@ -10149,6 +10151,11 @@ def err_fallthrough_attr_outside_switch : Error<
 def err_fallthrough_attr_invalid_placement : Error<
   "fallthrough annotation does not directly precede switch label">;
 
+def err_assume_attr_args : Error<
+  "attribute 'assume' requires a single expression argument">;
+def err_assume_attr_wrong_target : Error<
+  "'assume' attribute is only allowed on empty statements">;
+
 def warn_unreachable_default : Warning<
   "default label in switch which covers all enumeration values">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index da18cf88edcc92..0f982dbb67b41c 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1801,6 +1801,7 @@ class Parser : public CodeCompletionHandler {
   ExprResult 

[clang] [Clang][C++23] Implement P1774R8: Portable assumptions (PR #81014)

2024-02-07 Thread via cfe-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/81014

>From 5ba669011752b6ea6e6fe5f6141c4af66ca7ccbf Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 7 Feb 2024 17:25:10 +0100
Subject: [PATCH 01/17] [Clang] Parsing and Sema for C++23's `assume` attribute

---
 clang/include/clang/Basic/Attr.td |  9 
 clang/include/clang/Basic/DiagnosticGroups.td |  4 +-
 .../clang/Basic/DiagnosticParseKinds.td   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 +++
 clang/include/clang/Parse/Parser.h|  7 +++
 clang/lib/Parse/ParseDeclCXX.cpp  | 54 ++-
 clang/lib/Parse/ParseExpr.cpp | 13 +
 clang/lib/Sema/SemaStmtAttr.cpp   | 34 
 clang/test/Parser/cxx23-assume.cpp| 27 ++
 9 files changed, 156 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Parser/cxx23-assume.cpp

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b2d5309e142c1a..2804ff1aea005f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1564,6 +1564,15 @@ def Unlikely : StmtAttr {
 }
 def : MutualExclusions<[Likely, Unlikely]>;
 
+def Assume : StmtAttr {
+  let Spellings = [CXX11<"", "assume", 202302>];
+  let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">;
+  // The standard only allows a conditional-expression here, but we ought
+  // to get better results by handling that in Sema.
+  let Args = [ExprArgument<"Assumption">];
+  let Documentation = [AssumptionDocs];
+}
+
 def NoMerge : DeclOrStmtAttr {
   let Spellings = [Clang<"nomerge">];
   let Documentation = [NoMergeDocs];
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 6765721ae7002c..192b081404a827 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1124,9 +1124,11 @@ def NonGCC : DiagGroup<"non-gcc",
 def CXX14Attrs : DiagGroup<"c++14-attribute-extensions">;
 def CXX17Attrs : DiagGroup<"c++17-attribute-extensions">;
 def CXX20Attrs : DiagGroup<"c++20-attribute-extensions">;
+def CXX23Attrs : DiagGroup<"c++23-attribute-extensions">;
 def FutureAttrs : DiagGroup<"future-attribute-extensions", [CXX14Attrs,
 CXX17Attrs,
-CXX20Attrs]>;
+CXX20Attrs,
+CXX23Attrs]>;
 
 def CXX23AttrsOnLambda : DiagGroup<"c++23-lambda-attributes">;
 
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index a30ab27566ec3e..9ecfdab3617e05 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -783,6 +783,9 @@ def err_ms_property_expected_comma_or_rparen : Error<
 def err_ms_property_initializer : Error<
   "property declaration cannot have a default member initializer">;
 
+def err_assume_attr_expects_cond_expr : Error<
+  "use of this expression in an 'assume' attribute requires parentheses">;
+
 def warn_cxx20_compat_explicit_bool : Warning<
   "this expression will be parsed as explicit(bool) in C++20">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b4dc4feee8e63a..847168af288622 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9083,6 +9083,8 @@ def ext_cxx17_attr : Extension<
   "use of the %0 attribute is a C++17 extension">, InGroup;
 def ext_cxx20_attr : Extension<
   "use of the %0 attribute is a C++20 extension">, InGroup;
+def ext_cxx23_attr : Extension<
+  "use of the %0 attribute is a C++23 extension">, InGroup;
 
 def warn_unused_comparison : Warning<
   "%select{equality|inequality|relational|three-way}0 comparison result 
unused">,
@@ -10149,6 +10151,11 @@ def err_fallthrough_attr_outside_switch : Error<
 def err_fallthrough_attr_invalid_placement : Error<
   "fallthrough annotation does not directly precede switch label">;
 
+def err_assume_attr_args : Error<
+  "attribute 'assume' requires a single expression argument">;
+def err_assume_attr_wrong_target : Error<
+  "'assume' attribute is only allowed on empty statements">;
+
 def warn_unreachable_default : Warning<
   "default label in switch which covers all enumeration values">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index da18cf88edcc92..0f982dbb67b41c 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1801,6 +1801,7 @@ class Parser : public CodeCompletionHandler {
   ExprResult 

[clang] [llvm] Reapply "InstCombine: Introduce SimplifyDemandedUseFPClass"" (PR #74056)

2024-02-07 Thread Yingwei Zheng via cfe-commits


@@ -1877,3 +1877,139 @@ Value 
*InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
 
   return MadeChange ? I : nullptr;
 }
+
+/// For floating-point classes that resolve to a single bit pattern, return 
that
+/// value.
+static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
+  switch (Mask) {
+  case fcPosZero:
+return ConstantFP::getZero(Ty);
+  case fcNegZero:
+return ConstantFP::getZero(Ty, true);
+  case fcPosInf:
+return ConstantFP::getInfinity(Ty);
+  case fcNegInf:
+return ConstantFP::getInfinity(Ty, true);
+  case fcNone:
+return PoisonValue::get(Ty);
+  default:
+return nullptr;
+  }
+}
+
+Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
+Value *V, const FPClassTest DemandedMask, KnownFPClass ,
+unsigned Depth, Instruction *CxtI) {
+  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+  Type *VTy = V->getType();
+
+  assert(Known == KnownFPClass() && "expected uninitialized state");
+
+  if (DemandedMask == fcNone)
+return isa(V) ? nullptr : PoisonValue::get(VTy);
+
+  if (Depth == MaxAnalysisRecursionDepth)
+return nullptr;
+
+  Instruction *I = dyn_cast(V);
+  if (!I) {
+// Handle constants and arguments
+Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
+Value *FoldedToConst =
+getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses);
+return FoldedToConst == V ? nullptr : FoldedToConst;

dtcxzyw wrote:

Ah, sorry for my misreading.

https://github.com/llvm/llvm-project/pull/74056
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Reapply "InstCombine: Introduce SimplifyDemandedUseFPClass"" (PR #74056)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -1877,3 +1877,139 @@ Value 
*InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
 
   return MadeChange ? I : nullptr;
 }
+
+/// For floating-point classes that resolve to a single bit pattern, return 
that
+/// value.
+static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
+  switch (Mask) {
+  case fcPosZero:
+return ConstantFP::getZero(Ty);
+  case fcNegZero:
+return ConstantFP::getZero(Ty, true);
+  case fcPosInf:
+return ConstantFP::getInfinity(Ty);
+  case fcNegInf:
+return ConstantFP::getInfinity(Ty, true);
+  case fcNone:
+return PoisonValue::get(Ty);
+  default:
+return nullptr;
+  }
+}
+
+Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
+Value *V, const FPClassTest DemandedMask, KnownFPClass ,
+unsigned Depth, Instruction *CxtI) {
+  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+  Type *VTy = V->getType();
+
+  assert(Known == KnownFPClass() && "expected uninitialized state");
+
+  if (DemandedMask == fcNone)
+return isa(V) ? nullptr : PoisonValue::get(VTy);
+
+  if (Depth == MaxAnalysisRecursionDepth)
+return nullptr;
+
+  Instruction *I = dyn_cast(V);
+  if (!I) {
+// Handle constants and arguments
+Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
+Value *FoldedToConst =
+getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses);
+return FoldedToConst == V ? nullptr : FoldedToConst;
+  }
+
+  if (!I->hasOneUse())
+return nullptr;
+
+  // TODO: Should account for nofpclass/FastMathFlags on current instruction
+  switch (I->getOpcode()) {
+  case Instruction::FNeg: {
+if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
+Depth + 1))
+  return I;
+Known.fneg();
+break;
+  }
+  case Instruction::Call: {
+CallInst *CI = cast(I);
+switch (CI->getIntrinsicID()) {
+case Intrinsic::fabs:
+  if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), 
Known,
+  Depth + 1))
+return I;
+  Known.fabs();
+  break;
+case Intrinsic::arithmetic_fence:
+  if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+return I;
+  break;
+case Intrinsic::copysign: {
+  // Flip on more potentially demanded classes
+  const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
+  if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
+return I;
+
+  if ((DemandedMask & fcPositive) == fcNone) {
+// Roundabout way of replacing with fneg(fabs)
+I->setOperand(1, ConstantFP::get(VTy, -1.0));
+return I;
+  }
+
+  if ((DemandedMask & fcNegative) == fcNone) {
+// Roundabout way of replacing with fabs
+I->setOperand(1, ConstantFP::getZero(VTy));
+return I;
+  }
+
+  KnownFPClass KnownSign =
+  computeKnownFPClass(I->getOperand(1), fcAllFlags, CxtI, Depth + 1);
+  Known.copysign(KnownSign);
+  break;
+}
+default:
+  Known = computeKnownFPClass(I, ~DemandedMask, CxtI, Depth + 1);
+  break;
+}
+
+break;
+  }
+  case Instruction::Select: {
+KnownFPClass KnownLHS, KnownRHS;
+if (SimplifyDemandedFPClass(I, 2, DemandedMask, KnownRHS, Depth + 1) ||
+SimplifyDemandedFPClass(I, 1, DemandedMask, KnownLHS, Depth + 1))
+  return I;
+
+if (KnownLHS.isKnownNever(DemandedMask))
+  return I->getOperand(2);
+if (KnownRHS.isKnownNever(DemandedMask))
+  return I->getOperand(1);
+
+// TODO: Recognize clamping patterns
+Known = KnownLHS | KnownRHS;
+break;
+  }
+  default:
+Known = computeKnownFPClass(I, ~DemandedMask, CxtI, Depth + 1);

arsenm wrote:

No, you're only interested in the cases that you don't already know are 
impossible 

https://github.com/llvm/llvm-project/pull/74056
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Reapply "InstCombine: Introduce SimplifyDemandedUseFPClass"" (PR #74056)

2024-02-07 Thread Matt Arsenault via cfe-commits


@@ -1877,3 +1877,139 @@ Value 
*InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
 
   return MadeChange ? I : nullptr;
 }
+
+/// For floating-point classes that resolve to a single bit pattern, return 
that
+/// value.
+static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
+  switch (Mask) {
+  case fcPosZero:
+return ConstantFP::getZero(Ty);
+  case fcNegZero:
+return ConstantFP::getZero(Ty, true);
+  case fcPosInf:
+return ConstantFP::getInfinity(Ty);
+  case fcNegInf:
+return ConstantFP::getInfinity(Ty, true);
+  case fcNone:
+return PoisonValue::get(Ty);
+  default:
+return nullptr;
+  }
+}
+
+Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
+Value *V, const FPClassTest DemandedMask, KnownFPClass ,
+unsigned Depth, Instruction *CxtI) {
+  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+  Type *VTy = V->getType();
+
+  assert(Known == KnownFPClass() && "expected uninitialized state");
+
+  if (DemandedMask == fcNone)
+return isa(V) ? nullptr : PoisonValue::get(VTy);
+
+  if (Depth == MaxAnalysisRecursionDepth)
+return nullptr;
+
+  Instruction *I = dyn_cast(V);
+  if (!I) {
+// Handle constants and arguments
+Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
+Value *FoldedToConst =
+getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses);
+return FoldedToConst == V ? nullptr : FoldedToConst;

arsenm wrote:

This isn't true, this guards against infinite loops from returning the same 
value when no change was made 

https://github.com/llvm/llvm-project/pull/74056
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] require template arg list after template kw (PR #80801)

2024-02-07 Thread Erick Velez via cfe-commits

evelez7 wrote:

I was wondering why the Windows CI was failing but seems to be bugged according 
to Discourse. Newest commit changes the error to a pedantic warning that 
defaults to an error.

https://github.com/llvm/llvm-project/pull/80801
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][NFC] resolve redundant predicates (PR #79701)

2024-02-07 Thread via cfe-commits

https://github.com/cor3ntin closed 
https://github.com/llvm/llvm-project/pull/79701
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 351f94d - [clang][NFC] resolve redundant predicates (#79701)

2024-02-07 Thread via cfe-commits

Author: Rageking8
Date: 2024-02-08T06:05:53+01:00
New Revision: 351f94d981f363909ae6e76ed57cd0a75c3f5688

URL: 
https://github.com/llvm/llvm-project/commit/351f94d981f363909ae6e76ed57cd0a75c3f5688
DIFF: 
https://github.com/llvm/llvm-project/commit/351f94d981f363909ae6e76ed57cd0a75c3f5688.diff

LOG: [clang][NFC] resolve redundant predicates (#79701)

Fixes #79686

Added: 


Modified: 
clang/lib/Sema/SemaChecking.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index b071a02ca3713f..c775ff207ba837 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -17183,7 +17183,7 @@ class SequenceChecker : public 
ConstEvaluatedExprVisitor {
 //  evaluates to true.
 bool EvalResult = false;
 bool EvalOK = Eval.evaluate(BO->getLHS(), EvalResult);
-bool ShouldVisitRHS = !EvalOK || (EvalOK && !EvalResult);
+bool ShouldVisitRHS = !EvalOK || !EvalResult;
 if (ShouldVisitRHS) {
   Region = RHSRegion;
   Visit(BO->getRHS());
@@ -17215,7 +17215,7 @@ class SequenceChecker : public 
ConstEvaluatedExprVisitor {
 //  [...] the second operand is not evaluated if the first operand is 
false.
 bool EvalResult = false;
 bool EvalOK = Eval.evaluate(BO->getLHS(), EvalResult);
-bool ShouldVisitRHS = !EvalOK || (EvalOK && EvalResult);
+bool ShouldVisitRHS = !EvalOK || EvalResult;
 if (ShouldVisitRHS) {
   Region = RHSRegion;
   Visit(BO->getRHS());
@@ -17266,8 +17266,8 @@ class SequenceChecker : public 
ConstEvaluatedExprVisitor {
 // evaluated. [...]
 bool EvalResult = false;
 bool EvalOK = Eval.evaluate(CO->getCond(), EvalResult);
-bool ShouldVisitTrueExpr = !EvalOK || (EvalOK && EvalResult);
-bool ShouldVisitFalseExpr = !EvalOK || (EvalOK && !EvalResult);
+bool ShouldVisitTrueExpr = !EvalOK || EvalResult;
+bool ShouldVisitFalseExpr = !EvalOK || !EvalResult;
 if (ShouldVisitTrueExpr) {
   Region = TrueRegion;
   Visit(CO->getTrueExpr());



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] MIPS/clang: Fix asm constraint for softfloat (PR #79116)

2024-02-07 Thread Fangrui Song via cfe-commits


@@ -0,0 +1,25 @@
+; RUN: llc  -march=mips < %s | FileCheck %s --check-prefix=MIPS32
+; RUN: llc  -march=mips64 < %s | FileCheck %s --check-prefix=MIPS64
+
+define dso_local void @read_double(double* nocapture noundef readonly %0) 
local_unnamed_addr #0 {

MaskRay wrote:

Newer tests should use opaque pointers (`ptr`)

https://github.com/llvm/llvm-project/pull/79116
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] MIPS/clang: Fix asm constraint for softfloat (PR #79116)

2024-02-07 Thread Fangrui Song via cfe-commits


@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple mips -target-feature +soft-float 
-DSOFT_FLOAT_NO_CONSTRAINT_F -fsyntax-only -verify %s
+
+#ifdef SOFT_FLOAT_NO_CONSTRAINT_F
+void read_float(float* p) {

MaskRay wrote:

Can just use argument `float p`?

https://github.com/llvm/llvm-project/pull/79116
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][C++23] Implement P1774R8: Portable assumptions (PR #81014)

2024-02-07 Thread via cfe-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/81014

>From 5ba669011752b6ea6e6fe5f6141c4af66ca7ccbf Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 7 Feb 2024 17:25:10 +0100
Subject: [PATCH 01/16] [Clang] Parsing and Sema for C++23's `assume` attribute

---
 clang/include/clang/Basic/Attr.td |  9 
 clang/include/clang/Basic/DiagnosticGroups.td |  4 +-
 .../clang/Basic/DiagnosticParseKinds.td   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 +++
 clang/include/clang/Parse/Parser.h|  7 +++
 clang/lib/Parse/ParseDeclCXX.cpp  | 54 ++-
 clang/lib/Parse/ParseExpr.cpp | 13 +
 clang/lib/Sema/SemaStmtAttr.cpp   | 34 
 clang/test/Parser/cxx23-assume.cpp| 27 ++
 9 files changed, 156 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Parser/cxx23-assume.cpp

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b2d5309e142c1a..2804ff1aea005f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1564,6 +1564,15 @@ def Unlikely : StmtAttr {
 }
 def : MutualExclusions<[Likely, Unlikely]>;
 
+def Assume : StmtAttr {
+  let Spellings = [CXX11<"", "assume", 202302>];
+  let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">;
+  // The standard only allows a conditional-expression here, but we ought
+  // to get better results by handling that in Sema.
+  let Args = [ExprArgument<"Assumption">];
+  let Documentation = [AssumptionDocs];
+}
+
 def NoMerge : DeclOrStmtAttr {
   let Spellings = [Clang<"nomerge">];
   let Documentation = [NoMergeDocs];
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 6765721ae7002c..192b081404a827 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1124,9 +1124,11 @@ def NonGCC : DiagGroup<"non-gcc",
 def CXX14Attrs : DiagGroup<"c++14-attribute-extensions">;
 def CXX17Attrs : DiagGroup<"c++17-attribute-extensions">;
 def CXX20Attrs : DiagGroup<"c++20-attribute-extensions">;
+def CXX23Attrs : DiagGroup<"c++23-attribute-extensions">;
 def FutureAttrs : DiagGroup<"future-attribute-extensions", [CXX14Attrs,
 CXX17Attrs,
-CXX20Attrs]>;
+CXX20Attrs,
+CXX23Attrs]>;
 
 def CXX23AttrsOnLambda : DiagGroup<"c++23-lambda-attributes">;
 
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index a30ab27566ec3e..9ecfdab3617e05 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -783,6 +783,9 @@ def err_ms_property_expected_comma_or_rparen : Error<
 def err_ms_property_initializer : Error<
   "property declaration cannot have a default member initializer">;
 
+def err_assume_attr_expects_cond_expr : Error<
+  "use of this expression in an 'assume' attribute requires parentheses">;
+
 def warn_cxx20_compat_explicit_bool : Warning<
   "this expression will be parsed as explicit(bool) in C++20">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b4dc4feee8e63a..847168af288622 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9083,6 +9083,8 @@ def ext_cxx17_attr : Extension<
   "use of the %0 attribute is a C++17 extension">, InGroup;
 def ext_cxx20_attr : Extension<
   "use of the %0 attribute is a C++20 extension">, InGroup;
+def ext_cxx23_attr : Extension<
+  "use of the %0 attribute is a C++23 extension">, InGroup;
 
 def warn_unused_comparison : Warning<
   "%select{equality|inequality|relational|three-way}0 comparison result 
unused">,
@@ -10149,6 +10151,11 @@ def err_fallthrough_attr_outside_switch : Error<
 def err_fallthrough_attr_invalid_placement : Error<
   "fallthrough annotation does not directly precede switch label">;
 
+def err_assume_attr_args : Error<
+  "attribute 'assume' requires a single expression argument">;
+def err_assume_attr_wrong_target : Error<
+  "'assume' attribute is only allowed on empty statements">;
+
 def warn_unreachable_default : Warning<
   "default label in switch which covers all enumeration values">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index da18cf88edcc92..0f982dbb67b41c 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1801,6 +1801,7 @@ class Parser : public CodeCompletionHandler {
   ExprResult 

[clang] [Clang][C++23] Implement P1774R8: Portable assumptions (PR #81014)

2024-02-07 Thread via cfe-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/81014

>From 5ba669011752b6ea6e6fe5f6141c4af66ca7ccbf Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 7 Feb 2024 17:25:10 +0100
Subject: [PATCH 01/15] [Clang] Parsing and Sema for C++23's `assume` attribute

---
 clang/include/clang/Basic/Attr.td |  9 
 clang/include/clang/Basic/DiagnosticGroups.td |  4 +-
 .../clang/Basic/DiagnosticParseKinds.td   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 +++
 clang/include/clang/Parse/Parser.h|  7 +++
 clang/lib/Parse/ParseDeclCXX.cpp  | 54 ++-
 clang/lib/Parse/ParseExpr.cpp | 13 +
 clang/lib/Sema/SemaStmtAttr.cpp   | 34 
 clang/test/Parser/cxx23-assume.cpp| 27 ++
 9 files changed, 156 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Parser/cxx23-assume.cpp

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b2d5309e142c1..2804ff1aea005 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1564,6 +1564,15 @@ def Unlikely : StmtAttr {
 }
 def : MutualExclusions<[Likely, Unlikely]>;
 
+def Assume : StmtAttr {
+  let Spellings = [CXX11<"", "assume", 202302>];
+  let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">;
+  // The standard only allows a conditional-expression here, but we ought
+  // to get better results by handling that in Sema.
+  let Args = [ExprArgument<"Assumption">];
+  let Documentation = [AssumptionDocs];
+}
+
 def NoMerge : DeclOrStmtAttr {
   let Spellings = [Clang<"nomerge">];
   let Documentation = [NoMergeDocs];
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 6765721ae7002..192b081404a82 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1124,9 +1124,11 @@ def NonGCC : DiagGroup<"non-gcc",
 def CXX14Attrs : DiagGroup<"c++14-attribute-extensions">;
 def CXX17Attrs : DiagGroup<"c++17-attribute-extensions">;
 def CXX20Attrs : DiagGroup<"c++20-attribute-extensions">;
+def CXX23Attrs : DiagGroup<"c++23-attribute-extensions">;
 def FutureAttrs : DiagGroup<"future-attribute-extensions", [CXX14Attrs,
 CXX17Attrs,
-CXX20Attrs]>;
+CXX20Attrs,
+CXX23Attrs]>;
 
 def CXX23AttrsOnLambda : DiagGroup<"c++23-lambda-attributes">;
 
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index a30ab27566ec3..9ecfdab3617e0 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -783,6 +783,9 @@ def err_ms_property_expected_comma_or_rparen : Error<
 def err_ms_property_initializer : Error<
   "property declaration cannot have a default member initializer">;
 
+def err_assume_attr_expects_cond_expr : Error<
+  "use of this expression in an 'assume' attribute requires parentheses">;
+
 def warn_cxx20_compat_explicit_bool : Warning<
   "this expression will be parsed as explicit(bool) in C++20">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b4dc4feee8e63..847168af28862 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9083,6 +9083,8 @@ def ext_cxx17_attr : Extension<
   "use of the %0 attribute is a C++17 extension">, InGroup;
 def ext_cxx20_attr : Extension<
   "use of the %0 attribute is a C++20 extension">, InGroup;
+def ext_cxx23_attr : Extension<
+  "use of the %0 attribute is a C++23 extension">, InGroup;
 
 def warn_unused_comparison : Warning<
   "%select{equality|inequality|relational|three-way}0 comparison result 
unused">,
@@ -10149,6 +10151,11 @@ def err_fallthrough_attr_outside_switch : Error<
 def err_fallthrough_attr_invalid_placement : Error<
   "fallthrough annotation does not directly precede switch label">;
 
+def err_assume_attr_args : Error<
+  "attribute 'assume' requires a single expression argument">;
+def err_assume_attr_wrong_target : Error<
+  "'assume' attribute is only allowed on empty statements">;
+
 def warn_unreachable_default : Warning<
   "default label in switch which covers all enumeration values">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index da18cf88edcc9..0f982dbb67b41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1801,6 +1801,7 @@ class Parser : public CodeCompletionHandler {
   ExprResult ParseConstraintLogicalOrExpression(bool 

[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

2024-02-07 Thread Atousa Duprat via cfe-commits

https://github.com/Atousa edited https://github.com/llvm/llvm-project/pull/80939
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

2024-02-07 Thread Atousa Duprat via cfe-commits

https://github.com/Atousa edited https://github.com/llvm/llvm-project/pull/80939
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][C++23] Implement P1774R8: Portable assumptions (PR #81014)

2024-02-07 Thread via cfe-commits

Sirraide wrote:

Ok, I’ve added some more tests involving template instantiation (and also 
implemented actually handling `assume` in TreeTransform because I seem to have 
forgotten about that earlier...); just let me know if there are any other 
specific situations that we should test.

https://github.com/llvm/llvm-project/pull/81014
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][C++23] Implement P1774R8: Portable assumptions (PR #81014)

2024-02-07 Thread via cfe-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/81014

>From 5ba669011752b6ea6e6fe5f6141c4af66ca7ccbf Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 7 Feb 2024 17:25:10 +0100
Subject: [PATCH 01/14] [Clang] Parsing and Sema for C++23's `assume` attribute

---
 clang/include/clang/Basic/Attr.td |  9 
 clang/include/clang/Basic/DiagnosticGroups.td |  4 +-
 .../clang/Basic/DiagnosticParseKinds.td   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 +++
 clang/include/clang/Parse/Parser.h|  7 +++
 clang/lib/Parse/ParseDeclCXX.cpp  | 54 ++-
 clang/lib/Parse/ParseExpr.cpp | 13 +
 clang/lib/Sema/SemaStmtAttr.cpp   | 34 
 clang/test/Parser/cxx23-assume.cpp| 27 ++
 9 files changed, 156 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Parser/cxx23-assume.cpp

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b2d5309e142c1..2804ff1aea005 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1564,6 +1564,15 @@ def Unlikely : StmtAttr {
 }
 def : MutualExclusions<[Likely, Unlikely]>;
 
+def Assume : StmtAttr {
+  let Spellings = [CXX11<"", "assume", 202302>];
+  let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">;
+  // The standard only allows a conditional-expression here, but we ought
+  // to get better results by handling that in Sema.
+  let Args = [ExprArgument<"Assumption">];
+  let Documentation = [AssumptionDocs];
+}
+
 def NoMerge : DeclOrStmtAttr {
   let Spellings = [Clang<"nomerge">];
   let Documentation = [NoMergeDocs];
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 6765721ae7002..192b081404a82 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1124,9 +1124,11 @@ def NonGCC : DiagGroup<"non-gcc",
 def CXX14Attrs : DiagGroup<"c++14-attribute-extensions">;
 def CXX17Attrs : DiagGroup<"c++17-attribute-extensions">;
 def CXX20Attrs : DiagGroup<"c++20-attribute-extensions">;
+def CXX23Attrs : DiagGroup<"c++23-attribute-extensions">;
 def FutureAttrs : DiagGroup<"future-attribute-extensions", [CXX14Attrs,
 CXX17Attrs,
-CXX20Attrs]>;
+CXX20Attrs,
+CXX23Attrs]>;
 
 def CXX23AttrsOnLambda : DiagGroup<"c++23-lambda-attributes">;
 
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index a30ab27566ec3..9ecfdab3617e0 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -783,6 +783,9 @@ def err_ms_property_expected_comma_or_rparen : Error<
 def err_ms_property_initializer : Error<
   "property declaration cannot have a default member initializer">;
 
+def err_assume_attr_expects_cond_expr : Error<
+  "use of this expression in an 'assume' attribute requires parentheses">;
+
 def warn_cxx20_compat_explicit_bool : Warning<
   "this expression will be parsed as explicit(bool) in C++20">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b4dc4feee8e63..847168af28862 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9083,6 +9083,8 @@ def ext_cxx17_attr : Extension<
   "use of the %0 attribute is a C++17 extension">, InGroup;
 def ext_cxx20_attr : Extension<
   "use of the %0 attribute is a C++20 extension">, InGroup;
+def ext_cxx23_attr : Extension<
+  "use of the %0 attribute is a C++23 extension">, InGroup;
 
 def warn_unused_comparison : Warning<
   "%select{equality|inequality|relational|three-way}0 comparison result 
unused">,
@@ -10149,6 +10151,11 @@ def err_fallthrough_attr_outside_switch : Error<
 def err_fallthrough_attr_invalid_placement : Error<
   "fallthrough annotation does not directly precede switch label">;
 
+def err_assume_attr_args : Error<
+  "attribute 'assume' requires a single expression argument">;
+def err_assume_attr_wrong_target : Error<
+  "'assume' attribute is only allowed on empty statements">;
+
 def warn_unreachable_default : Warning<
   "default label in switch which covers all enumeration values">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index da18cf88edcc9..0f982dbb67b41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1801,6 +1801,7 @@ class Parser : public CodeCompletionHandler {
   ExprResult ParseConstraintLogicalOrExpression(bool 

[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

2024-02-07 Thread Atousa Duprat via cfe-commits

https://github.com/Atousa updated 
https://github.com/llvm/llvm-project/pull/80939

>From ac75fc2873fc7b8eec6c24ba97f4673e94457c8e Mon Sep 17 00:00:00 2001
From: Atousa Duprat 
Date: Tue, 6 Feb 2024 21:02:05 -0800
Subject: [PATCH] [clang] Use separator for large numeric values in overflow
 diagnostic

Add functionality to APInt::toString() that allows it to insert
separators between groups of digits, using the C++ litteral
separator ' between groups.

Fixes issue #58228
---
 clang/lib/AST/ExprConstant.cpp  |   6 +-
 clang/test/AST/Interp/c.c   |   4 +-
 clang/test/C/drs/dr0xx.c|   2 +-
 clang/test/C/drs/dr2xx.c|   2 +-
 clang/test/Sema/integer-overflow.c  | 100 -
 clang/test/Sema/switch-1.c  |   6 +-
 clang/test/SemaCXX/enum.cpp |   4 +-
 clang/test/SemaCXX/integer-overflow.cpp | 112 ++--
 clang/test/SemaObjC/integer-overflow.m  |   4 +-
 clang/test/SemaObjC/objc-literal-nsnumber.m |   2 +-
 llvm/include/llvm/ADT/APInt.h   |   3 +-
 llvm/include/llvm/ADT/StringExtras.h|   5 +-
 llvm/lib/Support/APInt.cpp  |  24 -
 llvm/unittests/ADT/APIntTest.cpp|  35 ++
 14 files changed, 185 insertions(+), 124 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 089bc2094567f7..d9037072c6767f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2774,7 +2774,8 @@ static bool CheckedIntArithmetic(EvalInfo , const 
Expr *E,
 if (Info.checkingForUndefinedBehavior())
   Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_integer_constant_overflow)
-  << toString(Result, 10) << E->getType() << E->getSourceRange();
+  << toString(Result, 10, Result.isSigned(), false, true, true)
+  << E->getType() << E->getSourceRange();
 return HandleOverflow(Info, E, Value, E->getType());
   }
   return true;
@@ -13852,7 +13853,8 @@ bool IntExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   if (Info.checkingForUndefinedBehavior())
 Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
  diag::warn_integer_constant_overflow)
-<< toString(Value, 10) << E->getType() << E->getSourceRange();
+<< toString(Value, 10, Value.isSigned(), false, true, true)
+<< E->getType() << E->getSourceRange();
 
   if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
   E->getType()))
diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 9ab271a82aeef9..aa067b0bc74831 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -109,9 +109,9 @@ int somefunc(int i) {
  // pedantic-expected-warning {{left operand of 
comma operator has no effect}} \
  // pedantic-expected-warning {{overflow in 
expression; result is 131073}} \
  // ref-warning {{left operand of comma operator 
has no effect}} \
- // ref-warning {{overflow in expression; result 
is 131073}} \
+ // ref-warning {{overflow in expression; result 
is 131'073}} \
  // pedantic-ref-warning {{left operand of comma 
operator has no effect}} \
- // pedantic-ref-warning {{overflow in expression; 
result is 131073}}
+ // pedantic-ref-warning {{overflow in expression; 
result is 131'073}}
 
 }
 
diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c
index d9c1fbe4ee40ab..c93cfb63d604cf 100644
--- a/clang/test/C/drs/dr0xx.c
+++ b/clang/test/C/drs/dr0xx.c
@@ -214,7 +214,7 @@ _Static_assert(__builtin_types_compatible_p(struct S { int 
a; }, union U { int a
  */
 void dr031(int i) {
   switch (i) {
-  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; 
result is -2147483648 with type 'int'}} */
+  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; 
result is -2'147'483'648 with type 'int'}} */
   #pragma clang diagnostic push
   #pragma clang diagnostic ignored "-Wswitch"
   /* Silence the targets which issue:
diff --git a/clang/test/C/drs/dr2xx.c b/clang/test/C/drs/dr2xx.c
index 9c8d77518ab55e..1b68b65acca6af 100644
--- a/clang/test/C/drs/dr2xx.c
+++ b/clang/test/C/drs/dr2xx.c
@@ -277,7 +277,7 @@ void dr258(void) {
 void dr261(void) {
   /* This is still an integer constant expression despite the overflow. */
   enum e1 {
-ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; 
result is -2147483648 with type 'int'}} */
+ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; 
result is -2'147'483'648 with type 'int'}} */
   };
 
   /* This is not an integer constant 

[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

2024-02-07 Thread via cfe-commits

llvmbot wrote:



@llvm/pr-subscribers-clang

@llvm/pr-subscribers-llvm-adt

Author: Atousa Duprat (Atousa)


Changes

Add functionality to APInt::toString() that allows it to insert
separators between groups of digits, using the C++ litteral
separator ' between groups.

Fixes issue #58228


---

Patch is 41.05 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/80939.diff


14 Files Affected:

- (modified) clang/lib/AST/ExprConstant.cpp (+4-2) 
- (modified) clang/test/AST/Interp/c.c (+2-2) 
- (modified) clang/test/C/drs/dr0xx.c (+1-1) 
- (modified) clang/test/C/drs/dr2xx.c (+1-1) 
- (modified) clang/test/Sema/integer-overflow.c (+50-50) 
- (modified) clang/test/Sema/switch-1.c (+3-3) 
- (modified) clang/test/SemaCXX/enum.cpp (+2-2) 
- (modified) clang/test/SemaCXX/integer-overflow.cpp (+56-56) 
- (modified) clang/test/SemaObjC/integer-overflow.m (+2-2) 
- (modified) clang/test/SemaObjC/objc-literal-nsnumber.m (+1-1) 
- (modified) llvm/include/llvm/ADT/APInt.h (+2-1) 
- (modified) llvm/include/llvm/ADT/StringExtras.h (+8-4) 
- (modified) llvm/lib/Support/APInt.cpp (+23-1) 
- (modified) llvm/unittests/ADT/APIntTest.cpp (+35) 


``diff
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 089bc2094567f7..53eaefe7c0dc7e 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2774,7 +2774,8 @@ static bool CheckedIntArithmetic(EvalInfo , const 
Expr *E,
 if (Info.checkingForUndefinedBehavior())
   Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_integer_constant_overflow)
-  << toString(Result, 10) << E->getType() << E->getSourceRange();
+  << toString(Result, 10, Result.isSigned(), false, true, true)
+  << E->getType() << E->getSourceRange();
 return HandleOverflow(Info, E, Value, E->getType());
   }
   return true;
@@ -13852,7 +13853,8 @@ bool IntExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   if (Info.checkingForUndefinedBehavior())
 Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
  diag::warn_integer_constant_overflow)
-<< toString(Value, 10) << E->getType() << E->getSourceRange();
+<< toString(Value, 10, false, true, true) << E->getType()
+<< E->getSourceRange();
 
   if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
   E->getType()))
diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 9ab271a82aeef9..aa067b0bc74831 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -109,9 +109,9 @@ int somefunc(int i) {
  // pedantic-expected-warning {{left operand of 
comma operator has no effect}} \
  // pedantic-expected-warning {{overflow in 
expression; result is 131073}} \
  // ref-warning {{left operand of comma operator 
has no effect}} \
- // ref-warning {{overflow in expression; result 
is 131073}} \
+ // ref-warning {{overflow in expression; result 
is 131'073}} \
  // pedantic-ref-warning {{left operand of comma 
operator has no effect}} \
- // pedantic-ref-warning {{overflow in expression; 
result is 131073}}
+ // pedantic-ref-warning {{overflow in expression; 
result is 131'073}}
 
 }
 
diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c
index d9c1fbe4ee40ab..c93cfb63d604cf 100644
--- a/clang/test/C/drs/dr0xx.c
+++ b/clang/test/C/drs/dr0xx.c
@@ -214,7 +214,7 @@ _Static_assert(__builtin_types_compatible_p(struct S { int 
a; }, union U { int a
  */
 void dr031(int i) {
   switch (i) {
-  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; 
result is -2147483648 with type 'int'}} */
+  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; 
result is -2'147'483'648 with type 'int'}} */
   #pragma clang diagnostic push
   #pragma clang diagnostic ignored "-Wswitch"
   /* Silence the targets which issue:
diff --git a/clang/test/C/drs/dr2xx.c b/clang/test/C/drs/dr2xx.c
index 9c8d77518ab55e..1b68b65acca6af 100644
--- a/clang/test/C/drs/dr2xx.c
+++ b/clang/test/C/drs/dr2xx.c
@@ -277,7 +277,7 @@ void dr258(void) {
 void dr261(void) {
   /* This is still an integer constant expression despite the overflow. */
   enum e1 {
-ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; 
result is -2147483648 with type 'int'}} */
+ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; 
result is -2'147'483'648 with type 'int'}} */
   };
 
   /* This is not an integer constant expression, because of the comma operator,
diff --git a/clang/test/Sema/integer-overflow.c 
b/clang/test/Sema/integer-overflow.c
index 

[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

2024-02-07 Thread Atousa Duprat via cfe-commits

https://github.com/Atousa converted_to_draft 
https://github.com/llvm/llvm-project/pull/80939
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

2024-02-07 Thread Atousa Duprat via cfe-commits

https://github.com/Atousa ready_for_review 
https://github.com/llvm/llvm-project/pull/80939
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [AMDGPU] Introduce GFX9/10.1/10.3/11 Generic Targets (PR #76955)

2024-02-07 Thread Tony Tye via cfe-commits

https://github.com/t-tye commented:

Documentation LGTM. Thanks.

https://github.com/llvm/llvm-project/pull/76955
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Add Leave to AlwaysBreakTemplateDeclarations (PR #80569)

2024-02-07 Thread Owen Pan via cfe-commits

https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/80569
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] d033799 - [clang-format] Add Leave to AlwaysBreakTemplateDeclarations (#80569)

2024-02-07 Thread via cfe-commits

Author: Owen Pan
Date: 2024-02-07T20:24:44-08:00
New Revision: d033799050b7bda70d80a933d5d99b7088a72a95

URL: 
https://github.com/llvm/llvm-project/commit/d033799050b7bda70d80a933d5d99b7088a72a95
DIFF: 
https://github.com/llvm/llvm-project/commit/d033799050b7bda70d80a933d5d99b7088a72a95.diff

LOG: [clang-format] Add Leave to AlwaysBreakTemplateDeclarations (#80569)

Closes #78067.

Added: 


Modified: 
clang/docs/ClangFormatStyleOptions.rst
clang/include/clang/Format/Format.h
clang/lib/Format/ContinuationIndenter.cpp
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/ConfigParseTest.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index f86be2c1246fb..0a8cc18c5b4cb 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1664,6 +1664,18 @@ the configuration (without a prefix: ``Auto``).
 
   Possible values:
 
+  * ``BTDS_Leave`` (in configuration: ``Leave``)
+Do not change the line breaking before the declaration.
+
+.. code-block:: c++
+
+   template 
+   T foo() {
+   }
+   template  T foo(int a,
+   int b) {
+   }
+
   * ``BTDS_No`` (in configuration: ``No``)
 Do not force break before declaration.
 ``PenaltyBreakTemplateDeclaration`` is taken into account.

diff  --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 415321310c24f..cb14d98825400 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -1031,6 +1031,16 @@ struct FormatStyle {
 
   /// Different ways to break after the template declaration.
   enum BreakTemplateDeclarationsStyle : int8_t {
+/// Do not change the line breaking before the declaration.
+/// \code
+///template 
+///T foo() {
+///}
+///template  T foo(int a,
+///int b) {
+///}
+/// \endcode
+BTDS_Leave,
 /// Do not force break before declaration.
 /// ``PenaltyBreakTemplateDeclaration`` is taken into account.
 /// \code

diff  --git a/clang/lib/Format/ContinuationIndenter.cpp 
b/clang/lib/Format/ContinuationIndenter.cpp
index 671ae540c75b1..7fd04b23abdca 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -569,7 +569,10 @@ bool ContinuationIndenter::mustBreak(const LineState 
) {
   return true;
 }
   }
-  return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_No;
+  return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_No &&
+ (Style.AlwaysBreakTemplateDeclarations !=
+  FormatStyle::BTDS_Leave ||
+  Current.NewlinesBefore > 0);
 }
 if (Previous.is(TT_FunctionAnnotationRParen) &&
 State.Line->Type != LT_PreprocessorDirective) {

diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 9c780cd7a5f4e..c5714af155f0b 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -296,6 +296,7 @@ template <>
 struct ScalarEnumerationTraits {
   static void enumeration(IO ,
   FormatStyle::BreakTemplateDeclarationsStyle ) {
+IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave);
 IO.enumCase(Value, "No", FormatStyle::BTDS_No);
 IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
 IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);

diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 7a62f5fd3dfbb..cec56fad53156 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5184,7 +5184,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine 
,
 // concept ...
 if (Right.is(tok::kw_concept))
   return Style.BreakBeforeConceptDeclarations == FormatStyle::BBCDS_Always;
-return Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes;
+return Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes ||
+   (Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Leave &&
+Right.NewlinesBefore > 0);
   }
   if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) {
 switch (Style.RequiresClausePosition) {
@@ -5617,7 +5619,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine 
,
 return Style.BreakBeforeConceptDeclarations != FormatStyle::BBCDS_Never;
   if (Right.is(TT_RequiresClause))
 return true;
-  if (Left.ClosesTemplateDeclaration || Left.is(TT_FunctionAnnotationRParen))
+  if (Left.ClosesTemplateDeclaration) {
+return Style.AlwaysBreakTemplateDeclarations != 

[clang] [clang][dataflow] Add support for `CXXRewrittenBinaryOperator`. (PR #81086)

2024-02-07 Thread via cfe-commits

llvmbot wrote:



@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-analysis

Author: None (martinboehme)


Changes

This occurs in rewritten candidates for binary operators (a C++20 feature).

The patch modifies UncheckedOptionalAccessModelTest to run in C++20 mode (as
well as C++17 mode, as before) and to use rewritten candidates. The modified
test fails without the newly added support for `CXXRewrittenBinaryOperator`.


---
Full diff: https://github.com/llvm/llvm-project/pull/81086.diff


2 Files Affected:

- (modified) clang/lib/Analysis/FlowSensitive/Transfer.cpp (+4) 
- (modified) 
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp 
(+15-1) 


``diff
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp 
b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index bb3aec763c29ca..a098471d0ee905 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -545,6 +545,10 @@ class TransferVisitor : public 
ConstStmtVisitor {
 VisitCallExpr(S);
   }
 
+  void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) {
+propagateValue(*RBO->getSemanticForm(), *RBO, Env);
+  }
+
   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
 if (S->getCastKind() == CK_ConstructorConversion) {
   const Expr *SubExpr = S->getSubExpr();
diff --git 
a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
index 73fb4063d92be9..b6e4973fd7cb2b 100644
--- 
a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ 
b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -770,12 +770,17 @@ constexpr bool operator!=(const optional , const 
optional );
 
 template 
 constexpr bool operator==(const optional , nullopt_t);
+
+// C++20 and later do not define the following overloads because they are
+// provided by rewritten candidates instead.
+#if __cplusplus < 202002L
 template 
 constexpr bool operator==(nullopt_t, const optional );
 template 
 constexpr bool operator!=(const optional , nullopt_t);
 template 
 constexpr bool operator!=(nullopt_t, const optional );
+#endif  // __cplusplus < 202002L
 
 template 
 constexpr bool operator==(const optional , const U );
@@ -1289,6 +1294,15 @@ class UncheckedOptionalAccessTest
   template 
   void ExpectDiagnosticsFor(std::string SourceCode,
 FuncDeclMatcher FuncMatcher) {
+// Run in C++17 and C++20 mode to cover differences in the AST between 
modes
+// (e.g. C++20 can contain `CXXRewrittenBinaryOperator`).
+for (const char *CxxMode : {"-std=c++17", "-std=c++20"})
+  ExpectDiagnosticsFor(SourceCode, FuncMatcher, CxxMode);
+  }
+
+  template 
+  void ExpectDiagnosticsFor(std::string SourceCode, FuncDeclMatcher 
FuncMatcher,
+const char *CxxMode) {
 ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
 ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
 
@@ -1332,7 +1346,7 @@ class UncheckedOptionalAccessTest
   llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
 })
 .withASTBuildArgs(
-{"-fsyntax-only", "-std=c++17", "-Wno-undefined-inline"})
+{"-fsyntax-only", CxxMode, "-Wno-undefined-inline"})
 .withASTBuildVirtualMappedFiles(
 tooling::FileContentMappings(Headers.begin(), Headers.end())),
 /*VerifyResults=*/[](

``




https://github.com/llvm/llvm-project/pull/81086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][dataflow] Add support for `CXXRewrittenBinaryOperator`. (PR #81086)

2024-02-07 Thread via cfe-commits

https://github.com/martinboehme created 
https://github.com/llvm/llvm-project/pull/81086

This occurs in rewritten candidates for binary operators (a C++20 feature).

The patch modifies UncheckedOptionalAccessModelTest to run in C++20 mode (as
well as C++17 mode, as before) and to use rewritten candidates. The modified
test fails without the newly added support for `CXXRewrittenBinaryOperator`.


>From 855349a61a16871a0bbbde6b00a0c929453bb1a9 Mon Sep 17 00:00:00 2001
From: Martin Braenne 
Date: Thu, 8 Feb 2024 04:20:52 +
Subject: [PATCH] [clang][dataflow] Add support for
 `CXXRewrittenBinaryOperator`.

This occurs in rewritten candidates for binary operators (a C++20 feature).

The patch modifies UncheckedOptionalAccessModelTest to run in C++20 mode (as
well as C++17 mode, as before) and to use rewritten candidates. The modified
test fails without the newly added support for `CXXRewrittenBinaryOperator`.
---
 clang/lib/Analysis/FlowSensitive/Transfer.cpp|  4 
 .../UncheckedOptionalAccessModelTest.cpp | 16 +++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp 
b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index bb3aec763c29c..a098471d0ee90 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -545,6 +545,10 @@ class TransferVisitor : public 
ConstStmtVisitor {
 VisitCallExpr(S);
   }
 
+  void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) {
+propagateValue(*RBO->getSemanticForm(), *RBO, Env);
+  }
+
   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
 if (S->getCastKind() == CK_ConstructorConversion) {
   const Expr *SubExpr = S->getSubExpr();
diff --git 
a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
index 73fb4063d92be..b6e4973fd7cb2 100644
--- 
a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ 
b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -770,12 +770,17 @@ constexpr bool operator!=(const optional , const 
optional );
 
 template 
 constexpr bool operator==(const optional , nullopt_t);
+
+// C++20 and later do not define the following overloads because they are
+// provided by rewritten candidates instead.
+#if __cplusplus < 202002L
 template 
 constexpr bool operator==(nullopt_t, const optional );
 template 
 constexpr bool operator!=(const optional , nullopt_t);
 template 
 constexpr bool operator!=(nullopt_t, const optional );
+#endif  // __cplusplus < 202002L
 
 template 
 constexpr bool operator==(const optional , const U );
@@ -1289,6 +1294,15 @@ class UncheckedOptionalAccessTest
   template 
   void ExpectDiagnosticsFor(std::string SourceCode,
 FuncDeclMatcher FuncMatcher) {
+// Run in C++17 and C++20 mode to cover differences in the AST between 
modes
+// (e.g. C++20 can contain `CXXRewrittenBinaryOperator`).
+for (const char *CxxMode : {"-std=c++17", "-std=c++20"})
+  ExpectDiagnosticsFor(SourceCode, FuncMatcher, CxxMode);
+  }
+
+  template 
+  void ExpectDiagnosticsFor(std::string SourceCode, FuncDeclMatcher 
FuncMatcher,
+const char *CxxMode) {
 ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
 ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);
 
@@ -1332,7 +1346,7 @@ class UncheckedOptionalAccessTest
   llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
 })
 .withASTBuildArgs(
-{"-fsyntax-only", "-std=c++17", "-Wno-undefined-inline"})
+{"-fsyntax-only", CxxMode, "-Wno-undefined-inline"})
 .withASTBuildVirtualMappedFiles(
 tooling::FileContentMappings(Headers.begin(), Headers.end())),
 /*VerifyResults=*/[](

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-07 Thread via cfe-commits

gulfemsavrun wrote:

> What are the next steps to work to land this? We're interested to try this 
> out for Chrome!

We just need to land this :)

https://github.com/llvm/llvm-project/pull/75425
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-07 Thread via cfe-commits

https://github.com/gulfemsavrun updated 
https://github.com/llvm/llvm-project/pull/75425

>From d98bf5ae49caee5d5539f5104011c6d1e217e6c6 Mon Sep 17 00:00:00 2001
From: Gulfem Savrun Yeniceri 
Date: Thu, 14 Dec 2023 03:40:57 +
Subject: [PATCH] [InstrProf] Single byte counters in coverage

This patch inserts 1-byte counters instead of an 8-byte counters
into llvm profiles for source-based code coverage. The origial idea
was proposed as block-cov for PGO, and this patch repurposes that
idea for coverage.

The current 8-byte counters mechanism add counters to minimal regions,
and infer the counters in the remaining regions via adding or
subtracting counters. For example, it infers the counter in the if.else
region by subtracting the counters between if.entry and if.then regions
in an if statement. Whenever there is a control-flow merge, it adds
the counters from all the incoming regions. However, we are not going to
be able to infer counters by subtracting two execution counts when using
single-byte counters. Therefore, this patch conservatively inserts
additional counters for the cases where we need to add or subtract counters.

RFC:
https://discourse.llvm.org/t/rfc-single-byte-counters-for-source-based-code-coverage/75685
---
 clang/lib/CodeGen/CGExprAgg.cpp   |  13 +-
 clang/lib/CodeGen/CGExprComplex.cpp   |  14 +-
 clang/lib/CodeGen/CGExprScalar.cpp|  32 ++-
 clang/lib/CodeGen/CGStmt.cpp  |  73 ++-
 clang/lib/CodeGen/CodeGenFunction.cpp |   9 +-
 clang/lib/CodeGen/CodeGenFunction.h   |   2 +-
 clang/lib/CodeGen/CodeGenModule.cpp   |   1 +
 clang/lib/CodeGen/CodeGenPGO.cpp  | 150 -
 clang/lib/CodeGen/CodeGenPGO.h|   6 +-
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 206 +-
 .../CoverageMapping/single-byte-counters.cpp  | 169 ++
 compiler-rt/lib/profile/InstrProfiling.h  |   3 +-
 .../ProfileData/Coverage/CoverageMapping.h|  20 +-
 llvm/include/llvm/ProfileData/InstrProf.h |   3 +-
 .../llvm/ProfileData/InstrProfWriter.h|   4 +
 .../ProfileData/Coverage/CoverageMapping.cpp  |  13 +-
 llvm/lib/ProfileData/InstrProf.cpp|  25 ++-
 llvm/lib/ProfileData/InstrProfWriter.cpp  |   2 +-
 18 files changed, 643 insertions(+), 102 deletions(-)
 create mode 100644 clang/test/CoverageMapping/single-byte-counters.cpp

diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 22f55fe9aac904..377bf413c857cb 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -33,6 +33,10 @@ using namespace CodeGen;
 //Aggregate Expression Emitter
 
//===--===//
 
+namespace llvm {
+extern cl::opt EnableSingleByteCoverage;
+} // namespace llvm
+
 namespace  {
 class AggExprEmitter : public StmtVisitor {
   CodeGenFunction 
@@ -1278,7 +1282,10 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(LHSBlock);
-  CGF.incrementProfileCounter(E);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getTrueExpr());
+  else
+CGF.incrementProfileCounter(E);
   Visit(E->getTrueExpr());
   eval.end(CGF);
 
@@ -1293,6 +1300,8 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(RHSBlock);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getFalseExpr());
   Visit(E->getFalseExpr());
   eval.end(CGF);
 
@@ -1301,6 +1310,8 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 E->getType());
 
   CGF.EmitBlock(ContBlock);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E);
 }
 
 void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp 
b/clang/lib/CodeGen/CGExprComplex.cpp
index 9ddf0e763f139b..683097eea5e76a 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -28,6 +28,10 @@ using namespace CodeGen;
 //Complex Expression Emitter
 
//===--===//
 
+namespace llvm {
+extern cl::opt EnableSingleByteCoverage;
+} // namespace llvm
+
 typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
 
 /// Return the complex type that we are meant to emit.
@@ -1329,7 +1333,11 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(LHSBlock);
-  CGF.incrementProfileCounter(E);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getTrueExpr());
+  else
+CGF.incrementProfileCounter(E);
+
   ComplexPairTy LHS = Visit(E->getTrueExpr());
   LHSBlock = Builder.GetInsertBlock();
   CGF.EmitBranch(ContBlock);
@@ -1337,9 +1345,13 @@ 

[clang] [llvm] [RFC][WIP][AMDGPU] Use `bf16` instead of `i16` for bfloat (PR #80908)

2024-02-07 Thread Shilei Tian via cfe-commits

https://github.com/shiltian updated 
https://github.com/llvm/llvm-project/pull/80908

>From 6a2bacee940d95abc53bcff2332b0d9aa0f1073f Mon Sep 17 00:00:00 2001
From: Shilei Tian 
Date: Wed, 7 Feb 2024 23:09:33 -0500
Subject: [PATCH] [RFC][WIP][AMDGPU] Use `bf16` instead of `i16` for bfloat

Currently it looks like we generally use `i16` to represent `bf16` in those 
tablegen
files. I'm not sure of the reason behind it. My wild guess is the type `bf16` 
was
not available when we enabled the support. This patch is trying to use `bf16`
directly in those tablegen files, aiming at fixing #79369. Of course for #79369
a workaround can be to treat all `INT16` variants as `BFloat` in 
`getOpFltSemantics`,
but it doesn't look good IMHO.

Since I'm fairly new to AMDGPU backend, I'd appreciate it if you can point out
where I don't understand correctly.
---
 clang/include/clang/Basic/BuiltinsAMDGPU.def  |  4 +-
 .../builtins-amdgcn-dl-insts-err.cl   |  9 ++-
 .../builtins-amdgcn-dl-insts-gfx11.cl | 13 ++--
 llvm/include/llvm/IR/IntrinsicsAMDGPU.td  | 12 ++--
 llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp  |  5 +-
 .../AMDGPU/AsmParser/AMDGPUAsmParser.cpp  | 66 +++
 .../AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp | 10 +++
 .../MCTargetDesc/AMDGPUMCCodeEmitter.cpp  |  7 ++
 llvm/lib/Target/AMDGPU/SIDefines.h|  7 ++
 llvm/lib/Target/AMDGPU/SIInstrInfo.cpp|  7 ++
 llvm/lib/Target/AMDGPU/SIInstrInfo.td | 60 +
 llvm/lib/Target/AMDGPU/SIRegisterInfo.td  | 22 ++-
 llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h |  7 ++
 llvm/lib/Target/AMDGPU/VOP3Instructions.td|  2 +-
 llvm/lib/Target/AMDGPU/VOP3PInstructions.td   |  2 +-
 .../AMDGPU/llvm.amdgcn.fdot2.bf16.bf16.ll | 36 +-
 .../AMDGPU/llvm.amdgcn.fdot2.f32.bf16.ll  | 14 ++--
 llvm/test/MC/AMDGPU/bf16_imm.s|  8 +++
 18 files changed, 217 insertions(+), 74 deletions(-)
 create mode 100644 llvm/test/MC/AMDGPU/bf16_imm.s

diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def 
b/clang/include/clang/Basic/BuiltinsAMDGPU.def
index 213311b96df74f..4fe236e8aca12d 100644
--- a/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -246,8 +246,8 @@ TARGET_BUILTIN(__builtin_amdgcn_ds_atomic_fadd_v2f16, 
"V2hV2h*3V2h", "t", "atomi
 
 TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hfIb", "nc", "dot10-insts")
 TARGET_BUILTIN(__builtin_amdgcn_fdot2_f16_f16, "hV2hV2hh", "nc", "dot9-insts")
-TARGET_BUILTIN(__builtin_amdgcn_fdot2_bf16_bf16, "sV2sV2ss", "nc", 
"dot9-insts")
-TARGET_BUILTIN(__builtin_amdgcn_fdot2_f32_bf16, "fV2sV2sfIb", "nc", 
"dot9-insts")
+TARGET_BUILTIN(__builtin_amdgcn_fdot2_bf16_bf16, "yV2yV2yy", "nc", 
"dot9-insts")
+TARGET_BUILTIN(__builtin_amdgcn_fdot2_f32_bf16, "fV2yV2yfIb", "nc", 
"dot9-insts")
 TARGET_BUILTIN(__builtin_amdgcn_sdot2, "SiV2SsV2SsSiIb", "nc", "dot2-insts")
 TARGET_BUILTIN(__builtin_amdgcn_udot2, "UiV2UsV2UsUiIb", "nc", "dot2-insts")
 TARGET_BUILTIN(__builtin_amdgcn_sdot4, "SiSiSiSiIb", "nc", "dot1-insts")
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl 
b/clang/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
index f5317683d0ff97..fa225c4962c90b 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
@@ -5,6 +5,8 @@
 
 typedef unsigned int uint;
 typedef half __attribute__((ext_vector_type(2))) half2;
+typedef __bf16 bfloat;
+typedef bfloat __attribute__((ext_vector_type(2))) bfloat2;
 typedef short __attribute__((ext_vector_type(2))) short2;
 typedef unsigned short __attribute__((ext_vector_type(2))) ushort2;
 
@@ -15,16 +17,17 @@ kernel void builtins_amdgcn_dl_insts_err(
 half2 v2hA, half2 v2hB, float fC, half hC,
 short2 v2ssA, short2 v2ssB, short sC, int siA, int siB, int siC,
 ushort2 v2usA, ushort2 v2usB, uint uiA, uint uiB, uint uiC,
+bfloat2 v2bfsA, bfloat2 v2bfsB, bfloat bfC,
 int A, int B, int C) {
   fOut[0] = __builtin_amdgcn_fdot2(v2hA, v2hB, fC, false);  // 
expected-error {{'__builtin_amdgcn_fdot2' needs target feature dot10-insts}}
   fOut[1] = __builtin_amdgcn_fdot2(v2hA, v2hB, fC, true);   // 
expected-error {{'__builtin_amdgcn_fdot2' needs target feature dot10-insts}}
 
   hOut[0] = __builtin_amdgcn_fdot2_f16_f16(v2hA, v2hB, hC);   // 
expected-error {{'__builtin_amdgcn_fdot2_f16_f16' needs target feature 
dot9-insts}}
 
-  sOut[0] = __builtin_amdgcn_fdot2_bf16_bf16(v2ssA, v2ssB, sC);   // 
expected-error {{'__builtin_amdgcn_fdot2_bf16_bf16' needs target feature 
dot9-insts}}
+  sOut[0] = __builtin_amdgcn_fdot2_bf16_bf16(v2bfsA, v2bfsB, bfC);   // 
expected-error {{'__builtin_amdgcn_fdot2_bf16_bf16' needs target feature 
dot9-insts}}
 
-  fOut[3] = __builtin_amdgcn_fdot2_f32_bf16(v2ssA, v2ssB, fC, false); // 
expected-error {{'__builtin_amdgcn_fdot2_f32_bf16' needs target feature 
dot9-insts}}
-  fOut[4] = 

[clang] [Clang][C++23] Implement P1774R8: Portable assumptions (PR #81014)

2024-02-07 Thread via cfe-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/81014

>From 5ba669011752b6ea6e6fe5f6141c4af66ca7ccbf Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 7 Feb 2024 17:25:10 +0100
Subject: [PATCH 01/13] [Clang] Parsing and Sema for C++23's `assume` attribute

---
 clang/include/clang/Basic/Attr.td |  9 
 clang/include/clang/Basic/DiagnosticGroups.td |  4 +-
 .../clang/Basic/DiagnosticParseKinds.td   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 +++
 clang/include/clang/Parse/Parser.h|  7 +++
 clang/lib/Parse/ParseDeclCXX.cpp  | 54 ++-
 clang/lib/Parse/ParseExpr.cpp | 13 +
 clang/lib/Sema/SemaStmtAttr.cpp   | 34 
 clang/test/Parser/cxx23-assume.cpp| 27 ++
 9 files changed, 156 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Parser/cxx23-assume.cpp

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b2d5309e142c1a..2804ff1aea005f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1564,6 +1564,15 @@ def Unlikely : StmtAttr {
 }
 def : MutualExclusions<[Likely, Unlikely]>;
 
+def Assume : StmtAttr {
+  let Spellings = [CXX11<"", "assume", 202302>];
+  let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">;
+  // The standard only allows a conditional-expression here, but we ought
+  // to get better results by handling that in Sema.
+  let Args = [ExprArgument<"Assumption">];
+  let Documentation = [AssumptionDocs];
+}
+
 def NoMerge : DeclOrStmtAttr {
   let Spellings = [Clang<"nomerge">];
   let Documentation = [NoMergeDocs];
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 6765721ae7002c..192b081404a827 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1124,9 +1124,11 @@ def NonGCC : DiagGroup<"non-gcc",
 def CXX14Attrs : DiagGroup<"c++14-attribute-extensions">;
 def CXX17Attrs : DiagGroup<"c++17-attribute-extensions">;
 def CXX20Attrs : DiagGroup<"c++20-attribute-extensions">;
+def CXX23Attrs : DiagGroup<"c++23-attribute-extensions">;
 def FutureAttrs : DiagGroup<"future-attribute-extensions", [CXX14Attrs,
 CXX17Attrs,
-CXX20Attrs]>;
+CXX20Attrs,
+CXX23Attrs]>;
 
 def CXX23AttrsOnLambda : DiagGroup<"c++23-lambda-attributes">;
 
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index a30ab27566ec3e..9ecfdab3617e05 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -783,6 +783,9 @@ def err_ms_property_expected_comma_or_rparen : Error<
 def err_ms_property_initializer : Error<
   "property declaration cannot have a default member initializer">;
 
+def err_assume_attr_expects_cond_expr : Error<
+  "use of this expression in an 'assume' attribute requires parentheses">;
+
 def warn_cxx20_compat_explicit_bool : Warning<
   "this expression will be parsed as explicit(bool) in C++20">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b4dc4feee8e63a..847168af288622 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9083,6 +9083,8 @@ def ext_cxx17_attr : Extension<
   "use of the %0 attribute is a C++17 extension">, InGroup;
 def ext_cxx20_attr : Extension<
   "use of the %0 attribute is a C++20 extension">, InGroup;
+def ext_cxx23_attr : Extension<
+  "use of the %0 attribute is a C++23 extension">, InGroup;
 
 def warn_unused_comparison : Warning<
   "%select{equality|inequality|relational|three-way}0 comparison result 
unused">,
@@ -10149,6 +10151,11 @@ def err_fallthrough_attr_outside_switch : Error<
 def err_fallthrough_attr_invalid_placement : Error<
   "fallthrough annotation does not directly precede switch label">;
 
+def err_assume_attr_args : Error<
+  "attribute 'assume' requires a single expression argument">;
+def err_assume_attr_wrong_target : Error<
+  "'assume' attribute is only allowed on empty statements">;
+
 def warn_unreachable_default : Warning<
   "default label in switch which covers all enumeration values">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index da18cf88edcc92..0f982dbb67b41c 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1801,6 +1801,7 @@ class Parser : public CodeCompletionHandler {
   ExprResult 

[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-07 Thread via cfe-commits


@@ -821,15 +822,23 @@ void InstrProfRecord::merge(InstrProfRecord , 
uint64_t Weight,
 
   for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
 bool Overflowed;
-uint64_t Value =
-SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], );
-if (Value > getInstrMaxCountValue()) {
-  Value = getInstrMaxCountValue();
-  Overflowed = true;
+uint64_t Value;
+// When a profile has single byte coverage, use || to merge counters.
+if (HasSingleByteCoverage)
+  Value = Other.Counts[I] || Counts[I];

gulfemsavrun wrote:

Yes, this is to make sure that we only write 0s or 1s into indexed profiles 
when we use single byte counters mode.  

re: "In addition, indexed profiles would have more information because if a 
counter is large, we know it is commonly executed because it was covered in 
many raw profiles.": Do you have a use case for this? Unless there is a use 
case, I prefer the values in raw profiles and indexed profiles to be 
consistent. Otherwise, it might be cause confusion and difficulty in debugging. 
Currently, we only explored single byte counter in raw profiles. If there is 
any benefit, we can also explore using single byte counters in the indexed 
profiles.


https://github.com/llvm/llvm-project/pull/75425
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnosis for constexpr constructor not initializing a union member (PR #81042)

2024-02-07 Thread Shafik Yaghmour via cfe-commits


@@ -224,6 +224,9 @@ struct TemplateInit {
   };
   // FIXME: This is ill-formed (no diagnostic required). We should diagnose it.
   constexpr TemplateInit() {} // desired-error {{must initialize all members}}
+#ifndef CXX2A

shafik wrote:

We normally do this using parameters to `-verify` and using those in the 
expected line e.g. 

https://github.com/llvm/llvm-project/blob/main/clang/test/Parser/cxx2b-lambdas-ext-warns.cpp

CC @AaronBallman 

https://github.com/llvm/llvm-project/pull/81042
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnosis for constexpr constructor not initializing a union member (PR #81042)

2024-02-07 Thread Shafik Yaghmour via cfe-commits


@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++14 -verify -fcxx-exceptions 
-Werror=c++14-extensions -Werror=c++20-extensions %s
+
+template  struct C {
+union {
+  int i;
+};
+constexpr C() {} // expected-error {{constexpr union constructor that does 
not initialize any member is a C++20 extension}}
+};
+constexpr C c;
+
+template  class D {
+union {
+  int i;
+};
+public:
+constexpr D() {} // expected-error {{constexpr union constructor that does 
not initialize any member is a C++20 extension}}
+};
+constexpr D d;

shafik wrote:

Please add a newline at the end of the file.

https://github.com/llvm/llvm-project/pull/81042
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [RFC][WIP][AMDGPU] Use `bf16` instead of `i16` for bfloat (PR #80908)

2024-02-07 Thread Shilei Tian via cfe-commits


@@ -2819,11 +2819,11 @@ def int_amdgcn_fdot2_f16_f16 :
 def int_amdgcn_fdot2_bf16_bf16 :
   ClangBuiltin<"__builtin_amdgcn_fdot2_bf16_bf16">,
   DefaultAttrsIntrinsic<
-[llvm_i16_ty],   // %r
+[llvm_bfloat_ty],   // %r

shiltian wrote:

Does it make sense if we also update both the Clang builtins and LLVM builtins 
here, and use IR auto upgrade to rewrite existing uses?

https://github.com/llvm/llvm-project/pull/80908
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-07 Thread via cfe-commits


@@ -234,8 +246,20 @@ struct MapRegionCounters : public 
RecursiveASTVisitor {
 if (Hash.getHashVersion() == PGO_HASH_V1)
   return Base::TraverseIfStmt(If);
 
+// When single byte coverage mode is enabled, add a counter to then and
+// else.
+for (Stmt *CS : If->children()) {
+  if (!CS || !llvm::EnableSingleByteCoverage)

gulfemsavrun wrote:

Done!

https://github.com/llvm/llvm-project/pull/75425
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-07 Thread via cfe-commits


@@ -569,16 +577,26 @@ struct CounterCoverageMappingBuilder
 
   /// Return a counter for the subtraction of \c RHS from \c LHS
   Counter subtractCounters(Counter LHS, Counter RHS, bool Simplify = true) {
+if (llvm::EnableSingleByteCoverage)
+  assert(
+  0 &&
+  "cannot subtract counters when single byte coverage mode is 
enabled");

gulfemsavrun wrote:

Thanks for the suggestion. Done!

https://github.com/llvm/llvm-project/pull/75425
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-07 Thread via cfe-commits

https://github.com/gulfemsavrun updated 
https://github.com/llvm/llvm-project/pull/75425

>From 4dd98d84d45e960fe655b23c7b6ec7b4b5ea0114 Mon Sep 17 00:00:00 2001
From: Gulfem Savrun Yeniceri 
Date: Thu, 14 Dec 2023 03:40:57 +
Subject: [PATCH] [InstrProf] Single byte counters in coverage

This patch inserts 1-byte counters instead of an 8-byte counters
into llvm profiles for source-based code coverage. The origial idea
was proposed as block-cov for PGO, and this patch repurposes that
idea for coverage.

The current 8-byte counters mechanism add counters to minimal regions,
and infer the counters in the remaining regions via adding or
subtracting counters. For example, it infers the counter in the if.else
region by subtracting the counters between if.entry and if.then regions
in an if statement. Whenever there is a control-flow merge, it adds
the counters from all the incoming regions. However, we are not going to
be able to infer counters by subtracting two execution counts when using
single-byte counters. Therefore, this patch conservatively inserts
additional counters for the cases where we need to add or subtract counters.

RFC:
https://discourse.llvm.org/t/rfc-single-byte-counters-for-source-based-code-coverage/75685
---
 clang/lib/CodeGen/CGExprAgg.cpp   |  13 +-
 clang/lib/CodeGen/CGExprComplex.cpp   |  14 +-
 clang/lib/CodeGen/CGExprScalar.cpp|  32 ++-
 clang/lib/CodeGen/CGStmt.cpp  |  73 ++-
 clang/lib/CodeGen/CodeGenFunction.cpp |   9 +-
 clang/lib/CodeGen/CodeGenFunction.h   |   2 +-
 clang/lib/CodeGen/CodeGenModule.cpp   |   1 +
 clang/lib/CodeGen/CodeGenPGO.cpp  | 150 +++--
 clang/lib/CodeGen/CodeGenPGO.h|   7 +-
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 203 +-
 .../CoverageMapping/single-byte-counters.cpp  | 169 +++
 compiler-rt/lib/profile/InstrProfiling.h  |   3 +-
 .../ProfileData/Coverage/CoverageMapping.h|  20 +-
 llvm/include/llvm/ProfileData/InstrProf.h |   3 +-
 .../llvm/ProfileData/InstrProfWriter.h|   4 +
 .../ProfileData/Coverage/CoverageMapping.cpp  |  13 +-
 llvm/lib/ProfileData/InstrProf.cpp|  25 ++-
 llvm/lib/ProfileData/InstrProfWriter.cpp  |   2 +-
 18 files changed, 641 insertions(+), 102 deletions(-)
 create mode 100644 clang/test/CoverageMapping/single-byte-counters.cpp

diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 22f55fe9aac904..377bf413c857cb 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -33,6 +33,10 @@ using namespace CodeGen;
 //Aggregate Expression Emitter
 
//===--===//
 
+namespace llvm {
+extern cl::opt EnableSingleByteCoverage;
+} // namespace llvm
+
 namespace  {
 class AggExprEmitter : public StmtVisitor {
   CodeGenFunction 
@@ -1278,7 +1282,10 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(LHSBlock);
-  CGF.incrementProfileCounter(E);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getTrueExpr());
+  else
+CGF.incrementProfileCounter(E);
   Visit(E->getTrueExpr());
   eval.end(CGF);
 
@@ -1293,6 +1300,8 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(RHSBlock);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getFalseExpr());
   Visit(E->getFalseExpr());
   eval.end(CGF);
 
@@ -1301,6 +1310,8 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 E->getType());
 
   CGF.EmitBlock(ContBlock);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E);
 }
 
 void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp 
b/clang/lib/CodeGen/CGExprComplex.cpp
index 9ddf0e763f139b..683097eea5e76a 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -28,6 +28,10 @@ using namespace CodeGen;
 //Complex Expression Emitter
 
//===--===//
 
+namespace llvm {
+extern cl::opt EnableSingleByteCoverage;
+} // namespace llvm
+
 typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
 
 /// Return the complex type that we are meant to emit.
@@ -1329,7 +1333,11 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(LHSBlock);
-  CGF.incrementProfileCounter(E);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getTrueExpr());
+  else
+CGF.incrementProfileCounter(E);
+
   ComplexPairTy LHS = Visit(E->getTrueExpr());
   LHSBlock = Builder.GetInsertBlock();
   CGF.EmitBranch(ContBlock);
@@ -1337,9 +1345,13 @@ 

[clang] [Clang] Fix a non-effective assertion (PR #81083)

2024-02-07 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Shilei Tian (shiltian)


Changes

`PTy` here is literally `FTy-getParamType(i)`, which makes this assertion 
not
work as expected.


---
Full diff: https://github.com/llvm/llvm-project/pull/81083.diff


1 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+1-1) 


``diff
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index e051cbc6486353..a7a410dab1a018 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5908,7 +5908,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
   }
 }
 
-assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) &&
+assert(ArgValue->getType()->canLosslesslyBitCastTo(PTy) &&
"Must be able to losslessly bit cast to param");
 // Cast vector type (e.g., v256i32) to x86_amx, this only happen
 // in amx intrinsics.

``




https://github.com/llvm/llvm-project/pull/81083
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix a non-effective assertion (PR #81083)

2024-02-07 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: Shilei Tian (shiltian)


Changes

`PTy` here is literally `FTy-getParamType(i)`, which makes this assertion 
not
work as expected.


---
Full diff: https://github.com/llvm/llvm-project/pull/81083.diff


1 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+1-1) 


``diff
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index e051cbc6486353..a7a410dab1a018 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5908,7 +5908,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
   }
 }
 
-assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) &&
+assert(ArgValue->getType()->canLosslesslyBitCastTo(PTy) &&
"Must be able to losslessly bit cast to param");
 // Cast vector type (e.g., v256i32) to x86_amx, this only happen
 // in amx intrinsics.

``




https://github.com/llvm/llvm-project/pull/81083
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix a non-effective assertion (PR #81083)

2024-02-07 Thread Shilei Tian via cfe-commits

https://github.com/shiltian created 
https://github.com/llvm/llvm-project/pull/81083

`PTy` here is literally `FTy->getParamType(i)`, which makes this assertion not
work as expected.


>From 076e6d3e1f5a88c4c54b0d2bf6932c9d9ae33678 Mon Sep 17 00:00:00 2001
From: Shilei Tian 
Date: Wed, 7 Feb 2024 22:35:28 -0500
Subject: [PATCH] [Clang] Fix a non-effective assertion

`PTy` here is literally `FTy->getParamType(i)`, which makes this assertion not
work as expected.
---
 clang/lib/CodeGen/CGBuiltin.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index e051cbc6486353..a7a410dab1a018 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5908,7 +5908,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
   }
 }
 
-assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) &&
+assert(ArgValue->getType()->canLosslesslyBitCastTo(PTy) &&
"Must be able to losslessly bit cast to param");
 // Cast vector type (e.g., v256i32) to x86_amx, this only happen
 // in amx intrinsics.

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Jon Chesterfield via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [Clang][C++23] Implement P1774R8: Portable assumptions (PR #81014)

2024-02-07 Thread via cfe-commits

Sirraide wrote:

> I don't see any tests validating that these are being properly instantiated 
> (either by AST dump or by codegen), the only template cases i see are ones 
> where the instantiation not happening doesn't 'matter'. Also, I don't see how 
> these are affecting calls through concepts, so I'd like to see testing for 
> that as well (that is, how the attribute with a failure during instantiation 
> does).

I’ll add some more tests then. 


https://github.com/llvm/llvm-project/pull/81014
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Shilei Tian via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Jon Chesterfield via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();

JonChesterfield wrote:

I've gone with more comments, but maybe to make this clear enough I need to 
separate the field alignment from whether va_list is a void* or something that 
needs more work. The 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Jon Chesterfield via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Joseph Huber via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Jon Chesterfield via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Jon Chesterfield via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Jon Chesterfield via cfe-commits

https://github.com/JonChesterfield edited 
https://github.com/llvm/llvm-project/pull/81058
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Jon Chesterfield via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

2024-02-07 Thread Joseph Huber via cfe-commits


@@ -0,0 +1,698 @@
+//===-- ExpandVariadicsPass.cpp *- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This is an optimisation pass for variadic functions. If called from codegen,
+// it can serve as the implementation of variadic functions for a given target.
+//
+// The target-dependent parts are in namespace VariadicABIInfo. Enabling a new
+// target means adding a case to VariadicABIInfo::create() along with tests.
+//
+// The module pass using that information is class ExpandVariadics.
+//
+// The strategy is:
+// 1. Test whether a variadic function is sufficiently simple
+// 2. If it was, calls to it can be replaced with calls to a different function
+// 3. If it wasn't, try to split it into a simple function and a remainder
+// 4. Optionally rewrite the varadic function calling convention as well
+//
+// This pass considers "sufficiently simple" to mean a variadic function that
+// calls into a different function taking a va_list to do the real work. For
+// example, libc might implement fprintf as a single basic block calling into
+// vfprintf. This pass can then rewrite call to the variadic into some code
+// to construct a target-specific value to use for the va_list and a call
+// into the non-variadic implementation function. There's a test for that.
+//
+// Most other variadic functions whose definition is known can be converted 
into
+// that form. Create a new internal function taking a va_list where the 
original
+// took a ... parameter. Move the blocks across. Create a new block containing 
a
+// va_start that calls into the new function. This is nearly target 
independent.
+//
+// Where this transform is consistent with the ABI, e.g. AMDGPU or NVPTX, or
+// where the ABI can be chosen to align with this transform, the function
+// interface can be rewritten along with calls to unknown variadic functions.
+//
+// The aggregate effect is to unblock other transforms, most critically the
+// general purpose inliner. Known calls to variadic functions become zero cost.
+//
+// This pass does define some target specific information which is partially
+// redundant with other parts of the compiler. In particular, the call frame
+// it builds must be the exact complement of the va_arg lowering performed
+// by clang. The va_list construction is similar to work done by the backend
+// for targets that lower variadics there, though distinct in that this pass
+// constructs the pieces using alloca instead of relative to stack pointers.
+//
+// Consistency with clang is primarily tested by emitting va_arg using clang
+// then expanding the variadic functions using this pass, followed by trying
+// to constant fold the functions to no-ops.
+//
+// Target specific behaviour is tested in IR - mainly checking that values are
+// put into positions in call frames that make sense for that particular 
target.
+//
+//===--===//
+
+#include "llvm/Transforms/IPO/ExpandVariadics.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "expand-variadics"
+
+using namespace llvm;
+
+namespace {
+namespace VariadicABIInfo {
+
+// calling convention for passing as valist object, same as it would be in C
+// aarch64 uses byval
+enum class valistCC { value, pointer, /*byval*/ };
+
+struct Interface {
+protected:
+  Interface(uint32_t MinAlign, uint32_t MaxAlign)
+  : MinAlign(MinAlign), MaxAlign(MaxAlign) {}
+
+public:
+  virtual ~Interface() {}
+  const uint32_t MinAlign;
+  const uint32_t MaxAlign;
+
+  // Most ABIs use a void* or char* for va_list, others can specialise
+  virtual Type *vaListType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  // How the vaListType is passed
+  virtual valistCC vaListCC() { return valistCC::value; }
+
+  // The valist might need to be stack allocated.
+  virtual bool valistOnStack() { return false; }
+
+  virtual void initializeVAList(LLVMContext , IRBuilder<> ,
+AllocaInst * /*va_list*/, Value * /*buffer*/) {
+// Function needs to be implemented if valist is on the stack
+assert(!valistOnStack());
+__builtin_unreachable();
+  }
+
+  // All targets currently implemented use a ptr for the valist parameter
+  Type *vaListParameterType(LLVMContext ) {
+return PointerType::getUnqual(Ctx);
+  }
+
+  bool VAEndIsNop() { return true; }
+
+  bool 

  1   2   3   4   5   >