[clang] [clang][analyzer] Add note tags to alpha.unix.BlockInCriticalSection (PR #80029)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
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)
@@ -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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
@@ -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)
@@ -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