From 20ed5b1f45871612570d3bd447121ac43e083c6a Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Thu, 11 Apr 2024 12:47:51 -0700 Subject: [PATCH 001/464] [nfc]Fix test gold/x86/thinlto.ll with GV Summary change (#88429) This gold thinlto test should have been updated in commit dda7333 (https://github.com/llvm/llvm-project/commit/dda73336ad22bd0b5ecda17040c50fb10fcbe5fb). It's ok to keep {Inputs/emit-llvm.foo.ll, Inputs/emit-llvm.bar.ll} the current way for `llvm-as` since the field is optional (see example in https://github.com/llvm/llvm-project/blob/5d6d8dcd292e0a107b11d378932eee9c2f9ccfc7/llvm/test/Assembler/thinlto-summary.ll#L12-L16) --- llvm/test/tools/gold/X86/thinlto.ll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/test/tools/gold/X86/thinlto.ll b/llvm/test/tools/gold/X86/thinlto.ll index 1745f0382b81..9d56afe9d58d 100644 --- a/llvm/test/tools/gold/X86/thinlto.ll +++ b/llvm/test/tools/gold/X86/thinlto.ll @@ -123,11 +123,11 @@ ; DIS1: ^0 = module: (path: "{{.*}}thinlto.ll.tmp.o", hash: (0, 0, 0, 0, 0)) ; DIS1: ^1 = module: (path: "{{.*}}thinlto.ll.tmp2.o", hash: (0, 0, 0, 0, 0)) -; DIS1: ^2 = gv: (guid: 13146401226427987378, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 1))) -; DIS1: ^3 = gv: (guid: 14740650423002898831, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 2, calls: ((callee: ^2))))) +; DIS1: ^2 = gv: (guid: 13146401226427987378, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; DIS1: ^3 = gv: (guid: 14740650423002898831, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^2))))) ; DIS2: ^0 = module: (path: "{{.*}}thinlto.ll.tmp2.o", hash: (0, 0, 0, 0, 0)) -; DIS2: ^1 = gv: (guid: 13146401226427987378, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 1))) +; DIS2: ^1 = gv: (guid: 13146401226427987378, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) ; COMBINED: Date: Thu, 11 Apr 2024 16:19:29 -0400 Subject: [PATCH 002/464] Reapply "[Clang][Sema] Fix crash when 'this' is used in a dependent class scope function template specialization that instantiates to a static member function (#87541)" (#88311) Reapplies #87541 and addresses the bug which caused expressions naming overload sets to be incorrectly rebuilt. --- clang/docs/ReleaseNotes.rst | 2 + clang/include/clang/Sema/Sema.h | 16 ++- clang/lib/Sema/SemaExpr.cpp | 28 +---- clang/lib/Sema/SemaExprCXX.cpp | 61 +++++----- clang/lib/Sema/SemaExprMember.cpp | 63 ++++++++--- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 ++ clang/lib/Sema/TreeTransform.h | 65 ++++++----- .../SemaTemplate/instantiate-using-decl.cpp | 2 +- ...ms-function-specialization-class-scope.cpp | 106 +++++++++++++++++- 9 files changed, 252 insertions(+), 99 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 93a380411604..45a9a79739a4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -526,6 +526,8 @@ Bug Fixes to C++ Support - Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757). - Fixed a bug that prevented member function templates of class templates declared with a deduced return type from being explicitly specialized for a given implicit instantiation of the class template. +- Fixed a crash when ``this`` is used in a dependent class scope function template specialization + that instantiates to a static member function. - Fix crash when inheriting from a cv-qualified type. Fixes: (`#35603 `_) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f2c55b13b6d3..351b8e1f3113 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5447,7 +5447,8 @@ public: ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, - bool AcceptInvalidDecl = false); + bool AcceptInvalidDecl = false, + bool NeedUnresolved = false); ExprResult BuildDeclarationNameExpr( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, NamedDecl *FoundD = nullptr, @@ -6590,7 +6591,10 @@ public: SourceLocation RParenLoc); //// ActOnCXXThis - Parse 'this' pointer. - ExprResult ActOnCXXThis(SourceLocation loc); + ExprResult ActOnCXXThis(SourceLocation Loc); + + /// Check whether the type of 'this' is valid in the current context. + bool CheckCXXThisType(SourceLocation Loc, QualType Type); /// Build a CXXThisExpr and mark it referenced in the current context. Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit); @@ -7013,10 +7017,14 @@ private: ///@{ public: + /// Check whether an expression might be an implicit class member access. + bool isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, LookupResult &R, + bool IsAddressOfOperand); + ExprResult BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S, - UnresolvedLookupExpr *AsULE = nullptr); + const TemplateArgumentListInfo *TemplateArgs, const Scope *S); + ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4d4ef9b16381..846e7d5d3ab9 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2912,26 +2912,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // to get this right here so that we don't end up making a // spuriously dependent expression if we're inside a dependent // instance method. - if (getLangOpts().CPlusPlus && !R.empty() && - (*R.begin())->isCXXClassMember()) { - bool MightBeImplicitMember; - if (!IsAddressOfOperand) - MightBeImplicitMember = true; - else if (!SS.isEmpty()) - MightBeImplicitMember = false; - else if (R.isOverloadedResult()) - MightBeImplicitMember = false; - else if (R.isUnresolvableResult()) - MightBeImplicitMember = true; - else - MightBeImplicitMember = isa(R.getFoundDecl()) || - isa(R.getFoundDecl()) || - isa(R.getFoundDecl()); - - if (MightBeImplicitMember) - return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, - R, TemplateArgs, S); - } + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, + S); if (TemplateArgs || TemplateKWLoc.isValid()) { @@ -3442,10 +3425,11 @@ static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) { ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, - bool AcceptInvalidDecl) { + bool AcceptInvalidDecl, + bool NeedUnresolved) { // If this is a single, fully-resolved result and we don't need ADL, // just build an ordinary singleton decl ref. - if (!NeedsADL && R.isSingleResult() && + if (!NeedUnresolved && !NeedsADL && R.isSingleResult() && !R.getAsSingle() && !ShouldLookupResultBeMultiVersionOverload(R)) return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(), diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 12f42f66e5e2..763901d4418d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1414,26 +1414,42 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, } ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { - /// C++ 9.3.2: In the body of a non-static member function, the keyword this - /// is a non-lvalue expression whose value is the address of the object for - /// which the function is called. + // C++20 [expr.prim.this]p1: + // The keyword this names a pointer to the object for which an + // implicit object member function is invoked or a non-static + // data member's initializer is evaluated. QualType ThisTy = getCurrentThisType(); - if (ThisTy.isNull()) { - DeclContext *DC = getFunctionLevelDeclContext(); + if (CheckCXXThisType(Loc, ThisTy)) + return ExprError(); - if (const auto *Method = dyn_cast(DC); - Method && Method->isExplicitObjectMemberFunction()) { - return Diag(Loc, diag::err_invalid_this_use) << 1; - } + return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); +} - if (isLambdaCallWithExplicitObjectParameter(CurContext)) - return Diag(Loc, diag::err_invalid_this_use) << 1; +bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) { + if (!Type.isNull()) + return false; - return Diag(Loc, diag::err_invalid_this_use) << 0; + // C++20 [expr.prim.this]p3: + // If a declaration declares a member function or member function template + // of a class X, the expression this is a prvalue of type + // "pointer to cv-qualifier-seq X" wherever X is the current class between + // the optional cv-qualifier-seq and the end of the function-definition, + // member-declarator, or declarator. It shall not appear within the + // declaration of either a static member function or an explicit object + // member function of the current class (although its type and value + // category are defined within such member functions as they are within + // an implicit object member function). + DeclContext *DC = getFunctionLevelDeclContext(); + if (const auto *Method = dyn_cast(DC); + Method && Method->isExplicitObjectMemberFunction()) { + Diag(Loc, diag::err_invalid_this_use) << 1; + } else if (isLambdaCallWithExplicitObjectParameter(CurContext)) { + Diag(Loc, diag::err_invalid_this_use) << 1; + } else { + Diag(Loc, diag::err_invalid_this_use) << 0; } - - return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); + return true; } Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, @@ -8626,21 +8642,8 @@ static ExprResult attemptRecovery(Sema &SemaRef, // Detect and handle the case where the decl might be an implicit // member. - bool MightBeImplicitMember; - if (!Consumer.isAddressOfOperand()) - MightBeImplicitMember = true; - else if (!NewSS.isEmpty()) - MightBeImplicitMember = false; - else if (R.isOverloadedResult()) - MightBeImplicitMember = false; - else if (R.isUnresolvableResult()) - MightBeImplicitMember = true; - else - MightBeImplicitMember = isa(ND) || - isa(ND) || - isa(ND); - - if (MightBeImplicitMember) + if (SemaRef.isPotentialImplicitMemberAccess( + NewSS, R, Consumer.isAddressOfOperand())) return SemaRef.BuildPossibleImplicitMemberExpr( NewSS, /*TemplateKWLoc*/ SourceLocation(), R, /*TemplateArgs*/ nullptr, /*S*/ nullptr); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 32998ae60eaf..eeac753a3489 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -61,6 +61,10 @@ enum IMAKind { /// The reference is a contextually-permitted abstract member reference. IMA_Abstract, + /// Whether the context is static is dependent on the enclosing template (i.e. + /// in a dependent class scope explicit specialization). + IMA_Dependent, + /// The reference may be to an unresolved using declaration and the /// context is not an instance method. IMA_Unresolved_StaticOrExplicitContext, @@ -91,10 +95,18 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); - bool isStaticOrExplicitContext = - SemaRef.CXXThisTypeOverride.isNull() && - (!isa(DC) || cast(DC)->isStatic() || - cast(DC)->isExplicitObjectMemberFunction()); + bool couldInstantiateToStatic = false; + bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull(); + + if (auto *MD = dyn_cast(DC)) { + if (MD->isImplicitObjectMemberFunction()) { + isStaticOrExplicitContext = false; + // A dependent class scope function template explicit specialization + // that is neither declared 'static' nor with an explicit object + // parameter could instantiate to a static or non-static member function. + couldInstantiateToStatic = MD->getDependentSpecializationInfo(); + } + } if (R.isUnresolvableResult()) return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext @@ -123,6 +135,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, if (Classes.empty()) return IMA_Static; + if (couldInstantiateToStatic) + return IMA_Dependent; + // C++11 [expr.prim.general]p12: // An id-expression that denotes a non-static data member or non-static // member function of a class can only be used: @@ -263,32 +278,52 @@ static void diagnoseInstanceReference(Sema &SemaRef, } } +bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, + LookupResult &R, + bool IsAddressOfOperand) { + if (!getLangOpts().CPlusPlus) + return false; + else if (R.empty() || !R.begin()->isCXXClassMember()) + return false; + else if (!IsAddressOfOperand) + return true; + else if (!SS.isEmpty()) + return false; + else if (R.isOverloadedResult()) + return false; + else if (R.isUnresolvableResult()) + return true; + else + return isa(R.getFoundDecl()); +} + /// Builds an expression which might be an implicit member expression. ExprResult Sema::BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S, - UnresolvedLookupExpr *AsULE) { - switch (ClassifyImplicitMemberAccess(*this, R)) { + const TemplateArgumentListInfo *TemplateArgs, const Scope *S) { + switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) { case IMA_Instance: - return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S); - case IMA_Mixed: case IMA_Mixed_Unrelated: case IMA_Unresolved: - return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false, - S); - + return BuildImplicitMemberExpr( + SS, TemplateKWLoc, R, TemplateArgs, + /*IsKnownInstance=*/Classification == IMA_Instance, S); case IMA_Field_Uneval_Context: Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) << R.getLookupNameInfo().getName(); [[fallthrough]]; case IMA_Static: case IMA_Abstract: + case IMA_Dependent: case IMA_Mixed_StaticOrExplicitContext: case IMA_Unresolved_StaticOrExplicitContext: if (TemplateArgs || TemplateKWLoc.isValid()) - return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); - return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false); + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false, + TemplateArgs); + return BuildDeclarationNameExpr( + SS, R, /*NeedsADL=*/false, /*AcceptInvalidDecl=*/false, + /*NeedUnresolved=*/Classification == IMA_Dependent); case IMA_Error_StaticOrExplicitContext: case IMA_Error_Unrelated: diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 2aa696d35d1d..707446e13209 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5095,6 +5095,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, EnterExpressionEvaluationContext EvalContext( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + Qualifiers ThisTypeQuals; + CXXRecordDecl *ThisContext = nullptr; + if (CXXMethodDecl *Method = dyn_cast(Function)) { + ThisContext = Method->getParent(); + ThisTypeQuals = Method->getMethodQualifiers(); + } + CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals); + // Introduce a new scope where local variable instantiations will be // recorded, unless we're actually a member function within a local // class, in which case we need to merge our results with the parent diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 33a9356e82f4..284c9173e68e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -795,6 +795,9 @@ public: ParenExpr *PE, DependentScopeDeclRefExpr *DRE, bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI); + ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E, + bool IsAddressOfOperand); + StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S); // FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous @@ -3309,12 +3312,13 @@ public: /// Build a new C++ "this" expression. /// - /// By default, builds a new "this" expression without performing any - /// semantic analysis. Subclasses may override this routine to provide - /// different behavior. + /// By default, performs semantic analysis to build a new "this" expression. + /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc, QualType ThisType, bool isImplicit) { + if (getSema().CheckCXXThisType(ThisLoc, ThisType)) + return ExprError(); return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit); } @@ -11351,7 +11355,11 @@ template ExprResult TreeTransform::TransformAddressOfOperand(Expr *E) { if (DependentScopeDeclRefExpr *DRE = dyn_cast(E)) - return getDerived().TransformDependentScopeDeclRefExpr(DRE, true, nullptr); + return getDerived().TransformDependentScopeDeclRefExpr( + DRE, /*IsAddressOfOperand=*/true, nullptr); + else if (UnresolvedLookupExpr *ULE = dyn_cast(E)) + return getDerived().TransformUnresolvedLookupExpr( + ULE, /*IsAddressOfOperand=*/true); else return getDerived().TransformExpr(E); } @@ -13057,10 +13065,16 @@ bool TreeTransform::TransformOverloadExprDecls(OverloadExpr *Old, return false; } -template +template +ExprResult TreeTransform::TransformUnresolvedLookupExpr( + UnresolvedLookupExpr *Old) { + return TransformUnresolvedLookupExpr(Old, /*IsAddressOfOperand=*/false); +} + +template ExprResult -TreeTransform::TransformUnresolvedLookupExpr( - UnresolvedLookupExpr *Old) { +TreeTransform::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, + bool IsAddressOfOperand) { LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), Sema::LookupOrdinaryName); @@ -13092,26 +13106,8 @@ TreeTransform::TransformUnresolvedLookupExpr( R.setNamingClass(NamingClass); } + // Rebuild the template arguments, if any. SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc(); - - // If we have neither explicit template arguments, nor the template keyword, - // it's a normal declaration name or member reference. - if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) { - NamedDecl *D = R.getAsSingle(); - // In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an - // instance member. In other contexts, BuildPossibleImplicitMemberExpr will - // give a good diagnostic. - if (D && D->isCXXInstanceMember()) { - return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, - /*TemplateArgs=*/nullptr, - /*Scope=*/nullptr); - } - - return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); - } - - // If we have template arguments, rebuild them, then rebuild the - // templateid expression. TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc()); if (Old->hasExplicitTemplateArgs() && getDerived().TransformTemplateArguments(Old->getTemplateArgs(), @@ -13121,6 +13117,23 @@ TreeTransform::TransformUnresolvedLookupExpr( return ExprError(); } + // An UnresolvedLookupExpr can refer to a class member. This occurs e.g. when + // a non-static data member is named in an unevaluated operand, or when + // a member is named in a dependent class scope function template explicit + // specialization that is neither declared static nor with an explicit object + // parameter. + if (SemaRef.isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return SemaRef.BuildPossibleImplicitMemberExpr( + SS, TemplateKWLoc, R, + Old->hasExplicitTemplateArgs() ? &TransArgs : nullptr, + /*S=*/nullptr); + + // If we have neither explicit template arguments, nor the template keyword, + // it's a normal declaration name or member reference. + if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) + return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); + + // If we have template arguments, then rebuild the template-id expression. return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R, Old->requiresADL(), &TransArgs); } diff --git a/clang/test/SemaTemplate/instantiate-using-decl.cpp b/clang/test/SemaTemplate/instantiate-using-decl.cpp index 0bbb3ca9c88c..28d837643851 100644 --- a/clang/test/SemaTemplate/instantiate-using-decl.cpp +++ b/clang/test/SemaTemplate/instantiate-using-decl.cpp @@ -121,7 +121,7 @@ template struct Derived : Base { (void)&field; // expected-error@+1 {{call to non-static member function without an object argument}} (void)method; - // expected-error@+1 {{call to non-static member function without an object argument}} + // expected-error@+1 {{must explicitly qualify name of member function when taking its address}} (void)&method; // expected-error@+1 {{call to non-static member function without an object argument}} method(); diff --git a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp index dcab9bfaeabc..f7b59f2ac715 100644 --- a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp +++ b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp @@ -1,7 +1,6 @@ -// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s -// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s +// RUN: %clang_cc1 -fms-extensions -fsyntax-only -Wno-unused-value -verify %s +// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -Wno-unused-value -verify %s -// expected-no-diagnostics class A { public: template A(U p) {} @@ -76,3 +75,104 @@ struct S { int f<0>(int); }; } + +namespace UsesThis { + template + struct A { + int x; + + static inline int y; + + template + static void f(); + + template + void g(); + + template + static auto h() -> A*; + + void i(); + + static void j(); + + template<> + void f() { + this->x; // expected-error {{invalid use of 'this' outside of a non-static member function}} + x; // expected-error {{invalid use of member 'x' in static member function}} + A::x; // expected-error {{invalid use of member 'x' in static member function}} + +x; // expected-error {{invalid use of member 'x' in static member function}} + +A::x; // expected-error {{invalid use of member 'x' in static member function}} + &x; // expected-error {{invalid use of member 'x' in static member function}} + &A::x; + this->y; // expected-error {{invalid use of 'this' outside of a non-static member function}} + y; + A::y; + +y; + +A::y; + &y; + &A::y; + f(); + f(); + g(); // expected-error {{call to non-static member function without an object argument}} + g(); // expected-error {{call to non-static member function without an object argument}} + i(); // expected-error {{call to non-static member function without an object argument}} + j(); + &i; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &j; + &A::i; + &A::j; + } + + template<> + void g() { + this->x; + x; + A::x; + +x; + +A::x; + &x; + &A::x; + this->y; + y; + A::y; + +y; + +A::y; + &y; + &A::y; + f(); + f(); + g(); + g(); + i(); + j(); + &i; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &j; + &A::i; + &A::j; + } + + template<> + auto h() -> decltype(this); // expected-error {{'this' cannot be used in a static member function declaration}} + }; + + template struct A; // expected-note 3{{in instantiation of}} + + template + struct Foo { + template + int bar(X x) { + return 0; + } + + template <> + int bar(int x) { + return bar(5.0); // ok + } + }; + + void call() { + Foo f; + f.bar(1); + } +} -- GitLab From 08e210c6af68005e1bd27488d92de2efba548f58 Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Thu, 11 Apr 2024 13:28:20 -0700 Subject: [PATCH 003/464] [NFC][IndirectCallProm] Refactor function-based conditional devirtualization and indirect call value profile update into one helper function (#80762) * The motivation is to move indirect callee profile update inside the function-based speculative indirect-call promotion, so that there are fewer diffs the vtable-based transformation and profile update is implemented in a follow-up patch. * The Parent patch is https://github.com/llvm/llvm-project/pull/79381 --- llvm/include/llvm/ProfileData/InstrProf.h | 3 +- llvm/lib/ProfileData/InstrProf.cpp | 2 + .../Instrumentation/IndirectCallPromotion.cpp | 49 +++++++++++-------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h index eb3c10bcba1c..d5c1ba62911f 100644 --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -277,6 +277,8 @@ void annotateValueSite(Module &M, Instruction &Inst, uint32_t MaxMDCount = 3); /// Same as the above interface but using an ArrayRef, as well as \p Sum. +/// This function will not annotate !prof metadata on the instruction if the +/// referenced array is empty. void annotateValueSite(Module &M, Instruction &Inst, ArrayRef VDs, uint64_t Sum, InstrProfValueKind ValueKind, uint32_t MaxMDCount); @@ -465,7 +467,6 @@ private: StringSet<> VTableNames; // A map from MD5 keys to function name strings. std::vector> MD5NameMap; - // A map from MD5 keys to function define. We only populate this map // when build the Symtab from a Module. std::vector> MD5FuncMap; diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp index 95f900d0fff1..a5abf63b010f 100644 --- a/llvm/lib/ProfileData/InstrProf.cpp +++ b/llvm/lib/ProfileData/InstrProf.cpp @@ -1246,6 +1246,8 @@ void annotateValueSite(Module &M, Instruction &Inst, ArrayRef VDs, uint64_t Sum, InstrProfValueKind ValueKind, uint32_t MaxMDCount) { + if (VDs.empty()) + return; LLVMContext &Ctx = M.getContext(); MDBuilder MDHelper(Ctx); SmallVector Vals; diff --git a/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp b/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp index 7344fea17517..23a7c6a20aec 100644 --- a/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp +++ b/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp @@ -136,11 +136,13 @@ private: const CallBase &CB, const ArrayRef &ValueDataRef, uint64_t TotalCount, uint32_t NumCandidates); - // Promote a list of targets for one indirect-call callsite. Return - // the number of promotions. - uint32_t tryToPromote(CallBase &CB, - const std::vector &Candidates, - uint64_t &TotalCount); + // Promote a list of targets for one indirect-call callsite by comparing + // indirect callee with functions. Returns true if there are IR + // transformations and false otherwise. + bool tryToPromoteWithFuncCmp( + CallBase &CB, const std::vector &Candidates, + uint64_t TotalCount, ArrayRef ICallProfDataRef, + uint32_t NumCandidates); public: IndirectCallPromoter(Function &Func, InstrProfSymtab *Symtab, bool SamplePGO, @@ -273,9 +275,10 @@ CallBase &llvm::pgo::promoteIndirectCall(CallBase &CB, Function *DirectCallee, } // Promote indirect-call to conditional direct-call for one callsite. -uint32_t IndirectCallPromoter::tryToPromote( +bool IndirectCallPromoter::tryToPromoteWithFuncCmp( CallBase &CB, const std::vector &Candidates, - uint64_t &TotalCount) { + uint64_t TotalCount, ArrayRef ICallProfDataRef, + uint32_t NumCandidates) { uint32_t NumPromoted = 0; for (const auto &C : Candidates) { @@ -287,7 +290,22 @@ uint32_t IndirectCallPromoter::tryToPromote( NumOfPGOICallPromotion++; NumPromoted++; } - return NumPromoted; + + if (NumPromoted == 0) + return false; + + // Adjust the MD.prof metadata. First delete the old one. + CB.setMetadata(LLVMContext::MD_prof, nullptr); + + assert(NumPromoted <= ICallProfDataRef.size() && + "Number of promoted functions should not be greater than the number " + "of values in profile metadata"); + // Annotate the remaining value profiles if counter is not zero. + if (TotalCount != 0) + annotateValueSite(*F.getParent(), CB, ICallProfDataRef.slice(NumPromoted), + TotalCount, IPVK_IndirectCallTarget, NumCandidates); + + return true; } // Traverse all the indirect-call callsite and get the value profile @@ -305,19 +323,8 @@ bool IndirectCallPromoter::processFunction(ProfileSummaryInfo *PSI) { continue; auto PromotionCandidates = getPromotionCandidatesForCallSite( *CB, ICallProfDataRef, TotalCount, NumCandidates); - uint32_t NumPromoted = tryToPromote(*CB, PromotionCandidates, TotalCount); - if (NumPromoted == 0) - continue; - - Changed = true; - // Adjust the MD.prof metadata. First delete the old one. - CB->setMetadata(LLVMContext::MD_prof, nullptr); - // If all promoted, we don't need the MD.prof metadata. - if (TotalCount == 0 || NumPromoted == NumVals) - continue; - // Otherwise we need update with the un-promoted records back. - annotateValueSite(*F.getParent(), *CB, ICallProfDataRef.slice(NumPromoted), - TotalCount, IPVK_IndirectCallTarget, NumCandidates); + Changed |= tryToPromoteWithFuncCmp(*CB, PromotionCandidates, TotalCount, + ICallProfDataRef, NumCandidates); } return Changed; } -- GitLab From 4df854e1a98ed47c955838d2c94bf2913c50041f Mon Sep 17 00:00:00 2001 From: Chelsea Cassanova Date: Thu, 11 Apr 2024 13:38:26 -0700 Subject: [PATCH 004/464] [lldb][lit] Add MallocNanoZone envvar to Darwin ASan builds (#88431) When builds on Darwin are configured with ASan, running tests will emit a warning about malloc's nano zone (`malloc: nano zone abandoned due to inability to reserve vm space`) that can interfere with the test output and cause failures. Setting the environment variable `MallocNanoZone` to 0 will remove this warning and allow the tests to run as normal. --- lldb/test/API/lit.cfg.py | 1 + lldb/test/Shell/lit.cfg.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py index f9497b632fc5..9ea389c639a0 100644 --- a/lldb/test/API/lit.cfg.py +++ b/lldb/test/API/lit.cfg.py @@ -121,6 +121,7 @@ if is_configured("llvm_use_sanitizer"): config.environment["DYLD_INSERT_LIBRARIES"] = find_sanitizer_runtime( "libclang_rt.asan_osx_dynamic.dylib" ) + config.environment["MallocNanoZone"] = "0" if "Thread" in config.llvm_use_sanitizer: config.environment["TSAN_OPTIONS"] = "halt_on_error=1" diff --git a/lldb/test/Shell/lit.cfg.py b/lldb/test/Shell/lit.cfg.py index 31afe5151c06..345627835d2b 100644 --- a/lldb/test/Shell/lit.cfg.py +++ b/lldb/test/Shell/lit.cfg.py @@ -52,6 +52,8 @@ llvm_config.with_system_environment( # Enable sanitizer runtime flags. config.environment["ASAN_OPTIONS"] = "detect_stack_use_after_return=1" config.environment["TSAN_OPTIONS"] = "halt_on_error=1" +if "Darwin" in config.host_os: + config.environment["MallocNanoZone"] = "0" # Support running the test suite under the lldb-repro wrapper. This makes it # possible to capture a test suite run and then rerun all the test from the -- GitLab From 1f5d130df85c2d0550dc8687ad0fa1d96856c318 Mon Sep 17 00:00:00 2001 From: Chelsea Cassanova Date: Thu, 11 Apr 2024 13:46:32 -0700 Subject: [PATCH 005/464] Revert "[lldb][lit] Add MallocNanoZone envvar to Darwin ASan builds" (#88436) Reverts llvm/llvm-project#88431. A config variable for the host OS is unrecognized on the Linux builds and is causing a build failure. --- lldb/test/API/lit.cfg.py | 1 - lldb/test/Shell/lit.cfg.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py index 9ea389c639a0..f9497b632fc5 100644 --- a/lldb/test/API/lit.cfg.py +++ b/lldb/test/API/lit.cfg.py @@ -121,7 +121,6 @@ if is_configured("llvm_use_sanitizer"): config.environment["DYLD_INSERT_LIBRARIES"] = find_sanitizer_runtime( "libclang_rt.asan_osx_dynamic.dylib" ) - config.environment["MallocNanoZone"] = "0" if "Thread" in config.llvm_use_sanitizer: config.environment["TSAN_OPTIONS"] = "halt_on_error=1" diff --git a/lldb/test/Shell/lit.cfg.py b/lldb/test/Shell/lit.cfg.py index 345627835d2b..31afe5151c06 100644 --- a/lldb/test/Shell/lit.cfg.py +++ b/lldb/test/Shell/lit.cfg.py @@ -52,8 +52,6 @@ llvm_config.with_system_environment( # Enable sanitizer runtime flags. config.environment["ASAN_OPTIONS"] = "detect_stack_use_after_return=1" config.environment["TSAN_OPTIONS"] = "halt_on_error=1" -if "Darwin" in config.host_os: - config.environment["MallocNanoZone"] = "0" # Support running the test suite under the lldb-repro wrapper. This makes it # possible to capture a test suite run and then rerun all the test from the -- GitLab From 44de2bb6949f0ca62a2e16506fe3d91be14e6d23 Mon Sep 17 00:00:00 2001 From: Nathan Lanza Date: Thu, 11 Apr 2024 16:56:31 -0400 Subject: [PATCH 006/464] [CIR][cmake] Add support for cmake variable CLANG_ENABLE_CIR Introduce a cmake variable that guards the inclusion of ClangIR into the build of clang. Guard that we aren't trying to build without MLIR. Add two subdirectories that, as of now, don't do anything. Reviewers: bcardosolopes, erichkeane, petrhosek, Ericson2314 Reviewed By: bcardosolopes Pull Request: https://github.com/llvm/llvm-project/pull/86078 --- clang/CMakeLists.txt | 7 +++++++ clang/include/clang/CIR/CMakeLists.txt | 0 clang/include/clang/CMakeLists.txt | 3 +++ clang/include/clang/Config/config.h.cmake | 3 +++ clang/lib/CIR/CMakeLists.txt | 0 clang/lib/CMakeLists.txt | 4 ++++ clang/test/CMakeLists.txt | 1 + clang/test/lit.site.cfg.py.in | 1 + 8 files changed, 19 insertions(+) create mode 100644 clang/include/clang/CIR/CMakeLists.txt create mode 100644 clang/lib/CIR/CMakeLists.txt diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 284b2af24dda..f092766fa19f 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -165,6 +165,13 @@ if(CLANG_ENABLE_LIBXML2) endif() endif() +if(CLANG_ENABLE_CIR) + if (NOT "${LLVM_ENABLE_PROJECTS}" MATCHES "MLIR|mlir") + message(FATAL_ERROR + "Cannot build ClangIR without MLIR in LLVM_ENABLE_PROJECTS") + endif() +endif() + include(CheckIncludeFile) check_include_file(sys/resource.h CLANG_HAVE_RLIMITS) diff --git a/clang/include/clang/CIR/CMakeLists.txt b/clang/include/clang/CIR/CMakeLists.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/include/clang/CMakeLists.txt b/clang/include/clang/CMakeLists.txt index 0dc9ea5ed8ac..47ac70cd2169 100644 --- a/clang/include/clang/CMakeLists.txt +++ b/clang/include/clang/CMakeLists.txt @@ -1,5 +1,8 @@ add_subdirectory(AST) add_subdirectory(Basic) +if(CLANG_ENABLE_CIR) + add_subdirectory(CIR) +endif() add_subdirectory(Driver) add_subdirectory(Parse) add_subdirectory(Sema) diff --git a/clang/include/clang/Config/config.h.cmake b/clang/include/clang/Config/config.h.cmake index 4015ac804086..27ed69e21562 100644 --- a/clang/include/clang/Config/config.h.cmake +++ b/clang/include/clang/Config/config.h.cmake @@ -83,4 +83,7 @@ /* Spawn a new process clang.exe for the CC1 tool invocation, when necessary */ #cmakedefine01 CLANG_SPAWN_CC1 +/* Whether CIR is built into Clang */ +#cmakedefine01 CLANG_ENABLE_CIR + #endif diff --git a/clang/lib/CIR/CMakeLists.txt b/clang/lib/CIR/CMakeLists.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt index 0cac86451f39..14ba55360fe0 100644 --- a/clang/lib/CMakeLists.txt +++ b/clang/lib/CMakeLists.txt @@ -31,3 +31,7 @@ if(CLANG_INCLUDE_TESTS) endif() add_subdirectory(Interpreter) add_subdirectory(Support) + +if(CLANG_ENABLE_CIR) + add_subdirectory(CIR) +endif() diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index fcfca354f4a7..df34a5707da3 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -9,6 +9,7 @@ llvm_canonicalize_cmake_booleans( CLANG_ENABLE_STATIC_ANALYZER CLANG_PLUGIN_SUPPORT CLANG_SPAWN_CC1 + CLANG_ENABLE_CIR ENABLE_BACKTRACES LLVM_ENABLE_ZLIB LLVM_ENABLE_ZSTD diff --git a/clang/test/lit.site.cfg.py.in b/clang/test/lit.site.cfg.py.in index ef75770a2c3c..6641811c5883 100644 --- a/clang/test/lit.site.cfg.py.in +++ b/clang/test/lit.site.cfg.py.in @@ -27,6 +27,7 @@ config.clang_default_pie_on_linux = @CLANG_DEFAULT_PIE_ON_LINUX@ config.clang_default_cxx_stdlib = "@CLANG_DEFAULT_CXX_STDLIB@" config.clang_staticanalyzer = @CLANG_ENABLE_STATIC_ANALYZER@ config.clang_staticanalyzer_z3 = @LLVM_WITH_Z3@ +config.clang_enable_cir = @CLANG_ENABLE_CIR@ config.clang_examples = @CLANG_BUILD_EXAMPLES@ config.enable_shared = @ENABLE_SHARED@ config.enable_backtrace = @ENABLE_BACKTRACES@ -- GitLab From a952c123880eb1168f1021b116485e27170d48ca Mon Sep 17 00:00:00 2001 From: Marius Brehler Date: Thu, 11 Apr 2024 22:58:47 +0200 Subject: [PATCH 007/464] [GitHub] Set top level token permission (#87326) --- .github/workflows/pr-code-format.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index 10b18f245d89..983838858ba4 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -1,4 +1,8 @@ name: "Check code formatting" + +permissions: + contents: read + on: pull_request: branches: -- GitLab From 84df7a09f8da5809b85fd097015e5ac6cc8a3f88 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Thu, 11 Apr 2024 14:44:55 -0700 Subject: [PATCH 008/464] [clang][modules] Do not resolve `HeaderFileInfo` externally in `ASTWriter` (#87848) Clang uses the `HeaderFileInfo` struct to track bits of information on header files, which gets used throughout the compiler. We also use this to compute the set of affecting module maps in `ASTWriter` and in the end serialize the information into the `HEADER_SEARCH_TABLE` record of a PCM file, allowing clients to learn about headers from the module. In doing so, Clang asks for existing `HeaderFileInfo` for all known `FileEntries`. Note that this asks the loaded PCM files for the information they have on each header file in question. This seems unnecessary: we only want to serialize information on header files that either belong to the current module or that got included textually. Loaded PCM files can't provide us with any useful information. For explicit modules with lazy loading (using `-fmodule-map-file=` with `-fmodule-file==`) the compiler knows about header files listed in the module map files on the command-line. This can be a large number. Asking for existing `HeaderFileInfo` can trigger deserialization of `HEADER_SEARCH_TABLE` from loaded PCM files. Keys of the on-disk hash table consist of the header file size and modification time. However, with explicit modules Clang zeroes out the modification time. Moreover, if you import lots of modules, some of their header files end up having identical sizes. This means lots of hash collisions that can only be resolved by running the serialized filename through `FileManager` and comparing equality of the `FileEntry`. This ends up being super expensive, essentially re-stating lots of the transitively loaded SDK header files. This patch cleans up the API for getting `HeaderFileInfo` and makes sure `ASTWriter` uses the version that doesn't ask loaded PCM files for more information. This removes the excessive stat traffic coming from `ASTWriter` hopefully without changing observable behavior. --- .../clangd/index/SymbolCollector.cpp | 2 +- clang/include/clang/Lex/HeaderSearch.h | 24 +++--- clang/lib/Lex/HeaderSearch.cpp | 77 ++++++++++--------- clang/lib/Serialization/ASTWriter.cpp | 11 +-- 4 files changed, 60 insertions(+), 54 deletions(-) diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index 85b8fc549b01..969f27af6fb1 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -409,7 +409,7 @@ private: // Framework headers are spelled as , not // "path/FrameworkName.framework/Headers/Foo.h". auto &HS = PP->getHeaderSearchInfo(); - if (const auto *HFI = HS.getExistingFileInfo(*FE, /*WantExternal*/ false)) + if (const auto *HFI = HS.getExistingLocalFileInfo(*FE)) if (!HFI->Framework.empty()) if (auto Spelling = getFrameworkHeaderIncludeSpelling(*FE, HFI->Framework, HS)) diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index 855f81f775f8..c5f90ef4cb36 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -547,14 +547,15 @@ public: /// Return whether the specified file is a normal header, /// a system header, or a C++ friendly system header. SrcMgr::CharacteristicKind getFileDirFlavor(FileEntryRef File) { - return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo; + if (const HeaderFileInfo *HFI = getExistingFileInfo(File)) + return (SrcMgr::CharacteristicKind)HFI->DirInfo; + return (SrcMgr::CharacteristicKind)HeaderFileInfo().DirInfo; } /// Mark the specified file as a "once only" file due to /// \#pragma once. void MarkFileIncludeOnce(FileEntryRef File) { - HeaderFileInfo &FI = getFileInfo(File); - FI.isPragmaOnce = true; + getFileInfo(File).isPragmaOnce = true; } /// Mark the specified file as a system header, e.g. due to @@ -834,16 +835,17 @@ public: unsigned header_file_size() const { return FileInfo.size(); } - /// Return the HeaderFileInfo structure for the specified FileEntry, - /// in preparation for updating it in some way. + /// Return the HeaderFileInfo structure for the specified FileEntry, in + /// preparation for updating it in some way. HeaderFileInfo &getFileInfo(FileEntryRef FE); - /// Return the HeaderFileInfo structure for the specified FileEntry, - /// if it has ever been filled in. - /// \param WantExternal Whether the caller wants purely-external header file - /// info (where \p External is true). - const HeaderFileInfo *getExistingFileInfo(FileEntryRef FE, - bool WantExternal = true) const; + /// Return the HeaderFileInfo structure for the specified FileEntry, if it has + /// ever been filled in (either locally or externally). + const HeaderFileInfo *getExistingFileInfo(FileEntryRef FE) const; + + /// Return the headerFileInfo structure for the specified FileEntry, if it has + /// ever been filled in locally. + const HeaderFileInfo *getExistingLocalFileInfo(FileEntryRef FE) const; SearchDirIterator search_dir_begin() { return {*this, 0}; } SearchDirIterator search_dir_end() { return {*this, SearchDirs.size()}; } diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index f0750e5336b6..0632882b2961 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -946,9 +946,13 @@ OptionalFileEntryRef HeaderSearch::LookupFile( // If we have no includer, that means we're processing a #include // from a module build. We should treat this as a system header if we're // building a [system] module. - bool IncluderIsSystemHeader = - Includer ? getFileInfo(*Includer).DirInfo != SrcMgr::C_User : - BuildSystemModule; + bool IncluderIsSystemHeader = [&]() { + if (!Includer) + return BuildSystemModule; + const HeaderFileInfo *HFI = getExistingFileInfo(*Includer); + assert(HFI && "includer without file info"); + return HFI->DirInfo != SrcMgr::C_User; + }(); if (OptionalFileEntryRef FE = getFileAndSuggestModule( TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader, RequestingModule, SuggestedModule)) { @@ -963,10 +967,11 @@ OptionalFileEntryRef HeaderSearch::LookupFile( // Note that we only use one of FromHFI/ToHFI at once, due to potential // reallocation of the underlying vector potentially making the first // reference binding dangling. - HeaderFileInfo &FromHFI = getFileInfo(*Includer); - unsigned DirInfo = FromHFI.DirInfo; - bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader; - StringRef Framework = FromHFI.Framework; + const HeaderFileInfo *FromHFI = getExistingFileInfo(*Includer); + assert(FromHFI && "includer without file info"); + unsigned DirInfo = FromHFI->DirInfo; + bool IndexHeaderMapHeader = FromHFI->IndexHeaderMapHeader; + StringRef Framework = FromHFI->Framework; HeaderFileInfo &ToHFI = getFileInfo(*FE); ToHFI.DirInfo = DirInfo; @@ -1153,10 +1158,12 @@ OptionalFileEntryRef HeaderSearch::LookupFile( // "Foo" is the name of the framework in which the including header was found. if (!Includers.empty() && Includers.front().first && !isAngled && !Filename.contains('/')) { - HeaderFileInfo &IncludingHFI = getFileInfo(*Includers.front().first); - if (IncludingHFI.IndexHeaderMapHeader) { + const HeaderFileInfo *IncludingHFI = + getExistingFileInfo(*Includers.front().first); + assert(IncludingHFI && "includer without file info"); + if (IncludingHFI->IndexHeaderMapHeader) { SmallString<128> ScratchFilename; - ScratchFilename += IncludingHFI.Framework; + ScratchFilename += IncludingHFI->Framework; ScratchFilename += '/'; ScratchFilename += Filename; @@ -1286,11 +1293,11 @@ OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader( } // This file is a system header or C++ unfriendly if the old file is. - // - // Note that the temporary 'DirInfo' is required here, as either call to - // getFileInfo could resize the vector and we don't want to rely on order - // of evaluation. - unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; + const HeaderFileInfo *ContextHFI = getExistingFileInfo(ContextFileEnt); + assert(ContextHFI && "context file without file info"); + // Note that the temporary 'DirInfo' is required here, as the call to + // getFileInfo could resize the vector and might invalidate 'ContextHFI'. + unsigned DirInfo = ContextHFI->DirInfo; getFileInfo(*File).DirInfo = DirInfo; FrameworkName.pop_back(); // remove the trailing '/' @@ -1348,8 +1355,6 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI, HFI.Framework = OtherHFI.Framework; } -/// getFileInfo - Return the HeaderFileInfo structure for the specified -/// FileEntry. HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) { if (FE.getUID() >= FileInfo.size()) FileInfo.resize(FE.getUID() + 1); @@ -1366,27 +1371,20 @@ HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) { } HFI->IsValid = true; - // We have local information about this header file, so it's no longer - // strictly external. + // We assume the caller has local information about this header file, so it's + // no longer strictly external. HFI->External = false; return *HFI; } -const HeaderFileInfo * -HeaderSearch::getExistingFileInfo(FileEntryRef FE, bool WantExternal) const { - // If we have an external source, ensure we have the latest information. - // FIXME: Use a generation count to check whether this is really up to date. +const HeaderFileInfo *HeaderSearch::getExistingFileInfo(FileEntryRef FE) const { HeaderFileInfo *HFI; if (ExternalSource) { - if (FE.getUID() >= FileInfo.size()) { - if (!WantExternal) - return nullptr; + if (FE.getUID() >= FileInfo.size()) FileInfo.resize(FE.getUID() + 1); - } HFI = &FileInfo[FE.getUID()]; - if (!WantExternal && (!HFI->IsValid || HFI->External)) - return nullptr; + // FIXME: Use a generation count to check whether this is really up to date. if (!HFI->Resolved) { auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); if (ExternalHFI.IsValid) { @@ -1395,16 +1393,25 @@ HeaderSearch::getExistingFileInfo(FileEntryRef FE, bool WantExternal) const { mergeHeaderFileInfo(*HFI, ExternalHFI); } } - } else if (FE.getUID() >= FileInfo.size()) { - return nullptr; - } else { + } else if (FE.getUID() < FileInfo.size()) { HFI = &FileInfo[FE.getUID()]; + } else { + HFI = nullptr; } - if (!HFI->IsValid || (HFI->External && !WantExternal)) - return nullptr; + return (HFI && HFI->IsValid) ? HFI : nullptr; +} + +const HeaderFileInfo * +HeaderSearch::getExistingLocalFileInfo(FileEntryRef FE) const { + HeaderFileInfo *HFI; + if (FE.getUID() < FileInfo.size()) { + HFI = &FileInfo[FE.getUID()]; + } else { + HFI = nullptr; + } - return HFI; + return (HFI && HFI->IsValid && !HFI->External) ? HFI : nullptr; } bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ffc53292e391..330dbd623350 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -185,8 +185,7 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { if (!File) continue; - const HeaderFileInfo *HFI = - HS.getExistingFileInfo(*File, /*WantExternal*/ false); + const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File); if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) continue; @@ -2052,14 +2051,12 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { if (!File) continue; - // Get the file info. This will load info from the external source if - // necessary. Skip emitting this file if we have no information on it - // as a header file (in which case HFI will be null) or if it hasn't + // Get the file info. Skip emitting this file if we have no information on + // it as a header file (in which case HFI will be null) or if it hasn't // changed since it was loaded. Also skip it if it's for a modular header // from a different module; in that case, we rely on the module(s) // containing the header to provide this information. - const HeaderFileInfo *HFI = - HS.getExistingFileInfo(*File, /*WantExternal*/!Chain); + const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File); if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) continue; -- GitLab From 95fbd8d19dff10b5a734e3db1b29cba2da7a983f Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Thu, 11 Apr 2024 15:22:35 -0700 Subject: [PATCH 009/464] [clangd] Don't ignore external HFI in `SymbolCollector` (#88446) The `FileEntry` corresponds to a `FileID` containing the `SourceLocation` of a `NamedDecl` which (I think) might've been deserialized from a PCM file. Considering external `HeaderFileInfo` here is most likely the right thing to do here in order to get the correct spelling in case the current compiler instance has not register this file as a header yet. --- clang-tools-extra/clangd/index/SymbolCollector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index 969f27af6fb1..5c4e2150cf31 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -409,7 +409,7 @@ private: // Framework headers are spelled as , not // "path/FrameworkName.framework/Headers/Foo.h". auto &HS = PP->getHeaderSearchInfo(); - if (const auto *HFI = HS.getExistingLocalFileInfo(*FE)) + if (const auto *HFI = HS.getExistingFileInfo(*FE)) if (!HFI->Framework.empty()) if (auto Spelling = getFrameworkHeaderIncludeSpelling(*FE, HFI->Framework, HS)) -- GitLab From 9a36077e4db30c7da603620762036d4a430e4e62 Mon Sep 17 00:00:00 2001 From: jimingham Date: Thu, 11 Apr 2024 15:22:58 -0700 Subject: [PATCH 010/464] Fix error in unrecognized register name handling for "SBFrame.register" (#88047) The code returned lldb.SBValue() when you passed in an unrecognized register name. But referring to "lldb" is apparently not legal within the module. I changed this to just return SBValue(), but then this construct: (lldb) script >>> for reg_set in lldb.target.process.thread[0].frames[0].register ... print(reg) Runs forever printing "No Value". The __getitem__(key) gets called with a monotonically increasing by 1 series of integers. I don't know why Python decided the class we defined should have a generator that returns positive integers in order, but we can add a more useful one here by returning an iterator over the flattened list of registers. Note, the not very aptly named "SBFrame.registers" is an iterator over register sets, not registers, so the two are not redundant. --- lldb/bindings/interface/SBFrameExtensions.i | 12 +++++++++++- lldb/test/API/python_api/frame/TestFrames.py | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lldb/bindings/interface/SBFrameExtensions.i b/lldb/bindings/interface/SBFrameExtensions.i index 43b22ed7a6b3..e0472280666a 100644 --- a/lldb/bindings/interface/SBFrameExtensions.i +++ b/lldb/bindings/interface/SBFrameExtensions.i @@ -44,6 +44,16 @@ STRING_EXTENSION_OUTSIDE(SBFrame) def __init__(self, regs): self.regs = regs + def __iter__(self): + return self.get_registers() + + def get_registers(self): + for i in range(0,len(self.regs)): + rs = self.regs[i] + for j in range (0,rs.num_children): + reg = rs.GetChildAtIndex(j) + yield reg + def __getitem__(self, key): if type(key) is str: for i in range(0,len(self.regs)): @@ -52,7 +62,7 @@ STRING_EXTENSION_OUTSIDE(SBFrame) reg = rs.GetChildAtIndex(j) if reg.name == key: return reg else: - return lldb.SBValue() + return SBValue() return registers_access(self.registers) diff --git a/lldb/test/API/python_api/frame/TestFrames.py b/lldb/test/API/python_api/frame/TestFrames.py index a82b129bc809..dfa96d51830b 100644 --- a/lldb/test/API/python_api/frame/TestFrames.py +++ b/lldb/test/API/python_api/frame/TestFrames.py @@ -73,7 +73,19 @@ class FrameAPITestCase(TestBase): gpr_reg_set = lldbutil.get_GPRs(frame) pc_value = gpr_reg_set.GetChildMemberWithName("pc") self.assertTrue(pc_value, "We should have a valid PC.") + # Make sure we can also get this from the "register" property: + iterator_pc_value = 0 + found_pc = False + for reg in frame.register: + if reg.name == "pc": + found_pc = True + iterator_pc_value = int(reg.GetValue(), 0) + break + pc_value_int = int(pc_value.GetValue(), 0) + self.assertTrue(found_pc, "Found the PC value in the register list") + self.assertEqual(iterator_pc_value, pc_value_int, "The methods of finding pc match") + # Make sure on arm targets we dont mismatch PC value on the basis of thumb bit. # Frame PC will not have thumb bit set in case of a thumb # instruction as PC. -- GitLab From 4036a6946e5420bb77a93037c83732be600b9b0b Mon Sep 17 00:00:00 2001 From: Farzon Lotfi <1802579+farzonl@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:26:25 -0700 Subject: [PATCH 011/464] [HLSL] move rcp to cgbuiltins (#88401) Removing the intrinsic because there is no opCodes for rcp in DXIL or SPIR-V. Moving means we don't have to re-implement this feature for each backend. fixes #87784 Co-authored-by: Farzon Lotfi --- clang/lib/CodeGen/CGBuiltin.cpp | 13 +- clang/test/CodeGenHLSL/builtins/rcp.hlsl | 127 ++++++++++++------ .../Target/DirectX/DXILIntrinsicExpansion.cpp | 22 --- llvm/test/CodeGen/DirectX/rcp.ll | 52 ------- .../test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll | 126 +++++++++++++++++ 5 files changed, 224 insertions(+), 116 deletions(-) delete mode 100644 llvm/test/CodeGen/DirectX/rcp.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c052367d2878..c7b219dcfcec 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18303,9 +18303,16 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, Value *Op0 = EmitScalarExpr(E->getArg(0)); if (!E->getArg(0)->getType()->hasFloatingRepresentation()) llvm_unreachable("rcp operand must have a float representation"); - return Builder.CreateIntrinsic( - /*ReturnType=*/Op0->getType(), Intrinsic::dx_rcp, - ArrayRef{Op0}, nullptr, "dx.rcp"); + llvm::Type *Ty = Op0->getType(); + llvm::Type *EltTy = Ty->getScalarType(); + Constant *One = + Ty->isVectorTy() + ? ConstantVector::getSplat( + ElementCount::getFixed( + dyn_cast(Ty)->getNumElements()), + ConstantFP::get(EltTy, 1.0)) + : ConstantFP::get(EltTy, 1.0); + return Builder.CreateFDiv(One, Op0, "hlsl.rcp"); } case Builtin::BI__builtin_hlsl_elementwise_rsqrt: { Value *Op0 = EmitScalarExpr(E->getArg(0)); diff --git a/clang/test/CodeGenHLSL/builtins/rcp.hlsl b/clang/test/CodeGenHLSL/builtins/rcp.hlsl index 9b8406e1f0b6..eb89bcc4c7c0 100644 --- a/clang/test/CodeGenHLSL/builtins/rcp.hlsl +++ b/clang/test/CodeGenHLSL/builtins/rcp.hlsl @@ -1,53 +1,102 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: --check-prefixes=CHECK,DXIL_CHECK,DXIL_NATIVE_HALF,NATIVE_HALF // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF - -// NATIVE_HALF: define noundef half @ -// NATIVE_HALF: %dx.rcp = call half @llvm.dx.rcp.f16( -// NATIVE_HALF: ret half %dx.rcp -// NO_HALF: define noundef float @"?test_rcp_half@@YA$halff@$halff@@Z"( -// NO_HALF: %dx.rcp = call float @llvm.dx.rcp.f32( -// NO_HALF: ret float %dx.rcp +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXIL_CHECK,NO_HALF,DXIL_NO_HALF +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF,SPIR_NATIVE_HALF,SPIR_CHECK +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF,SPIR_NO_HALF,SPIR_CHECK + +// DXIL_NATIVE_HALF: define noundef half @ +// SPIR_NATIVE_HALF: define spir_func noundef half @ +// NATIVE_HALF: %hlsl.rcp = fdiv half 0xH3C00, %{{.*}} +// NATIVE_HALF: ret half %hlsl.rcp +// DXIL_NO_HALF: define noundef float @ +// SPIR_NO_HALF: define spir_func noundef float @ +// NO_HALF: %hlsl.rcp = fdiv float 1.000000e+00, %{{.*}} +// NO_HALF: ret float %hlsl.rcp half test_rcp_half(half p0) { return rcp(p0); } -// NATIVE_HALF: define noundef <2 x half> @ -// NATIVE_HALF: %dx.rcp = call <2 x half> @llvm.dx.rcp.v2f16 -// NATIVE_HALF: ret <2 x half> %dx.rcp -// NO_HALF: define noundef <2 x float> @ -// NO_HALF: %dx.rcp = call <2 x float> @llvm.dx.rcp.v2f32( -// NO_HALF: ret <2 x float> %dx.rcp + +// DXIL_NATIVE_HALF: define noundef <2 x half> @ +// SPIR_NATIVE_HALF: define spir_func noundef <2 x half> @ +// NATIVE_HALF: %hlsl.rcp = fdiv <2 x half> , %{{.*}} +// NATIVE_HALF: ret <2 x half> %hlsl.rcp +// DXIL_NO_HALF: define noundef <2 x float> @ +// SPIR_NO_HALF: define spir_func noundef <2 x float> @ +// NO_HALF: %hlsl.rcp = fdiv <2 x float> , %{{.*}} +// NO_HALF: ret <2 x float> %hlsl.rcp half2 test_rcp_half2(half2 p0) { return rcp(p0); } -// NATIVE_HALF: define noundef <3 x half> @ -// NATIVE_HALF: %dx.rcp = call <3 x half> @llvm.dx.rcp.v3f16 -// NATIVE_HALF: ret <3 x half> %dx.rcp -// NO_HALF: define noundef <3 x float> @ -// NO_HALF: %dx.rcp = call <3 x float> @llvm.dx.rcp.v3f32( -// NO_HALF: ret <3 x float> %dx.rcp + +// DXIL_NATIVE_HALF: define noundef <3 x half> @ +// SPIR_NATIVE_HALF: define spir_func noundef <3 x half> @ +// NATIVE_HALF: %hlsl.rcp = fdiv <3 x half> , %{{.*}} +// NATIVE_HALF: ret <3 x half> %hlsl.rcp +// DXIL_NO_HALF: define noundef <3 x float> @ +// SPIR_NO_HALF: define spir_func noundef <3 x float> @ +// NO_HALF: %hlsl.rcp = fdiv <3 x float> , %{{.*}} +// NO_HALF: ret <3 x float> %hlsl.rcp half3 test_rcp_half3(half3 p0) { return rcp(p0); } -// NATIVE_HALF: define noundef <4 x half> @ -// NATIVE_HALF: %dx.rcp = call <4 x half> @llvm.dx.rcp.v4f16 -// NATIVE_HALF: ret <4 x half> %dx.rcp -// NO_HALF: define noundef <4 x float> @ -// NO_HALF: %dx.rcp = call <4 x float> @llvm.dx.rcp.v4f32( -// NO_HALF: ret <4 x float> %dx.rcp + +// DXIL_NATIVE_HALF: define noundef <4 x half> @ +// SPIR_NATIVE_HALF: define spir_func noundef <4 x half> @ +// NATIVE_HALF: %hlsl.rcp = fdiv <4 x half> , %{{.*}} +// NATIVE_HALF: ret <4 x half> %hlsl.rcp +// DXIL_NO_HALF: define noundef <4 x float> @ +// SPIR_NO_HALF: define spir_func noundef <4 x float> @ +// NO_HALF: %hlsl.rcp = fdiv <4 x float> , %{{.*}} +// NO_HALF: ret <4 x float> %hlsl.rcp half4 test_rcp_half4(half4 p0) { return rcp(p0); } -// CHECK: define noundef float @ -// CHECK: %dx.rcp = call float @llvm.dx.rcp.f32( -// CHECK: ret float %dx.rcp +// DXIL_CHECK: define noundef float @ +// SPIR_CHECK: define spir_func noundef float @ +// CHECK: %hlsl.rcp = fdiv float 1.000000e+00, %{{.*}} +// CHECK: ret float %hlsl.rcp float test_rcp_float(float p0) { return rcp(p0); } -// CHECK: define noundef <2 x float> @ -// CHECK: %dx.rcp = call <2 x float> @llvm.dx.rcp.v2f32 -// CHECK: ret <2 x float> %dx.rcp + +// DXIL_CHECK: define noundef <2 x float> @ +// SPIR_CHECK: define spir_func noundef <2 x float> @ +// CHECK: %hlsl.rcp = fdiv <2 x float> , %{{.*}} +// CHECK: ret <2 x float> %hlsl.rcp float2 test_rcp_float2(float2 p0) { return rcp(p0); } -// CHECK: define noundef <3 x float> @ -// CHECK: %dx.rcp = call <3 x float> @llvm.dx.rcp.v3f32 -// CHECK: ret <3 x float> %dx.rcp + +// DXIL_CHECK: define noundef <3 x float> @ +// SPIR_CHECK: define spir_func noundef <3 x float> @ +// CHECK: %hlsl.rcp = fdiv <3 x float> , %{{.*}} +// CHECK: ret <3 x float> %hlsl.rcp float3 test_rcp_float3(float3 p0) { return rcp(p0); } -// CHECK: define noundef <4 x float> @ -// CHECK: %dx.rcp = call <4 x float> @llvm.dx.rcp.v4f32 -// CHECK: ret <4 x float> %dx.rcp + +// DXIL_CHECK: define noundef <4 x float> @ +// SPIR_CHECK: define spir_func noundef <4 x float> @ +// CHECK: %hlsl.rcp = fdiv <4 x float> , %{{.*}} +// CHECK: ret <4 x float> %hlsl.rcp float4 test_rcp_float4(float4 p0) { return rcp(p0); } + +// DXIL_CHECK: define noundef double @ +// SPIR_CHECK: define spir_func noundef double @ +// CHECK: %hlsl.rcp = fdiv double 1.000000e+00, %{{.*}} +// CHECK: ret double %hlsl.rcp +double test_rcp_double(double p0) { return rcp(p0); } + +// DXIL_CHECK: define noundef <2 x double> @ +// SPIR_CHECK: define spir_func noundef <2 x double> @ +// CHECK: %hlsl.rcp = fdiv <2 x double> , %{{.*}} +// CHECK: ret <2 x double> %hlsl.rcp +double2 test_rcp_double2(double2 p0) { return rcp(p0); } + +// DXIL_CHECK: define noundef <3 x double> @ +// SPIR_CHECK: define spir_func noundef <3 x double> @ +// CHECK: %hlsl.rcp = fdiv <3 x double> , %{{.*}} +// CHECK: ret <3 x double> %hlsl.rcp +double3 test_rcp_double3(double3 p0) { return rcp(p0); } + +// DXIL_CHECK: define noundef <4 x double> @ +// SPIR_CHECK: define spir_func noundef <4 x double> @ +// CHECK: %hlsl.rcp = fdiv <4 x double> , %{{.*}} +// CHECK: ret <4 x double> %hlsl.rcp +double4 test_rcp_double4(double4 p0) { return rcp(p0); } diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index 3e2d10f5ee7a..4d99bc006900 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -42,7 +42,6 @@ static bool isIntrinsicExpansion(Function &F) { case Intrinsic::dx_clamp: case Intrinsic::dx_uclamp: case Intrinsic::dx_lerp: - case Intrinsic::dx_rcp: case Intrinsic::dx_sdot: case Intrinsic::dx_udot: return true; @@ -218,25 +217,6 @@ static bool expandPowIntrinsic(CallInst *Orig) { return true; } -static bool expandRcpIntrinsic(CallInst *Orig) { - Value *X = Orig->getOperand(0); - IRBuilder<> Builder(Orig->getParent()); - Builder.SetInsertPoint(Orig); - Type *Ty = X->getType(); - Type *EltTy = Ty->getScalarType(); - Constant *One = - Ty->isVectorTy() - ? ConstantVector::getSplat( - ElementCount::getFixed( - dyn_cast(Ty)->getNumElements()), - ConstantFP::get(EltTy, 1.0)) - : ConstantFP::get(EltTy, 1.0); - auto *Result = Builder.CreateFDiv(One, X, "dx.rcp"); - Orig->replaceAllUsesWith(Result); - Orig->eraseFromParent(); - return true; -} - static Intrinsic::ID getMaxForClamp(Type *ElemTy, Intrinsic::ID ClampIntrinsic) { if (ClampIntrinsic == Intrinsic::dx_uclamp) @@ -300,8 +280,6 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) { return expandClampIntrinsic(Orig, F.getIntrinsicID()); case Intrinsic::dx_lerp: return expandLerpIntrinsic(Orig); - case Intrinsic::dx_rcp: - return expandRcpIntrinsic(Orig); case Intrinsic::dx_sdot: case Intrinsic::dx_udot: return expandIntegerDot(Orig, F.getIntrinsicID()); diff --git a/llvm/test/CodeGen/DirectX/rcp.ll b/llvm/test/CodeGen/DirectX/rcp.ll deleted file mode 100644 index 65abe832db53..000000000000 --- a/llvm/test/CodeGen/DirectX/rcp.ll +++ /dev/null @@ -1,52 +0,0 @@ -; RUN: opt -S -dxil-op-lower < %s | FileCheck %s - -; Make sure dxil operation function calls for rcp are generated for float, double, and half. - -; CHECK-LABEL: rcp_float4 -; CHECK: fdiv <4 x float> , %{{.*}} -define noundef <4 x float> @rcp_float4(<4 x float> noundef %p0) { -entry: - %p0.addr = alloca <4 x float>, align 16 - store <4 x float> %p0, ptr %p0.addr, align 16 - %0 = load <4 x float>, ptr %p0.addr, align 16 - %dx.rcp = call <4 x float> @llvm.dx.rcp.v4f32(<4 x float> %0) - ret <4 x float> %dx.rcp -} - -; CHECK-LABEL: rcp_double4 -; CHECK: fdiv <4 x double> , %{{.*}} -define noundef <4 x double> @rcp_double4(<4 x double> noundef %p0) { -entry: - %p0.addr = alloca <4 x double>, align 16 - store <4 x double> %p0, ptr %p0.addr, align 16 - %0 = load <4 x double>, ptr %p0.addr, align 16 - %dx.rcp = call <4 x double> @llvm.dx.rcp.v4f64(<4 x double> %0) - ret <4 x double> %dx.rcp -} - -; CHECK-LABEL: rcp_half4 -; CHECK: fdiv <4 x half> , %{{.*}} -define noundef <4 x half> @rcp_half4(<4 x half> noundef %p0) { -entry: - %p0.addr = alloca <4 x half>, align 16 - store <4 x half> %p0, ptr %p0.addr, align 16 - %0 = load <4 x half>, ptr %p0.addr, align 16 - %dx.rcp = call <4 x half> @llvm.dx.rcp.v4f16(<4 x half> %0) - ret <4 x half> %dx.rcp -} - -; CHECK-LABEL: rcp_half -; CHECK: fdiv half 0xH3C00, %{{.*}} -define noundef half @rcp_half(half noundef %p0) { -entry: - %p0.addr = alloca half, align 2 - store half %p0, ptr %p0.addr, align 2 - %0 = load half, ptr %p0.addr, align 2 - %dx.rcp = call half @llvm.dx.rcp.f16(half %0) - ret half %dx.rcp -} - -declare half @llvm.dx.rcp.f16(half) -declare <4 x half> @llvm.dx.rcp.v4f16(<4 x half>) -declare <4 x float> @llvm.dx.rcp.v4f32(<4 x float>) -declare <4 x double> @llvm.dx.rcp.v4f64(<4 x double>) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll new file mode 100644 index 000000000000..95962c0fdc96 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll @@ -0,0 +1,126 @@ + ; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s + +; CHECK-DAG: %[[#float_64:]] = OpTypeFloat 64 +; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16 +; CHECK-DAG: %[[#vec2_float_16:]] = OpTypeVector %[[#float_16]] 2 +; CHECK-DAG: %[[#vec2_float_32:]] = OpTypeVector %[[#float_32]] 2 +; CHECK-DAG: %[[#vec2_float_64:]] = OpTypeVector %[[#float_64]] 2 +; CHECK-DAG: %[[#vec3_float_16:]] = OpTypeVector %[[#float_16]] 3 +; CHECK-DAG: %[[#vec3_float_32:]] = OpTypeVector %[[#float_32]] 3 +; CHECK-DAG: %[[#vec3_float_64:]] = OpTypeVector %[[#float_64]] 3 +; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4 +; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4 +; CHECK-DAG: %[[#vec4_float_64:]] = OpTypeVector %[[#float_64]] 4 +; CHECK-DAG: %[[#const_f64_1:]] = OpConstant %[[#float_64]] 1 +; CHECK-DAG: %[[#const_f32_1:]] = OpConstant %[[#float_32:]] 1 +; CHECK-DAG: %[[#const_f16_1:]] = OpConstant %[[#float_16:]] 1 + +; CHECK-DAG: %[[#vec2_const_ones_f16:]] = OpConstantComposite %[[#vec2_float_16:]] %[[#const_f16_1:]] %[[#const_f16_1:]] +; CHECK-DAG: %[[#vec3_const_ones_f16:]] = OpConstantComposite %[[#vec3_float_16:]] %[[#const_f16_1:]] %[[#const_f16_1:]] %[[#const_f16_1:]] +; CHECK-DAG: %[[#vec4_const_ones_f16:]] = OpConstantComposite %[[#vec4_float_16:]] %[[#const_f16_1:]] %[[#const_f16_1:]] %[[#const_f16_1:]] %[[#const_f16_1:]] + +; CHECK-DAG: %[[#vec2_const_ones_f32:]] = OpConstantComposite %[[#vec2_float_32:]] %[[#const_f32_1:]] %[[#const_f32_1:]] +; CHECK-DAG: %[[#vec3_const_ones_f32:]] = OpConstantComposite %[[#vec3_float_32:]] %[[#const_f32_1:]] %[[#const_f32_1:]] %[[#const_f32_1:]] +; CHECK-DAG: %[[#vec4_const_ones_f32:]] = OpConstantComposite %[[#vec4_float_32:]] %[[#const_f32_1:]] %[[#const_f32_1:]] %[[#const_f32_1:]] %[[#const_f32_1:]] + +; CHECK-DAG: %[[#vec2_const_ones_f64:]] = OpConstantComposite %[[#vec2_float_64:]] %[[#const_f64_1:]] %[[#const_f64_1:]] +; CHECK-DAG: %[[#vec3_const_ones_f64:]] = OpConstantComposite %[[#vec3_float_64:]] %[[#const_f64_1:]] %[[#const_f64_1:]] %[[#const_f64_1:]] +; CHECK-DAG: %[[#vec4_const_ones_f64:]] = OpConstantComposite %[[#vec4_float_64:]] %[[#const_f64_1:]] %[[#const_f64_1:]] %[[#const_f64_1:]] %[[#const_f64_1:]] + + +define spir_func noundef half @test_rcp_half(half noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16:]] + ; CHECK: OpFDiv %[[#float_16:]] %[[#const_f16_1:]] %[[#arg0:]] + %hlsl.rcp = fdiv half 0xH3C00, %p0 + ret half %hlsl.rcp +} + +define spir_func noundef <2 x half> @test_rcp_half2(<2 x half> noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec2_float_16:]] + ; CHECK: OpFDiv %[[#vec2_float_16:]] %[[#vec2_const_ones_f16:]] %[[#arg0:]] + %hlsl.rcp = fdiv <2 x half> , %p0 + ret <2 x half> %hlsl.rcp +} + +define spir_func noundef <3 x half> @test_rcp_half3(<3 x half> noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_16:]] + ; CHECK: OpFDiv %[[#vec3_float_16:]] %[[#vec3_const_ones_f16:]] %[[#arg0:]] + %hlsl.rcp = fdiv <3 x half> , %p0 + ret <3 x half> %hlsl.rcp +} + +define spir_func noundef <4 x half> @test_rcp_half4(<4 x half> noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16:]] + ; CHECK: OpFDiv %[[#vec4_float_16:]] %[[#vec4_const_ones_f16:]] %[[#arg0:]] + %hlsl.rcp = fdiv <4 x half> , %p0 + ret <4 x half> %hlsl.rcp +} + +define spir_func noundef float @test_rcp_float(float noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32:]] + ; CHECK: OpFDiv %[[#float_32:]] %[[#const_f32_1:]] %[[#arg0:]] + %hlsl.rcp = fdiv float 1.000000e+00, %p0 + ret float %hlsl.rcp +} + +define spir_func noundef <2 x float> @test_rcp_float2(<2 x float> noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec2_float_32:]] + ; CHECK: OpFDiv %[[#vec2_float_32:]] %[[#vec2_const_ones_f32:]] %[[#arg0:]] + %hlsl.rcp = fdiv <2 x float> , %p0 + ret <2 x float> %hlsl.rcp +} + +define spir_func noundef <3 x float> @test_rcp_float3(<3 x float> noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_32:]] + ; CHECK: OpFDiv %[[#vec3_float_32:]] %[[#vec3_const_ones_f32:]] %[[#arg0:]] + %hlsl.rcp = fdiv <3 x float> , %p0 + ret <3 x float> %hlsl.rcp +} + +define spir_func noundef <4 x float> @test_rcp_float4(<4 x float> noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32:]] + ; CHECK: OpFDiv %[[#vec4_float_32:]] %[[#vec4_const_ones_f32:]] %[[#arg0:]] + %hlsl.rcp = fdiv <4 x float> , %p0 + ret <4 x float> %hlsl.rcp +} + +define spir_func noundef double @test_rcp_double(double noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_64:]] + ; CHECK: OpFDiv %[[#float_64:]] %[[#const_f64_1:]] %[[#arg0:]] + %hlsl.rcp = fdiv double 1.000000e+00, %p0 + ret double %hlsl.rcp +} + +define spir_func noundef <2 x double> @test_rcp_double2(<2 x double> noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec2_float_64:]] + ; CHECK: OpFDiv %[[#vec2_float_64:]] %[[#vec2_const_ones_f64:]] %[[#arg0:]] + %hlsl.rcp = fdiv <2 x double> , %p0 + ret <2 x double> %hlsl.rcp +} + +define spir_func noundef <3 x double> @test_rcp_double3(<3 x double> noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_64:]] + ; CHECK: OpFDiv %[[#vec3_float_64:]] %[[#vec3_const_ones_f64:]] %[[#arg0:]] + %hlsl.rcp = fdiv <3 x double> , %p0 + ret <3 x double> %hlsl.rcp +} + +define spir_func noundef <4 x double> @test_rcp_double4(<4 x double> noundef %p0) #0 { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_64:]] + ; CHECK: OpFDiv %[[#vec4_float_64:]] %[[#vec4_const_ones_f64:]] %[[#arg0:]] + %hlsl.rcp = fdiv <4 x double> , %p0 + ret <4 x double> %hlsl.rcp +} -- GitLab From 00a4f091bad199053b33af983a5abbf2c5abe949 Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Thu, 11 Apr 2024 15:51:27 -0700 Subject: [PATCH 012/464] [clang][docs] Modernize attribute docs for darwin specifics (#88448) * Generally recommend target triples. But replace `m*version-min` with `mtargetos`. * Also include test coverage for -mtargetos=visionos --- clang/include/clang/Basic/AttrDocs.td | 37 ++++++++++++++++++--------- clang/test/Driver/mtargetos-darwin.c | 2 ++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 0ca4ea377fc3..8687c4f57d3f 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1604,27 +1604,40 @@ specifies availability for the current target platform, the availability attributes are ignored. Supported platforms are: ``ios`` - Apple's iOS operating system. The minimum deployment target is specified by - the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*`` - command-line arguments. + Apple's iOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-ios*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=ios*version*`` + command-line argument. ``macos`` - Apple's macOS operating system. The minimum deployment target is - specified by the ``-mmacosx-version-min=*version*`` command-line argument. - ``macosx`` is supported for backward-compatibility reasons, but it is - deprecated. + Apple's macOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-macos*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=macos*version*`` + command-line argument. ``macosx`` is supported for + backward-compatibility reasons, but it is deprecated. ``tvos`` - Apple's tvOS operating system. The minimum deployment target is specified by - the ``-mtvos-version-min=*version*`` command-line argument. + Apple's tvOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-tvos*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=tvos*version*`` + command-line argument. ``watchos`` - Apple's watchOS operating system. The minimum deployment target is specified by - the ``-mwatchos-version-min=*version*`` command-line argument. + Apple's watchOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-watchos*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=watchos*version*`` + command-line argument. + +``visionos`` + Apple's visionOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-visionos*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=visionos*version*`` + command-line argument. ``driverkit`` Apple's DriverKit userspace kernel extensions. The minimum deployment target - is specified as part of the triple. + is specified as part of the ``-target *arch*-apple-driverkit*version*`` + command line argument. A declaration can typically be used even when deploying back to a platform version prior to when the declaration was introduced. When this happens, the diff --git a/clang/test/Driver/mtargetos-darwin.c b/clang/test/Driver/mtargetos-darwin.c index e706be37a371..7e86ab15279b 100644 --- a/clang/test/Driver/mtargetos-darwin.c +++ b/clang/test/Driver/mtargetos-darwin.c @@ -4,6 +4,7 @@ // RUN: %clang -mtargetos=ios14-macabi -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=MACCATALYST %s // RUN: %clang -mtargetos=tvos14 -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=TVOS %s // RUN: %clang -mtargetos=watchos7.1 -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=WATCHOS %s +// RUN: %clang -mtargetos=visionos1 -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=VISIONOS %s // RUN: not %clang -target arm64-apple-ios14 -mtargetos=ios14 -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=NOMIX1 %s // RUN: not %clang -mtargetos=ios14 -arch arm64 -miphoneos-version-min=14 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=NOMIX2 %s @@ -19,6 +20,7 @@ // MACCATALYST: "-cc1" "-triple" "arm64-apple-ios14.0.0-macabi" // TVOS: "-cc1" "-triple" "arm64-apple-tvos14.0.0" // WATCHOS: "-cc1" "-triple" "arm64-apple-watchos7.1.0" +// VISIONOS: "-cc1" "-triple" "arm64-apple-xros1.0.0" // NOMIX1: error: cannot specify '-mtargetos=ios14' along with '-target arm64-apple-ios14' // NOMIX2: error: cannot specify '-miphoneos-version-min=14' along with '-mtargetos=ios14' -- GitLab From 43d0891d3bb1fc40ff5dcea91c28d1582978caff Mon Sep 17 00:00:00 2001 From: Maksim Panchenko Date: Thu, 11 Apr 2024 16:11:00 -0700 Subject: [PATCH 013/464] [BOLT] Fix handling of trailing entries in jump tables (#88444) If a jump table has entries at the end that are a result of __builtin_unreachable() targets, BOLT can confuse them with function pointers. In such case, we should exclude these targets from the table as we risk incorrectly updating the function pointers. It is safe to exclude them as branching on such targets is considered an undefined behavior. --- bolt/lib/Core/BinaryContext.cpp | 26 ++++- bolt/test/runtime/X86/jt-confusion.s | 164 +++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 bolt/test/runtime/X86/jt-confusion.s diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index 47eae964e816..7c2d8c52287b 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -555,6 +555,9 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address, const uint64_t NextJTAddress, JumpTable::AddressesType *EntriesAsAddress, bool *HasEntryInFragment) const { + // Target address of __builtin_unreachable. + const uint64_t UnreachableAddress = BF.getAddress() + BF.getSize(); + // Is one of the targets __builtin_unreachable? bool HasUnreachable = false; @@ -564,9 +567,15 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address, // Number of targets other than __builtin_unreachable. uint64_t NumRealEntries = 0; - auto addEntryAddress = [&](uint64_t EntryAddress) { - if (EntriesAsAddress) - EntriesAsAddress->emplace_back(EntryAddress); + // Size of the jump table without trailing __builtin_unreachable entries. + size_t TrimmedSize = 0; + + auto addEntryAddress = [&](uint64_t EntryAddress, bool Unreachable = false) { + if (!EntriesAsAddress) + return; + EntriesAsAddress->emplace_back(EntryAddress); + if (!Unreachable) + TrimmedSize = EntriesAsAddress->size(); }; ErrorOr Section = getSectionForAddress(Address); @@ -618,8 +627,8 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address, : *getPointerAtAddress(EntryAddress); // __builtin_unreachable() case. - if (Value == BF.getAddress() + BF.getSize()) { - addEntryAddress(Value); + if (Value == UnreachableAddress) { + addEntryAddress(Value, /*Unreachable*/ true); HasUnreachable = true; LLVM_DEBUG(dbgs() << formatv("OK: {0:x} __builtin_unreachable\n", Value)); continue; @@ -673,6 +682,13 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address, addEntryAddress(Value); } + // Trim direct/normal jump table to exclude trailing unreachable entries that + // can collide with a function address. + if (Type == JumpTable::JTT_NORMAL && EntriesAsAddress && + TrimmedSize != EntriesAsAddress->size() && + getBinaryFunctionAtAddress(UnreachableAddress)) + EntriesAsAddress->resize(TrimmedSize); + // It's a jump table if the number of real entries is more than 1, or there's // one real entry and one or more special targets. If there are only multiple // special targets, then it's not a jump table. diff --git a/bolt/test/runtime/X86/jt-confusion.s b/bolt/test/runtime/X86/jt-confusion.s new file mode 100644 index 000000000000..f15c83b35b6a --- /dev/null +++ b/bolt/test/runtime/X86/jt-confusion.s @@ -0,0 +1,164 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: llvm-strip --strip-unneeded %t.o +# RUN: %clang %cflags -no-pie -nostartfiles -nostdlib -lc %t.o -o %t.exe -Wl,-q + +# RUN: llvm-bolt %t.exe -o %t.exe.bolt --relocs=1 --lite=0 + +# RUN: %t.exe.bolt + +## Check that BOLT's jump table detection diffrentiates between +## __builtin_unreachable() targets and function pointers. + +## The test case was built from the following two source files and +## modiffied for standalone build. main became _start, etc. +## $ $(CC) a.c -O1 -S -o a.s +## $ $(CC) b.c -O0 -S -o b.s + +## a.c: + +## typedef int (*fptr)(int); +## void check_fptr(fptr, int); +## +## int foo(int a) { +## check_fptr(foo, 0); +## switch (a) { +## default: +## __builtin_unreachable(); +## case 0: +## return 3; +## case 1: +## return 5; +## case 2: +## return 7; +## case 3: +## return 11; +## case 4: +## return 13; +## case 5: +## return 17; +## } +## return 0; +## } +## +## int main(int argc) { +## check_fptr(main, 1); +## return foo(argc); +## } +## +## const fptr funcs[2] = {foo, main}; + +## b.c.: + +## typedef int (*fptr)(int); +## extern const fptr funcs[2]; +## +## #define assert(C) { if (!(C)) (*(unsigned long long *)0) = 0; } +## void check_fptr(fptr f, int i) { +## assert(f == funcs[i]); +## } + + + .text + .globl foo + .type foo, @function +foo: +.LFB0: + .cfi_startproc + pushq %rbx + .cfi_def_cfa_offset 16 + .cfi_offset 3, -16 + movl %edi, %ebx + movl $0, %esi + movl $foo, %edi + call check_fptr + movl %ebx, %ebx + jmp *.L4(,%rbx,8) +.L8: + movl $5, %eax + jmp .L1 +.L7: + movl $7, %eax + jmp .L1 +.L6: + movl $11, %eax + jmp .L1 +.L5: + movl $13, %eax + jmp .L1 +.L3: + movl $17, %eax + jmp .L1 +.L10: + movl $3, %eax +.L1: + popq %rbx + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE0: + .size foo, .-foo + .globl _start + .type _start, @function +_start: +.LFB1: + .cfi_startproc + pushq %rbx + .cfi_def_cfa_offset 16 + .cfi_offset 3, -16 + movl %edi, %ebx + movl $1, %esi + movl $_start, %edi + call check_fptr + movl $1, %edi + call foo + popq %rbx + .cfi_def_cfa_offset 8 + callq exit@PLT + .cfi_endproc +.LFE1: + .size _start, .-_start + .globl check_fptr + .type check_fptr, @function +check_fptr: +.LFB2: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movq %rdi, -8(%rbp) + movl %esi, -12(%rbp) + movl -12(%rbp), %eax + cltq + movq funcs(,%rax,8), %rax + cmpq %rax, -8(%rbp) + je .L33 + movl $0, %eax + movq $0, (%rax) +.L33: + nop + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc + + .section .rodata + .align 8 + .align 4 +.L4: + .quad .L10 + .quad .L8 + .quad .L7 + .quad .L6 + .quad .L5 + .quad .L3 + + .globl funcs + .type funcs, @object + .size funcs, 16 +funcs: + .quad foo + .quad _start -- GitLab From 2f55056c89dd1ccb1aa69a9aed68048a59413d4d Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Thu, 11 Apr 2024 16:13:54 -0700 Subject: [PATCH 014/464] [compiler-rt] Don't explicitly ad-hoc code sign dylibs if using Apple's new linker (#88323) Apple's new linker reports itself as ld rather than ld64 and does not match the version detection regex. Invert the logic to look only for older versions of ld64. This ensures the runtime dylibs are left with a linker-generated code signature that tools such as `strip` will preserve. Co-authored-by: Mark Rowe --- compiler-rt/cmake/Modules/AddCompilerRT.cmake | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/compiler-rt/cmake/Modules/AddCompilerRT.cmake index e0400a8ea952..dc36f16c661c 100644 --- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -405,11 +405,14 @@ function(add_compiler_rt_runtime name type) if (HAD_ERROR) message(FATAL_ERROR "${CMAKE_LINKER} failed with status ${HAD_ERROR}") endif() - set(NEED_EXPLICIT_ADHOC_CODESIGN 1) + set(NEED_EXPLICIT_ADHOC_CODESIGN 0) + # Apple introduced a new linker by default in Xcode 15. This linker reports itself as ld + # rather than ld64 and does not match this version regex. That's ok since it never needs + # the explicit ad-hoc code signature. if ("${LD_V_OUTPUT}" MATCHES ".*ld64-([0-9.]+).*") string(REGEX REPLACE ".*ld64-([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT}) - if (HOST_LINK_VERSION VERSION_GREATER_EQUAL 609) - set(NEED_EXPLICIT_ADHOC_CODESIGN 0) + if (HOST_LINK_VERSION VERSION_LESS 609) + set(NEED_EXPLICIT_ADHOC_CODESIGN 1) endif() endif() if (NEED_EXPLICIT_ADHOC_CODESIGN) -- GitLab From 5fb821560afd0543e4875c3c81d58f68f73eb03b Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Thu, 11 Apr 2024 16:26:49 -0700 Subject: [PATCH 015/464] [libc] add remaining epoll functions, pipe (#84587) The epoll_wait functions need the rest of the epoll functions (create, ctl) to be available to actually test them, as well as pipe to create a usable file descriptor. This patch adds epoll_create, epoll_create1, epoll_ctl, and pipe. These have tests, and the tests for epoll_wait, epoll_pwait, and epoll_pwait2 (currently disabled) are updated to use these newly available functions. --- libc/config/linux/x86_64/entrypoints.txt | 4 + libc/hdr/CMakeLists.txt | 18 +++ libc/hdr/signal_macros.h | 22 ++++ libc/hdr/sys_epoll_macros.h | 22 ++++ libc/include/CMakeLists.txt | 1 + libc/include/llvm-libc-macros/CMakeLists.txt | 6 + .../llvm-libc-macros/linux/CMakeLists.txt | 6 + .../llvm-libc-macros/linux/sys-epoll-macros.h | 40 +++++++ .../llvm-libc-macros/sys-epoll-macros.h | 16 +++ libc/include/llvm-libc-types/sigset_t.h | 4 +- .../llvm-libc-types/struct_epoll_event.h | 6 +- libc/include/sys/epoll.h.def | 2 + libc/spec/posix.td | 5 + libc/src/sys/epoll/CMakeLists.txt | 21 ++++ libc/src/sys/epoll/epoll_create.h | 18 +++ libc/src/sys/epoll/epoll_create1.h | 18 +++ libc/src/sys/epoll/epoll_ctl.h | 21 ++++ libc/src/sys/epoll/epoll_pwait.h | 4 +- libc/src/sys/epoll/linux/CMakeLists.txt | 45 +++++++- libc/src/sys/epoll/linux/epoll_create.cpp | 38 +++++++ libc/src/sys/epoll/linux/epoll_create1.cpp | 31 ++++++ libc/src/sys/epoll/linux/epoll_ctl.cpp | 34 ++++++ libc/src/sys/epoll/linux/epoll_pwait.cpp | 5 +- libc/src/sys/epoll/linux/epoll_pwait2.cpp | 5 +- libc/src/sys/epoll/linux/epoll_wait.cpp | 5 +- libc/src/unistd/CMakeLists.txt | 7 ++ libc/src/unistd/linux/CMakeLists.txt | 13 +++ libc/src/unistd/linux/pipe.cpp | 33 ++++++ libc/src/unistd/pipe.h | 18 +++ libc/test/src/sys/epoll/linux/CMakeLists.txt | 68 +++++++++++- .../sys/epoll/linux/epoll_create1_test.cpp | 31 ++++++ .../src/sys/epoll/linux/epoll_create_test.cpp | 26 +++++ .../src/sys/epoll/linux/epoll_ctl_test.cpp | 47 ++++++++ .../src/sys/epoll/linux/epoll_pwait2_test.cpp | 47 +++++++- .../src/sys/epoll/linux/epoll_pwait_test.cpp | 42 ++++++- .../src/sys/epoll/linux/epoll_wait_test.cpp | 37 ++++++- libc/test/src/unistd/CMakeLists.txt | 15 +++ libc/test/src/unistd/pipe_test.cpp | 26 +++++ .../llvm-project-overlay/libc/BUILD.bazel | 103 ++++++++++++++++-- .../libc/test/src/sys/epoll/BUILD.bazel | 61 +++++++++++ 40 files changed, 933 insertions(+), 38 deletions(-) create mode 100644 libc/hdr/signal_macros.h create mode 100644 libc/hdr/sys_epoll_macros.h create mode 100644 libc/include/llvm-libc-macros/linux/sys-epoll-macros.h create mode 100644 libc/include/llvm-libc-macros/sys-epoll-macros.h create mode 100644 libc/src/sys/epoll/epoll_create.h create mode 100644 libc/src/sys/epoll/epoll_create1.h create mode 100644 libc/src/sys/epoll/epoll_ctl.h create mode 100644 libc/src/sys/epoll/linux/epoll_create.cpp create mode 100644 libc/src/sys/epoll/linux/epoll_create1.cpp create mode 100644 libc/src/sys/epoll/linux/epoll_ctl.cpp create mode 100644 libc/src/unistd/linux/pipe.cpp create mode 100644 libc/src/unistd/pipe.h create mode 100644 libc/test/src/sys/epoll/linux/epoll_create1_test.cpp create mode 100644 libc/test/src/sys/epoll/linux/epoll_create_test.cpp create mode 100644 libc/test/src/sys/epoll/linux/epoll_ctl_test.cpp create mode 100644 libc/test/src/unistd/pipe_test.cpp diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 6bb53cb76220..8fdd4575e27e 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -215,6 +215,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdio.fileno # sys/epoll.h entrypoints + libc.src.sys.epoll.epoll_create + libc.src.sys.epoll.epoll_create1 + libc.src.sys.epoll.epoll_ctl libc.src.sys.epoll.epoll_wait libc.src.sys.epoll.epoll_pwait # TODO: Need to check if pwait2 is available before providing. @@ -308,6 +311,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.unistd.link libc.src.unistd.linkat libc.src.unistd.lseek + libc.src.unistd.pipe libc.src.unistd.pread libc.src.unistd.pwrite libc.src.unistd.read diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt index 38ef56e3f04c..fb7c342f92b7 100644 --- a/libc/hdr/CMakeLists.txt +++ b/libc/hdr/CMakeLists.txt @@ -41,4 +41,22 @@ add_proxy_header_library( libc.include.fenv ) +add_proxy_header_library( + signal_macros + HDRS + signal_macros.h + FULL_BUILD_DEPENDS + libc.include.llvm-libc-macros.signal_macros + libc.include.signal +) + +add_proxy_header_library( + sys_epoll_macros + HDRS + sys_epoll_macros.h + FULL_BUILD_DEPENDS + libc.include.sys_epoll + libc.include.llvm-libc-macros.sys_epoll_macros +) + add_subdirectory(types) diff --git a/libc/hdr/signal_macros.h b/libc/hdr/signal_macros.h new file mode 100644 index 000000000000..867d17a4ca8c --- /dev/null +++ b/libc/hdr/signal_macros.h @@ -0,0 +1,22 @@ +//===-- Definition of macros from signal.h --------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_HDR_SIGNAL_MACROS_H +#define LLVM_LIBC_HDR_SIGNAL_MACROS_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-macros/signal-macros.h" + +#else // Overlay mode + +#include + +#endif // LLVM_LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_SIGNAL_MACROS_H diff --git a/libc/hdr/sys_epoll_macros.h b/libc/hdr/sys_epoll_macros.h new file mode 100644 index 000000000000..db047f161634 --- /dev/null +++ b/libc/hdr/sys_epoll_macros.h @@ -0,0 +1,22 @@ +//===-- Definition of macros from sys/epoll.h -----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_HDR_SYS_EPOLL_MACROS_H +#define LLVM_LIBC_HDR_SYS_EPOLL_MACROS_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-macros/sys-epoll-macros.h" + +#else // Overlay mode + +#include + +#endif // LLVM_LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_SYS/EPOLL_MACROS_H diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index 02c7dc8fbc0b..b85366c8deaf 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -379,6 +379,7 @@ add_gen_header( .llvm-libc-types.struct_epoll_event .llvm-libc-types.struct_epoll_data .llvm-libc-types.sigset_t + .llvm-libc-macros.sys_epoll_macros ) add_gen_header( diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt index 635ccadfb49e..382cb8ee417e 100644 --- a/libc/include/llvm-libc-macros/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/CMakeLists.txt @@ -143,6 +143,12 @@ add_macro_header( sys-auxv-macros.h ) +add_macro_header( + sys_epoll_macros + HDR + sys-epoll-macros.h +) + add_macro_header( sys_ioctl_macros HDR diff --git a/libc/include/llvm-libc-macros/linux/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/CMakeLists.txt index d934c3a0fca6..4ee429d1db16 100644 --- a/libc/include/llvm-libc-macros/linux/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/linux/CMakeLists.txt @@ -10,6 +10,12 @@ add_header( sched-macros.h ) +add_header( + sys_epoll_macros + HDR + sys-epoll-macros.h +) + add_header( sys_ioctl_macros HDR diff --git a/libc/include/llvm-libc-macros/linux/sys-epoll-macros.h b/libc/include/llvm-libc-macros/linux/sys-epoll-macros.h new file mode 100644 index 000000000000..f73d690908fd --- /dev/null +++ b/libc/include/llvm-libc-macros/linux/sys-epoll-macros.h @@ -0,0 +1,40 @@ +//===-- Macros defined in sys/epoll.h header file -------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_MACROS_LINUX_SYS_EPOLL_MACROS_H +#define LLVM_LIBC_MACROS_LINUX_SYS_EPOLL_MACROS_H + +#include "fcntl-macros.h" + +// These are also defined in but that also contains a +// different definition of the epoll_event struct that is different from the +// userspace version. + +#define EPOLL_CLOEXEC O_CLOEXEC + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_DEL 2 +#define EPOLL_CTL_MOD 3 + +#define EPOLLIN 0x1 +#define EPOLLPRI 0x2 +#define EPOLLOUT 0x4 +#define EPOLLERR 0x8 +#define EPOLLHUP 0x10 +#define EPOLLRDNORM 0x40 +#define EPOLLRDBAND 0x80 +#define EPOLLWRNORM 0x100 +#define EPOLLWRBAND 0x200 +#define EPOLLMSG 0x400 +#define EPOLLRDHUP 0x2000 +#define EPOLLEXCLUSIVE 0x10000000 +#define EPOLLWAKEUP 0x20000000 +#define EPOLLONESHOT 0x40000000 +#define EPOLLET 0x80000000 + +#endif // LLVM_LIBC_MACROS_LINUX_SYS_EPOLL_MACROS_H diff --git a/libc/include/llvm-libc-macros/sys-epoll-macros.h b/libc/include/llvm-libc-macros/sys-epoll-macros.h new file mode 100644 index 000000000000..8212df252b8e --- /dev/null +++ b/libc/include/llvm-libc-macros/sys-epoll-macros.h @@ -0,0 +1,16 @@ +//===-- Macros defined in sys/epoll.h header file -------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_MACROS_SYS_EPOLL_MACROS_H +#define LLVM_LIBC_MACROS_SYS_EPOLL_MACROS_H + +#ifdef __linux__ +#include "linux/sys-epoll-macros.h" +#endif + +#endif // LLVM_LIBC_MACROS_SYS_EPOLL_MACROS_H diff --git a/libc/include/llvm-libc-types/sigset_t.h b/libc/include/llvm-libc-types/sigset_t.h index 311a92b823ff..5c3e4e6f0431 100644 --- a/libc/include/llvm-libc-types/sigset_t.h +++ b/libc/include/llvm-libc-types/sigset_t.h @@ -13,8 +13,8 @@ // This definition can be adjusted/specialized for different targets and // platforms as necessary. This definition works for Linux on most targets. -typedef struct { +struct sigset_t { unsigned long __signals[__NSIGSET_WORDS]; -} sigset_t; +}; #endif // LLVM_LIBC_TYPES_SIGSET_T_H diff --git a/libc/include/llvm-libc-types/struct_epoll_event.h b/libc/include/llvm-libc-types/struct_epoll_event.h index 66cf86c1e2a0..b7685df20bd7 100644 --- a/libc/include/llvm-libc-types/struct_epoll_event.h +++ b/libc/include/llvm-libc-types/struct_epoll_event.h @@ -11,7 +11,11 @@ #include "llvm-libc-types/struct_epoll_data.h" -typedef struct epoll_event { +typedef struct +#ifdef __x86_64__ + [[gnu::packed]] // Necessary for compatibility. +#endif + epoll_event { __UINT32_TYPE__ events; epoll_data_t data; } epoll_event; diff --git a/libc/include/sys/epoll.h.def b/libc/include/sys/epoll.h.def index 85f7d9ad6091..98d96bf42925 100644 --- a/libc/include/sys/epoll.h.def +++ b/libc/include/sys/epoll.h.def @@ -11,6 +11,8 @@ #include "__llvm-libc-common.h" +#include "llvm-libc-macros/sys-epoll-macros.h" + %%public_api() #endif // LLVM_LIBC_SYS_EPOLL_H diff --git a/libc/spec/posix.td b/libc/spec/posix.td index 45f7ecfe84e9..7095a3964ee3 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -572,6 +572,11 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec, ArgSpec, ArgSpec] >, + FunctionSpec< + "pipe", + RetValSpec, + [ArgSpec] //TODO: make this int[2] + >, FunctionSpec< "pread", RetValSpec, diff --git a/libc/src/sys/epoll/CMakeLists.txt b/libc/src/sys/epoll/CMakeLists.txt index d4991a238e2a..e785f535bf0c 100644 --- a/libc/src/sys/epoll/CMakeLists.txt +++ b/libc/src/sys/epoll/CMakeLists.txt @@ -2,6 +2,27 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) endif() +add_entrypoint_object( + epoll_create + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.epoll_create +) + +add_entrypoint_object( + epoll_create1 + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.epoll_create1 +) + +add_entrypoint_object( + epoll_ctl + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.epoll_ctl +) + add_entrypoint_object( epoll_wait ALIAS diff --git a/libc/src/sys/epoll/epoll_create.h b/libc/src/sys/epoll/epoll_create.h new file mode 100644 index 000000000000..a1eeabd567e4 --- /dev/null +++ b/libc/src/sys/epoll/epoll_create.h @@ -0,0 +1,18 @@ +//===-- Implementation header for epoll_create function ---------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SYS_EPOLL_EPOLL_CREATE_H +#define LLVM_LIBC_SRC_SYS_EPOLL_EPOLL_CREATE_H + +namespace LIBC_NAMESPACE { + +int epoll_create(int size); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_EPOLL_EPOLL_CREATE_H diff --git a/libc/src/sys/epoll/epoll_create1.h b/libc/src/sys/epoll/epoll_create1.h new file mode 100644 index 000000000000..70f446b59266 --- /dev/null +++ b/libc/src/sys/epoll/epoll_create1.h @@ -0,0 +1,18 @@ +//===-- Implementation header for epoll_create1 function --------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SYS_EPOLL_EPOLL_CREATE1_H +#define LLVM_LIBC_SRC_SYS_EPOLL_EPOLL_CREATE1_H + +namespace LIBC_NAMESPACE { + +int epoll_create1(int flags); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_EPOLL_EPOLL_CREATE1_H diff --git a/libc/src/sys/epoll/epoll_ctl.h b/libc/src/sys/epoll/epoll_ctl.h new file mode 100644 index 000000000000..42402949d06b --- /dev/null +++ b/libc/src/sys/epoll/epoll_ctl.h @@ -0,0 +1,21 @@ +//===-- Implementation header for epoll_ctl function ------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SYS_EPOLL_EPOLL_CTL_H +#define LLVM_LIBC_SRC_SYS_EPOLL_EPOLL_CTL_H + +#include "hdr/types/struct_epoll_event.h" + +namespace LIBC_NAMESPACE { + +// TODO: event should be nullable +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_EPOLL_EPOLL_CTL_H diff --git a/libc/src/sys/epoll/epoll_pwait.h b/libc/src/sys/epoll/epoll_pwait.h index 801aa9761000..bcae72b3e2c2 100644 --- a/libc/src/sys/epoll/epoll_pwait.h +++ b/libc/src/sys/epoll/epoll_pwait.h @@ -15,8 +15,8 @@ namespace LIBC_NAMESPACE { // TODO: sigmask should be nullable -int epoll_pwait(int epfd, epoll_event *events, int maxevents, int timeout, - const sigset_t *sigmask); +int epoll_pwait(int epfd, struct epoll_event *events, int maxevents, + int timeout, const sigset_t *sigmask); } // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/epoll/linux/CMakeLists.txt b/libc/src/sys/epoll/linux/CMakeLists.txt index 586aac7055dc..4e661b262b85 100644 --- a/libc/src/sys/epoll/linux/CMakeLists.txt +++ b/libc/src/sys/epoll/linux/CMakeLists.txt @@ -1,3 +1,41 @@ +add_entrypoint_object( + epoll_create + SRCS + epoll_create.cpp + HDRS + ../epoll_create.h + DEPENDS + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + +add_entrypoint_object( + epoll_create1 + SRCS + epoll_create1.cpp + HDRS + ../epoll_create1.h + DEPENDS + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + +add_entrypoint_object( + epoll_ctl + SRCS + epoll_ctl.cpp + HDRS + ../epoll_ctl.h + DEPENDS + libc.hdr.types.struct_epoll_event + libc.hdr.sys_epoll_macros + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + add_entrypoint_object( epoll_wait SRCS @@ -23,7 +61,8 @@ add_entrypoint_object( libc.hdr.types.sigset_t libc.hdr.types.struct_epoll_event libc.hdr.types.struct_timespec - libc.include.signal + libc.hdr.sys_epoll_macros + libc.hdr.signal_macros libc.include.sys_syscall libc.src.__support.OSUtil.osutil libc.src.errno.errno @@ -39,9 +78,9 @@ add_entrypoint_object( libc.hdr.types.sigset_t libc.hdr.types.struct_epoll_event libc.hdr.types.struct_timespec - libc.include.signal + libc.hdr.sys_epoll_macros + libc.hdr.signal_macros libc.include.sys_syscall - libc.include.time libc.src.__support.OSUtil.osutil libc.src.errno.errno ) diff --git a/libc/src/sys/epoll/linux/epoll_create.cpp b/libc/src/sys/epoll/linux/epoll_create.cpp new file mode 100644 index 000000000000..d4995c476074 --- /dev/null +++ b/libc/src/sys/epoll/linux/epoll_create.cpp @@ -0,0 +1,38 @@ +//===---------- Linux implementation of the epoll_create function ---------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/sys/epoll/epoll_create.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, epoll_create, ([[maybe_unused]] int size)) { +#ifdef SYS_epoll_create + int ret = LIBC_NAMESPACE::syscall_impl(SYS_epoll_create, size); +#elif defined(SYS_epoll_create1) + int ret = LIBC_NAMESPACE::syscall_impl(SYS_epoll_create1, 0); +#else +#error \ + "epoll_create and epoll_create1 are unavailable. Unable to build epoll_create." +#endif + + // A negative return value indicates an error with the magnitude of the + // value being the error code. + if (ret < 0) { + libc_errno = -ret; + return -1; + } + + return ret; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/epoll/linux/epoll_create1.cpp b/libc/src/sys/epoll/linux/epoll_create1.cpp new file mode 100644 index 000000000000..30f1a9910274 --- /dev/null +++ b/libc/src/sys/epoll/linux/epoll_create1.cpp @@ -0,0 +1,31 @@ +//===---------- Linux implementation of the epoll_create1 function --------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/sys/epoll/epoll_create1.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, epoll_create1, (int flags)) { + int ret = LIBC_NAMESPACE::syscall_impl(SYS_epoll_create1, flags); + + // A negative return value indicates an error with the magnitude of the + // value being the error code. + if (ret < 0) { + libc_errno = -ret; + return -1; + } + + return ret; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/epoll/linux/epoll_ctl.cpp b/libc/src/sys/epoll/linux/epoll_ctl.cpp new file mode 100644 index 000000000000..c111c5e4e0ee --- /dev/null +++ b/libc/src/sys/epoll/linux/epoll_ctl.cpp @@ -0,0 +1,34 @@ +//===---------- Linux implementation of the epoll_ctl function ----------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/sys/epoll/epoll_ctl.h" + +#include "hdr/types/struct_epoll_event.h" +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, epoll_ctl, + (int epfd, int op, int fd, epoll_event *event)) { + int ret = LIBC_NAMESPACE::syscall_impl(SYS_epoll_ctl, epfd, op, fd, + reinterpret_cast(event)); + + // A negative return value indicates an error with the magnitude of the + // value being the error code. + if (ret < 0) { + libc_errno = -ret; + return -1; + } + + return ret; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/epoll/linux/epoll_pwait.cpp b/libc/src/sys/epoll/linux/epoll_pwait.cpp index ac012944a957..8f498d18d547 100644 --- a/libc/src/sys/epoll/linux/epoll_pwait.cpp +++ b/libc/src/sys/epoll/linux/epoll_pwait.cpp @@ -8,6 +8,7 @@ #include "src/sys/epoll/epoll_pwait.h" +#include "hdr/signal_macros.h" // for NSIG #include "hdr/types/sigset_t.h" #include "hdr/types/struct_epoll_event.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. @@ -23,7 +24,7 @@ LLVM_LIBC_FUNCTION(int, epoll_pwait, int timeout, const sigset_t *sigmask)) { int ret = LIBC_NAMESPACE::syscall_impl( SYS_epoll_pwait, epfd, reinterpret_cast(events), maxevents, timeout, - reinterpret_cast(sigmask), sizeof(sigset_t)); + reinterpret_cast(sigmask), NSIG / 8); // A negative return value indicates an error with the magnitude of the // value being the error code. @@ -32,7 +33,7 @@ LLVM_LIBC_FUNCTION(int, epoll_pwait, return -1; } - return 0; + return ret; } } // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/epoll/linux/epoll_pwait2.cpp b/libc/src/sys/epoll/linux/epoll_pwait2.cpp index 3c42e38deb22..bd33cb6325ce 100644 --- a/libc/src/sys/epoll/linux/epoll_pwait2.cpp +++ b/libc/src/sys/epoll/linux/epoll_pwait2.cpp @@ -8,6 +8,7 @@ #include "src/sys/epoll/epoll_pwait2.h" +#include "hdr/signal_macros.h" // for NSIG #include "hdr/types/sigset_t.h" #include "hdr/types/struct_epoll_event.h" #include "hdr/types/struct_timespec.h" @@ -25,7 +26,7 @@ LLVM_LIBC_FUNCTION(int, epoll_pwait2, int ret = LIBC_NAMESPACE::syscall_impl( SYS_epoll_pwait2, epfd, reinterpret_cast(events), maxevents, reinterpret_cast(timeout), reinterpret_cast(sigmask), - sizeof(sigset_t)); + NSIG / 8); // A negative return value indicates an error with the magnitude of the // value being the error code. @@ -34,7 +35,7 @@ LLVM_LIBC_FUNCTION(int, epoll_pwait2, return -1; } - return 0; + return ret; } } // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/epoll/linux/epoll_wait.cpp b/libc/src/sys/epoll/linux/epoll_wait.cpp index 18dd6e2b8354..95238d872d52 100644 --- a/libc/src/sys/epoll/linux/epoll_wait.cpp +++ b/libc/src/sys/epoll/linux/epoll_wait.cpp @@ -8,6 +8,7 @@ #include "src/sys/epoll/epoll_wait.h" +#include "hdr/signal_macros.h" // for NSIG #include "hdr/types/sigset_t.h" #include "hdr/types/struct_epoll_event.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. @@ -27,7 +28,7 @@ LLVM_LIBC_FUNCTION(int, epoll_wait, #elif defined(SYS_epoll_pwait) int ret = LIBC_NAMESPACE::syscall_impl( SYS_epoll_pwait, epfd, reinterpret_cast(events), maxevents, timeout, - reinterpret_cast(nullptr), sizeof(sigset_t)); + reinterpret_cast(nullptr), NSIG / 8); #else #error "epoll_wait and epoll_pwait are unavailable. Unable to build epoll_wait." #endif @@ -38,7 +39,7 @@ LLVM_LIBC_FUNCTION(int, epoll_wait, return -1; } - return 0; + return ret; } } // namespace LIBC_NAMESPACE diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt index 58b44f5307ca..77db76518350 100644 --- a/libc/src/unistd/CMakeLists.txt +++ b/libc/src/unistd/CMakeLists.txt @@ -160,6 +160,13 @@ add_entrypoint_object( .${LIBC_TARGET_OS}.lseek ) +add_entrypoint_object( + pipe + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.pipe +) + add_entrypoint_object( pread ALIAS diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt index df85d44e9e9e..7d831f9c29c7 100644 --- a/libc/src/unistd/linux/CMakeLists.txt +++ b/libc/src/unistd/linux/CMakeLists.txt @@ -273,6 +273,19 @@ add_entrypoint_object( libc.src.errno.errno ) +add_entrypoint_object( + pipe + SRCS + pipe.cpp + HDRS + ../pipe.h + DEPENDS + libc.include.unistd + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + add_entrypoint_object( pread SRCS diff --git a/libc/src/unistd/linux/pipe.cpp b/libc/src/unistd/linux/pipe.cpp new file mode 100644 index 000000000000..b4e8b9b7d9c8 --- /dev/null +++ b/libc/src/unistd/linux/pipe.cpp @@ -0,0 +1,33 @@ +//===-- Linux implementation of pipe --------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/unistd/pipe.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pipe, (int pipefd[2])) { +#ifdef SYS_pipe + int ret = LIBC_NAMESPACE::syscall_impl(SYS_pipe, + reinterpret_cast(pipefd)); +#elif defined(SYS_pipe2) + int ret = LIBC_NAMESPACE::syscall_impl( + SYS_pipe2, reinterpret_cast(pipefd), 0); +#endif + if (ret < 0) { + libc_errno = -ret; + return -1; + } + return ret; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/unistd/pipe.h b/libc/src/unistd/pipe.h new file mode 100644 index 000000000000..0e20bb49c058 --- /dev/null +++ b/libc/src/unistd/pipe.h @@ -0,0 +1,18 @@ +//===-- Implementation header for pipe --------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_UNISTD_PIPE_H +#define LLVM_LIBC_SRC_UNISTD_PIPE_H + +namespace LIBC_NAMESPACE { + +int pipe(int pipefd[2]); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_UNISTD_PIPE_H diff --git a/libc/test/src/sys/epoll/linux/CMakeLists.txt b/libc/test/src/sys/epoll/linux/CMakeLists.txt index e346af2328db..8f4b698ef141 100644 --- a/libc/test/src/sys/epoll/linux/CMakeLists.txt +++ b/libc/test/src/sys/epoll/linux/CMakeLists.txt @@ -1,4 +1,50 @@ add_custom_target(libc_sys_epoll_unittests) + +add_libc_unittest( + epoll_create_test + SUITE + libc_sys_epoll_unittests + SRCS + epoll_create_test.cpp + DEPENDS + libc.include.sys_epoll + libc.src.errno.errno + libc.src.sys.epoll.epoll_create + libc.src.unistd.close + libc.test.UnitTest.ErrnoSetterMatcher +) + +add_libc_unittest( + epoll_create1_test + SUITE + libc_sys_epoll_unittests + SRCS + epoll_create1_test.cpp + DEPENDS + libc.hdr.sys_epoll_macros + libc.src.errno.errno + libc.src.sys.epoll.epoll_create1 + libc.src.unistd.close + libc.test.UnitTest.ErrnoSetterMatcher +) + +add_libc_unittest( + epoll_ctl_test + SUITE + libc_sys_epoll_unittests + SRCS + epoll_ctl_test.cpp + DEPENDS + libc.hdr.sys_epoll_macros + libc.hdr.types.struct_epoll_event + libc.src.errno.errno + libc.src.sys.epoll.epoll_create1 + libc.src.sys.epoll.epoll_ctl + libc.src.unistd.pipe + libc.src.unistd.close + libc.test.UnitTest.ErrnoSetterMatcher +) + add_libc_unittest( epoll_wait_test SUITE @@ -6,9 +52,14 @@ add_libc_unittest( SRCS epoll_wait_test.cpp DEPENDS - libc.include.sys_epoll + libc.hdr.sys_epoll_macros + libc.hdr.types.struct_epoll_event libc.src.errno.errno + libc.src.sys.epoll.epoll_create1 + libc.src.sys.epoll.epoll_ctl libc.src.sys.epoll.epoll_wait + libc.src.unistd.pipe + libc.src.unistd.close libc.test.UnitTest.ErrnoSetterMatcher ) @@ -19,9 +70,14 @@ add_libc_unittest( SRCS epoll_pwait_test.cpp DEPENDS - libc.include.sys_epoll + libc.hdr.sys_epoll_macros + libc.hdr.types.struct_epoll_event libc.src.errno.errno + libc.src.sys.epoll.epoll_create1 + libc.src.sys.epoll.epoll_ctl libc.src.sys.epoll.epoll_pwait + libc.src.unistd.pipe + libc.src.unistd.close libc.test.UnitTest.ErrnoSetterMatcher ) @@ -32,8 +88,14 @@ add_libc_unittest( SRCS epoll_pwait2_test.cpp DEPENDS - libc.include.sys_epoll + libc.hdr.sys_epoll_macros + libc.hdr.types.struct_epoll_event + libc.hdr.types.struct_timespec libc.src.errno.errno + libc.src.sys.epoll.epoll_create1 + libc.src.sys.epoll.epoll_ctl libc.src.sys.epoll.epoll_pwait2 + libc.src.unistd.pipe + libc.src.unistd.close libc.test.UnitTest.ErrnoSetterMatcher ) diff --git a/libc/test/src/sys/epoll/linux/epoll_create1_test.cpp b/libc/test/src/sys/epoll/linux/epoll_create1_test.cpp new file mode 100644 index 000000000000..4059afe16b80 --- /dev/null +++ b/libc/test/src/sys/epoll/linux/epoll_create1_test.cpp @@ -0,0 +1,31 @@ +//===-- Unittests for epoll_create1 ---------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#include "hdr/sys_epoll_macros.h" +#include "src/errno/libc_errno.h" +#include "src/sys/epoll/epoll_create1.h" +#include "src/unistd/close.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; + +TEST(LlvmLibcEpollCreate1Test, Basic) { + int fd = LIBC_NAMESPACE::epoll_create1(0); + ASSERT_GT(fd, 0); + ASSERT_ERRNO_SUCCESS(); + + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds()); +} + +TEST(LlvmLibcEpollCreate1Test, CloseOnExecute) { + int fd = LIBC_NAMESPACE::epoll_create1(EPOLL_CLOEXEC); + ASSERT_GT(fd, 0); + ASSERT_ERRNO_SUCCESS(); + + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds()); +} diff --git a/libc/test/src/sys/epoll/linux/epoll_create_test.cpp b/libc/test/src/sys/epoll/linux/epoll_create_test.cpp new file mode 100644 index 000000000000..fdcdcf8eb427 --- /dev/null +++ b/libc/test/src/sys/epoll/linux/epoll_create_test.cpp @@ -0,0 +1,26 @@ +//===-- Unittests for epoll_create ----------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#include "src/errno/libc_errno.h" +#include "src/sys/epoll/epoll_create.h" +#include "src/unistd/close.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; + +TEST(LlvmLibcEpollCreateTest, Basic) { + int fd = LIBC_NAMESPACE::epoll_create(1); + ASSERT_GT(fd, 0); + ASSERT_ERRNO_SUCCESS(); + + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds()); +} + +TEST(LlvmLibcEpollCreateTest, Fails) { + ASSERT_THAT(LIBC_NAMESPACE::epoll_create(0), Fails(EINVAL)); +} diff --git a/libc/test/src/sys/epoll/linux/epoll_ctl_test.cpp b/libc/test/src/sys/epoll/linux/epoll_ctl_test.cpp new file mode 100644 index 000000000000..fa2d358c5796 --- /dev/null +++ b/libc/test/src/sys/epoll/linux/epoll_ctl_test.cpp @@ -0,0 +1,47 @@ +//===-- Unittests for epoll_ctl -------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "hdr/sys_epoll_macros.h" +#include "hdr/types/struct_epoll_event.h" +#include "src/errno/libc_errno.h" +#include "src/sys/epoll/epoll_create1.h" +#include "src/sys/epoll/epoll_ctl.h" +#include "src/unistd/close.h" +#include "src/unistd/pipe.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; + +TEST(LlvmLibcEpollCtlTest, Basic) { + int epfd = LIBC_NAMESPACE::epoll_create1(0); + ASSERT_GT(epfd, 0); + ASSERT_ERRNO_SUCCESS(); + + int pipefd[2]; + + ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds()); + + epoll_event event; + event.events = EPOLLOUT; + event.data.fd = pipefd[0]; + + ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event), + Succeeds()); + + // adding the same file fail. + ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event), + Fails(EEXIST)); + + ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_DEL, pipefd[0], &event), + Succeeds()); + + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::close(epfd), Succeeds()); +} diff --git a/libc/test/src/sys/epoll/linux/epoll_pwait2_test.cpp b/libc/test/src/sys/epoll/linux/epoll_pwait2_test.cpp index 83fe12bb8eb6..2f4c9854be1a 100644 --- a/libc/test/src/sys/epoll/linux/epoll_pwait2_test.cpp +++ b/libc/test/src/sys/epoll/linux/epoll_pwait2_test.cpp @@ -5,16 +5,53 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +#include "hdr/sys_epoll_macros.h" +#include "hdr/types/struct_epoll_event.h" +#include "hdr/types/struct_timespec.h" #include "src/errno/libc_errno.h" +#include "src/sys/epoll/epoll_create1.h" +#include "src/sys/epoll/epoll_ctl.h" #include "src/sys/epoll/epoll_pwait2.h" +#include "src/unistd/close.h" +#include "src/unistd/pipe.h" #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/Test.h" using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; -TEST(LlvmLibcEpollWaitTest, Basic) { - EXPECT_THAT(LIBC_NAMESPACE::epoll_pwait2(-1, nullptr, 0, nullptr, nullptr), - returns(EQ(-1ul)).with_errno(EQ(EINVAL))); -} +TEST(LlvmLibcEpollPwaitTest, Basic) { + int epfd = LIBC_NAMESPACE::epoll_create1(0); + ASSERT_GT(epfd, 0); + ASSERT_ERRNO_SUCCESS(); + + int pipefd[2]; + + ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds()); + + epoll_event event; + event.events = EPOLLOUT; + event.data.fd = pipefd[0]; + + timespec time_spec; + time_spec.tv_sec = 0; + time_spec.tv_nsec = 0; -// TODO: Complete these tests when epoll_create is implemented. + ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event), + Succeeds()); + + // Timeout of 0 causes immediate return. We just need to check that the + // interface works, we're not testing the kernel behavior here. + ASSERT_THAT( + LIBC_NAMESPACE::epoll_pwait2(epfd, &event, 1, &time_spec, nullptr), + Succeeds()); + + ASSERT_THAT(LIBC_NAMESPACE::epoll_pwait2(-1, &event, 1, &time_spec, nullptr), + Fails(EBADF)); + + ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_DEL, pipefd[0], &event), + Succeeds()); + + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::close(epfd), Succeeds()); +} diff --git a/libc/test/src/sys/epoll/linux/epoll_pwait_test.cpp b/libc/test/src/sys/epoll/linux/epoll_pwait_test.cpp index 217facbfcebb..8e14aea8b9d5 100644 --- a/libc/test/src/sys/epoll/linux/epoll_pwait_test.cpp +++ b/libc/test/src/sys/epoll/linux/epoll_pwait_test.cpp @@ -5,16 +5,48 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +#include "hdr/sys_epoll_macros.h" +#include "hdr/types/struct_epoll_event.h" #include "src/errno/libc_errno.h" +#include "src/sys/epoll/epoll_create1.h" +#include "src/sys/epoll/epoll_ctl.h" #include "src/sys/epoll/epoll_pwait.h" +#include "src/unistd/close.h" +#include "src/unistd/pipe.h" + #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/Test.h" using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; -TEST(LlvmLibcEpollWaitTest, Basic) { - EXPECT_THAT(LIBC_NAMESPACE::epoll_pwait(-1, nullptr, 0, 0, nullptr), - returns(EQ(-1ul)).with_errno(EQ(EINVAL))); -} +TEST(LlvmLibcEpollPwaitTest, Basic) { + int epfd = LIBC_NAMESPACE::epoll_create1(0); + ASSERT_GT(epfd, 0); + ASSERT_ERRNO_SUCCESS(); + + int pipefd[2]; + + ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds()); + + epoll_event event; + event.events = EPOLLOUT; + event.data.fd = pipefd[0]; -// TODO: Complete these tests when epoll_create is implemented. + ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event), + Succeeds()); + + // Timeout of 0 causes immediate return. We just need to check that the + // interface works, we're not testing the kernel behavior here. + ASSERT_THAT(LIBC_NAMESPACE::epoll_pwait(epfd, &event, 1, 0, nullptr), + Succeeds()); + + ASSERT_THAT(LIBC_NAMESPACE::epoll_pwait(-1, &event, 1, 0, nullptr), + Fails(EBADF)); + + ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_DEL, pipefd[0], &event), + Succeeds()); + + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::close(epfd), Succeeds()); +} diff --git a/libc/test/src/sys/epoll/linux/epoll_wait_test.cpp b/libc/test/src/sys/epoll/linux/epoll_wait_test.cpp index 57fef3f690b6..f9e855a891b0 100644 --- a/libc/test/src/sys/epoll/linux/epoll_wait_test.cpp +++ b/libc/test/src/sys/epoll/linux/epoll_wait_test.cpp @@ -5,16 +5,45 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +#include "hdr/sys_epoll_macros.h" +#include "hdr/types/struct_epoll_event.h" #include "src/errno/libc_errno.h" +#include "src/sys/epoll/epoll_create1.h" +#include "src/sys/epoll/epoll_ctl.h" #include "src/sys/epoll/epoll_wait.h" +#include "src/unistd/close.h" +#include "src/unistd/pipe.h" #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/Test.h" using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; TEST(LlvmLibcEpollWaitTest, Basic) { - EXPECT_THAT(LIBC_NAMESPACE::epoll_wait(-1, nullptr, 0, 0), - returns(EQ(-1ul)).with_errno(EQ(EINVAL))); -} + int epfd = LIBC_NAMESPACE::epoll_create1(0); + ASSERT_GT(epfd, 0); + ASSERT_ERRNO_SUCCESS(); + + int pipefd[2]; + + ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds()); + + epoll_event event; + event.events = EPOLLOUT; + event.data.fd = pipefd[0]; + + ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event), + Succeeds()); -// TODO: Complete these tests when epoll_create is implemented. + // Timeout of 0 causes immediate return. We just need to check that the + // interface works, we're not testing the kernel behavior here. + ASSERT_THAT(LIBC_NAMESPACE::epoll_wait(epfd, &event, 1, 0), Succeeds()); + + ASSERT_THAT(LIBC_NAMESPACE::epoll_wait(-1, &event, 1, 0), Fails(EBADF)); + + ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_DEL, pipefd[0], &event), + Succeeds()); + + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::close(epfd), Succeeds()); +} diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt index 9de5081f0094..de3e8d9ccbb6 100644 --- a/libc/test/src/unistd/CMakeLists.txt +++ b/libc/test/src/unistd/CMakeLists.txt @@ -212,6 +212,21 @@ add_libc_unittest( libc.test.UnitTest.ErrnoSetterMatcher ) +add_libc_unittest( + pipe_test + SUITE + libc_unistd_unittests + SRCS + pipe_test.cpp + DEPENDS + libc.include.errno + libc.include.unistd + libc.src.errno.errno + libc.src.unistd.close + libc.src.unistd.pipe + libc.test.UnitTest.ErrnoSetterMatcher +) + add_libc_unittest( rmdir_test SUITE diff --git a/libc/test/src/unistd/pipe_test.cpp b/libc/test/src/unistd/pipe_test.cpp new file mode 100644 index 000000000000..9c633dea1dba --- /dev/null +++ b/libc/test/src/unistd/pipe_test.cpp @@ -0,0 +1,26 @@ +//===-- Unittests for pipe ------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#include "src/unistd/close.h" +#include "src/unistd/pipe.h" + +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; + +TEST(LlvmLibcPipeTest, SmokeTest) { + + int pipefd[2]; + + ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds()); + + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds()); +} + +// TODO: Functionality tests diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index c61904a96711..9270a9d75b01 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -106,7 +106,7 @@ libc_support_library( hdrs = ["include/llvm-libc-macros/linux/fcntl-macros.h"], ) -############################ Proxy Header Files ################################ +########################### Macro Proxy Header Files ########################### libc_support_library( name = "hdr_math_macros", @@ -118,6 +118,33 @@ libc_support_library( hdrs = ["hdr/fenv_macros.h"], ) +libc_support_library( + name = "hdr_signal_macros", + hdrs = ["hdr/signal_macros.h"], +) + +libc_support_library( + name = "hdr_sys_epoll_macros", + hdrs = ["hdr/sys_epoll_macros.h"], +) + +############################ Type Proxy Header Files ########################### + +libc_support_library( + name = "types_sigset_t", + hdrs = ["hdr/types/sigset_t.h"], +) + +libc_support_library( + name = "types_struct_epoll_event", + hdrs = ["hdr/types/struct_epoll_event.h"], +) + +libc_support_library( + name = "types_struct_timespec", + hdrs = ["hdr/types/struct_timespec.h"], +) + ############################### Support libraries ############################## libc_support_library( @@ -2941,6 +2968,17 @@ libc_function( ], ) +libc_function( + name = "pipe", + srcs = ["src/unistd/linux/pipe.cpp"], + hdrs = ["src/unistd/pipe.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ], +) + libc_function( name = "lseek", srcs = ["src/unistd/linux/lseek.cpp"], @@ -3417,13 +3455,51 @@ libc_function( ############################## sys/epoll targets ############################### -libc_support_library( - name = "types_sigset_t", - hdrs = ["hdr/types/sigset_t.h"], +libc_function( + name = "epoll_create", + srcs = ["src/sys/epoll/linux/epoll_create.cpp"], + hdrs = ["src/sys/epoll/epoll_create.h"], + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + weak = True, + deps = [ + ":__support_osutil_syscall", + ":errno", + ], ) -libc_support_library( - name = "types_struct_epoll_event", - hdrs = ["hdr/types/struct_epoll_event.h"], + +libc_function( + name = "epoll_create1", + srcs = ["src/sys/epoll/linux/epoll_create1.cpp"], + hdrs = ["src/sys/epoll/epoll_create1.h"], + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + weak = True, + deps = [ + ":__support_osutil_syscall", + ":errno", + ], +) + +libc_function( + name = "epoll_ctl", + srcs = ["src/sys/epoll/linux/epoll_ctl.cpp"], + hdrs = ["src/sys/epoll/epoll_ctl.h"], + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + weak = True, + deps = [ + ":__support_osutil_syscall", + ":errno", + ":hdr_sys_epoll_macros", + ":types_struct_epoll_event", + ], ) libc_function( @@ -3438,6 +3514,8 @@ libc_function( deps = [ ":__support_osutil_syscall", ":errno", + ":hdr_signal_macros", + ":hdr_sys_epoll_macros", ":types_sigset_t", ":types_struct_epoll_event", ], @@ -3455,6 +3533,8 @@ libc_function( deps = [ ":__support_osutil_syscall", ":errno", + ":hdr_signal_macros", + ":hdr_sys_epoll_macros", ":types_sigset_t", ":types_struct_epoll_event", ], @@ -3466,9 +3546,18 @@ libc_function( # name = "epoll_pwait2", # srcs = ["src/sys/epoll/linux/epoll_pwait2.cpp"], # hdrs = ["src/sys/epoll/epoll_pwait2.h"], +# target_compatible_with = select({ +# "@platforms//os:linux": [], +# "//conditions:default": ["@platforms//:incompatible"], +# }), # weak = True, # deps = [ # ":__support_osutil_syscall", # ":errno", +# ":hdr_signal_macros", +# ":hdr_sys_epoll_macros", +# ":types_sigset_t", +# ":types_struct_epoll_event", +# ":types_struct_timespec", # ], # ) diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/sys/epoll/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/sys/epoll/BUILD.bazel index e6b63235757e..b090bde35b88 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/sys/epoll/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/sys/epoll/BUILD.bazel @@ -10,11 +10,55 @@ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) +libc_test( + name = "epoll_create_test", + srcs = ["linux/epoll_create_test.cpp"], + libc_function_deps = [ + "//libc:epoll_create", + "//libc:close", + ], +) + +libc_test( + name = "epoll_create1_test", + srcs = ["linux/epoll_create1_test.cpp"], + libc_function_deps = [ + "//libc:epoll_create1", + "//libc:close", + ], + deps = [ + "//libc:hdr_sys_epoll_macros", + ], +) + +libc_test( + name = "epoll_ctl_test", + srcs = ["linux/epoll_ctl_test.cpp"], + libc_function_deps = [ + "//libc:epoll_create1", + "//libc:epoll_ctl", + "//libc:pipe", + "//libc:close", + ], + deps = [ + "//libc:hdr_sys_epoll_macros", + "//libc:types_struct_epoll_event", + ], +) + libc_test( name = "epoll_wait_test", srcs = ["linux/epoll_wait_test.cpp"], libc_function_deps = [ "//libc:epoll_wait", + "//libc:epoll_create1", + "//libc:epoll_ctl", + "//libc:pipe", + "//libc:close", + ], + deps = [ + "//libc:hdr_sys_epoll_macros", + "//libc:types_struct_epoll_event", ], ) @@ -23,6 +67,14 @@ libc_test( srcs = ["linux/epoll_pwait_test.cpp"], libc_function_deps = [ "//libc:epoll_pwait", + "//libc:epoll_create1", + "//libc:epoll_ctl", + "//libc:pipe", + "//libc:close", + ], + deps = [ + "//libc:hdr_sys_epoll_macros", + "//libc:types_struct_epoll_event", ], ) @@ -33,5 +85,14 @@ libc_test( # srcs = ["linux/epoll_pwait2_test.cpp"], # libc_function_deps = [ # "//libc:epoll_pwait2", +# "//libc:epoll_create1", +# "//libc:epoll_ctl", +# "//libc:pipe", +# "//libc:close", +# ], +# deps = [ +# "//libc:hdr_sys_epoll_macros", +# "//libc:types_struct_epoll_event", +# "//libc:types_struct_timespec", # ], # ) -- GitLab From 7aa371687ace40b85f04e21956e03f1e93052b56 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Thu, 11 Apr 2024 19:34:53 -0400 Subject: [PATCH 016/464] [clangd] Avoid using CompletionItemKind.Text for macro completions from the index (#88236) This was fixed in https://github.com/clangd/clangd/issues/1484 for Sema completions but the fix did not apply to index completions. Fixes https://github.com/clangd/clangd/issues/2002 --- clang-tools-extra/clangd/CodeComplete.cpp | 16 +++++++++++++--- .../clangd/unittests/CodeCompleteTests.cpp | 7 +++++-- clang-tools-extra/clangd/unittests/TestIndex.cpp | 7 ++++++- clang-tools-extra/clangd/unittests/TestIndex.h | 4 +++- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 9e321dce4c50..89eee392837a 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -89,7 +89,11 @@ const CodeCompleteOptions::CodeCompletionRankingModel namespace { -CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) { +// Note: changes to this function should also be reflected in the +// CodeCompletionResult overload where appropriate. +CompletionItemKind +toCompletionItemKind(index::SymbolKind Kind, + const llvm::StringRef *Signature = nullptr) { using SK = index::SymbolKind; switch (Kind) { case SK::Unknown: @@ -99,7 +103,10 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) { case SK::NamespaceAlias: return CompletionItemKind::Module; case SK::Macro: - return CompletionItemKind::Text; + // Use macro signature (if provided) to tell apart function-like and + // object-like macros. + return Signature && Signature->contains('(') ? CompletionItemKind::Function + : CompletionItemKind::Constant; case SK::Enum: return CompletionItemKind::Enum; case SK::Struct: @@ -150,6 +157,8 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) { llvm_unreachable("Unhandled clang::index::SymbolKind."); } +// Note: changes to this function should also be reflected in the +// index::SymbolKind overload where appropriate. CompletionItemKind toCompletionItemKind(const CodeCompletionResult &Res, CodeCompletionContext::Kind CtxKind) { if (Res.Declaration) @@ -379,7 +388,8 @@ struct CodeCompletionBuilder { if (Completion.Scope.empty()) Completion.Scope = std::string(C.IndexResult->Scope); if (Completion.Kind == CompletionItemKind::Missing) - Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind); + Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind, + &C.IndexResult->Signature); if (Completion.Name.empty()) Completion.Name = std::string(C.IndexResult->Name); if (Completion.FilterText.empty()) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 49337bddf98d..8fbac73cb653 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -671,7 +671,8 @@ TEST(CompletionTest, Kinds) { #define MACRO 10 int X = ^ )cpp", - {func("indexFunction"), var("indexVariable"), cls("indexClass")}); + {func("indexFunction"), var("indexVariable"), cls("indexClass"), + macro("indexObjMacro"), macro("indexFuncMacro", "(x, y)")}); EXPECT_THAT(Results.Completions, AllOf(has("function", CompletionItemKind::Function), has("variable", CompletionItemKind::Variable), @@ -680,7 +681,9 @@ TEST(CompletionTest, Kinds) { has("MACRO", CompletionItemKind::Constant), has("indexFunction", CompletionItemKind::Function), has("indexVariable", CompletionItemKind::Variable), - has("indexClass", CompletionItemKind::Class))); + has("indexClass", CompletionItemKind::Class), + has("indexObjMacro", CompletionItemKind::Constant), + has("indexFuncMacro", CompletionItemKind::Function))); Results = completions("nam^"); EXPECT_THAT(Results.Completions, diff --git a/clang-tools-extra/clangd/unittests/TestIndex.cpp b/clang-tools-extra/clangd/unittests/TestIndex.cpp index 278336bdde2e..b13a5d32d175 100644 --- a/clang-tools-extra/clangd/unittests/TestIndex.cpp +++ b/clang-tools-extra/clangd/unittests/TestIndex.cpp @@ -38,7 +38,7 @@ static std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle, // Helpers to produce fake index symbols for memIndex() or completions(). // USRFormat is a regex replacement string for the unqualified part of the USR. Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, - llvm::StringRef USRFormat) { + llvm::StringRef USRFormat, llvm::StringRef Signature) { Symbol Sym; std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand! size_t Pos = QName.rfind("::"); @@ -55,6 +55,7 @@ Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, Sym.SymInfo.Kind = Kind; Sym.Flags |= Symbol::IndexedForCodeCompletion; Sym.Origin = SymbolOrigin::Static; + Sym.Signature = Signature; return Sym; } @@ -86,6 +87,10 @@ Symbol conceptSym(llvm::StringRef Name) { return sym(Name, index::SymbolKind::Concept, "@CT@\\0"); } +Symbol macro(llvm::StringRef Name, llvm::StringRef ArgList) { + return sym(Name, index::SymbolKind::Macro, "@macro@\\0", ArgList); +} + Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind, llvm::StringRef USRPrefix) { Symbol Sym; diff --git a/clang-tools-extra/clangd/unittests/TestIndex.h b/clang-tools-extra/clangd/unittests/TestIndex.h index 9280b0b12a67..0699b29392d7 100644 --- a/clang-tools-extra/clangd/unittests/TestIndex.h +++ b/clang-tools-extra/clangd/unittests/TestIndex.h @@ -20,7 +20,7 @@ Symbol symbol(llvm::StringRef QName); // Helpers to produce fake index symbols with proper SymbolID. // USRFormat is a regex replacement string for the unqualified part of the USR. Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, - llvm::StringRef USRFormat); + llvm::StringRef USRFormat, llvm::StringRef Signature = {}); // Creats a function symbol assuming no function arg. Symbol func(llvm::StringRef Name); // Creates a class symbol. @@ -35,6 +35,8 @@ Symbol var(llvm::StringRef Name); Symbol ns(llvm::StringRef Name); // Create a C++20 concept symbol. Symbol conceptSym(llvm::StringRef Name); +// Create a macro symbol. +Symbol macro(llvm::StringRef Name, llvm::StringRef ArgList = {}); // Create an Objective-C symbol. Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind, -- GitLab From c42a262560a659d1cfb9ec46712ad66420314f2d Mon Sep 17 00:00:00 2001 From: Alexandre Eichenberger Date: Thu, 11 Apr 2024 20:04:26 -0400 Subject: [PATCH 017/464] [MLIR] Bug Fix: affine.prefetch replaceAffineOp invoked during canonicalization (#88346) Signed-off-by: Alexandre Eichenberger --- mlir/lib/Dialect/Affine/IR/AffineOps.cpp | 5 ++--- mlir/test/Dialect/Affine/canonicalize.mlir | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp index c591e5056480..c9c0a7b4cc68 100644 --- a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp +++ b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp @@ -1487,9 +1487,8 @@ void SimplifyAffineOp::replaceAffineOp( PatternRewriter &rewriter, AffinePrefetchOp prefetch, AffineMap map, ArrayRef mapOperands) const { rewriter.replaceOpWithNewOp( - prefetch, prefetch.getMemref(), map, mapOperands, - prefetch.getLocalityHint(), prefetch.getIsWrite(), - prefetch.getIsDataCache()); + prefetch, prefetch.getMemref(), map, mapOperands, prefetch.getIsWrite(), + prefetch.getLocalityHint(), prefetch.getIsDataCache()); } template <> void SimplifyAffineOp::replaceAffineOp( diff --git a/mlir/test/Dialect/Affine/canonicalize.mlir b/mlir/test/Dialect/Affine/canonicalize.mlir index 7c0930eedc85..730808dbbdf1 100644 --- a/mlir/test/Dialect/Affine/canonicalize.mlir +++ b/mlir/test/Dialect/Affine/canonicalize.mlir @@ -1452,3 +1452,17 @@ func.func @mod_of_mod(%lb: index, %ub: index, %step: index) -> (index, index) { %1 = affine.apply affine_map<()[s0, s1, s2] -> ((s0 - ((s0 - s2) mod s1) - s2) mod s1)> ()[%ub, %step, %lb] return %0, %1 : index, index } + +// ----- + +// CHECK-LABEL: func.func @prefetch_canonicalize +// CHECK-SAME: ([[PARAM_0_:%.+]]: memref<512xf32>) { +func.func @prefetch_canonicalize(%arg0: memref<512xf32>) -> () { + // CHECK: affine.for [[I_0_:%.+]] = 0 to 8 { + affine.for %arg3 = 0 to 8 { + %1 = affine.apply affine_map<()[s0] -> (s0 * 64)>()[%arg3] + // CHECK: affine.prefetch [[PARAM_0_]][symbol([[I_0_]]) * 64], read, locality<3>, data : memref<512xf32> + affine.prefetch %arg0[%1], read, locality<3>, data : memref<512xf32> + } + return +} -- GitLab From 56954a53e58282d7584e31ec14a2b1052cd861e8 Mon Sep 17 00:00:00 2001 From: pawelszczerbuk <153013546+pawelszczerbuk@users.noreply.github.com> Date: Thu, 11 Apr 2024 17:09:44 -0700 Subject: [PATCH 018/464] [MLIR][LoopPipelining] Improve schedule verifier, so it checks also operands of nested operations (#88450) `verifySchedule` was not looking at the operands of nested operations, which caused incorrect schedule to be allowed in some cases, potentially leading to crash during expansion. There is also minor fix in `cloneAndUpdateOperands` in the pipeline expander that prevents double visit of the cloned op. This one has no functional impact, so no test for it. --- .../Dialect/SCF/Transforms/LoopPipelining.cpp | 18 +++++++++++---- mlir/test/Dialect/SCF/loop-pipelining.mlir | 23 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/mlir/lib/Dialect/SCF/Transforms/LoopPipelining.cpp b/mlir/lib/Dialect/SCF/Transforms/LoopPipelining.cpp index 9eda1a4597ba..82ec95d31f52 100644 --- a/mlir/lib/Dialect/SCF/Transforms/LoopPipelining.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/LoopPipelining.cpp @@ -203,6 +203,17 @@ bool LoopPipelinerInternal::initializeLoopInfo( return true; } +/// Find operands of all the nested operations within `op`. +static SetVector getNestedOperands(Operation *op) { + SetVector operands; + op->walk([&](Operation *nestedOp) { + for (Value operand : nestedOp->getOperands()) { + operands.insert(operand); + } + }); + return operands; +} + /// Compute unrolled cycles of each op (consumer) and verify that each op is /// scheduled after its operands (producers) while adjusting for the distance /// between producer and consumer. @@ -219,7 +230,7 @@ bool LoopPipelinerInternal::verifySchedule() { } for (Operation *consumer : opOrder) { int64_t consumerCycle = unrolledCyles[consumer]; - for (Value operand : consumer->getOperands()) { + for (Value operand : getNestedOperands(consumer)) { auto [producer, distance] = getDefiningOpAndDistance(operand); if (!producer) continue; @@ -245,9 +256,8 @@ static Operation * cloneAndUpdateOperands(RewriterBase &rewriter, Operation *op, function_ref callback) { Operation *clone = rewriter.clone(*op); - for (OpOperand &operand : clone->getOpOperands()) - callback(&operand); - clone->walk([&](Operation *nested) { + clone->walk([&](Operation *nested) { + // 'clone' itself will be visited first. for (OpOperand &operand : nested->getOpOperands()) { Operation *def = operand.get().getDefiningOp(); if ((def && !clone->isAncestor(def)) || isa(operand.get())) diff --git a/mlir/test/Dialect/SCF/loop-pipelining.mlir b/mlir/test/Dialect/SCF/loop-pipelining.mlir index 8d6f454d1875..46e7feca4329 100644 --- a/mlir/test/Dialect/SCF/loop-pipelining.mlir +++ b/mlir/test/Dialect/SCF/loop-pipelining.mlir @@ -846,3 +846,26 @@ func.func @invalid_schedule2(%A: memref, %result: memref) { } { __test_pipelining_loop__ } return } + +// ----- + +func.func @invalid_schedule3(%A: memref, %result: memref, %ext: index) { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c4 = arith.constant 4 : index + %r = scf.for %i0 = %c0 to %c4 step %c1 iter_args(%idx = %c0) -> (index) { + %cnd = arith.cmpi slt, %ext, %c4 { __test_pipelining_stage__ = 0, __test_pipelining_op_order__ = 0 } : index + // expected-error@+1 {{operation scheduled before its operands}} + %idx1 = scf.if %cnd -> (index) { + %idxinc = arith.addi %idx, %c1 : index + scf.yield %idxinc : index + } else { + scf.yield %idx : index + } { __test_pipelining_stage__ = 0, __test_pipelining_op_order__ = 1 } + %A_elem = memref.load %A[%idx1] { __test_pipelining_stage__ = 0, __test_pipelining_op_order__ = 2 } : memref + %idx2 = arith.addi %idx1, %c1 { __test_pipelining_stage__ = 1, __test_pipelining_op_order__ = 3 } : index + memref.store %A_elem, %result[%idx1] { __test_pipelining_stage__ = 2, __test_pipelining_op_order__ = 4 } : memref + scf.yield %idx2 : index + } { __test_pipelining_loop__ } + return +} -- GitLab From bf1d7b8df287d69ee265b91be40dec37267b2d5c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 11 Apr 2024 16:55:22 -0700 Subject: [PATCH 019/464] [RISCV] Give HWASAN_CHECK_MEMACCESS_SHORTGRANULES pseudo the same code size as PseudoCall. This is converted to a PseudoCall in RISCVAsmPrinter.cpp so it should have the same size of 8 bytes. --- llvm/lib/Target/RISCV/RISCVInstrInfo.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 2cfad7f7c061..f9dadc6c0d48 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1861,7 +1861,7 @@ def : Pat<(trap), (UNIMP)>; def : Pat<(debugtrap), (EBREAK)>; let Predicates = [IsRV64], Uses = [X5], - Defs = [X1, X6, X7, X28, X29, X30, X31] in + Defs = [X1, X6, X7, X28, X29, X30, X31], Size = 8 in def HWASAN_CHECK_MEMACCESS_SHORTGRANULES : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$accessinfo), [(int_hwasan_check_memaccess_shortgranules (i64 X5), GPRJALR:$ptr, -- GitLab From 09d51a841dcfbc41c3d7f3274b109b5f9fb09bb0 Mon Sep 17 00:00:00 2001 From: "Felix (Ting Wang)" Date: Fri, 12 Apr 2024 08:18:01 +0800 Subject: [PATCH 020/464] [PowerPC][AIX] Enable aix-small-local-dynamic-tls target attribute (#86641) Following the aix-small-local-exec-tls target attribute, this patch adds a target attribute for an AIX-specific option in llc that informs the compiler that it can use a faster access sequence for the local-dynamic TLS model (formally named aix-small-local-dynamic-tls) when TLS variables are less than ~32KB in size. The patch either produces an addi/la with a displacement off of module handle (return value from .__tls_get_mod) when the address is calculated, or it produces an addi/la followed by a load/store when the address is calculated and used for further accesses. --------- Co-authored-by: Amy Kwan --- .../MCTargetDesc/PPCXCOFFObjectWriter.cpp | 4 + llvm/lib/Target/PowerPC/PPC.td | 9 + llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 20 +- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 32 +- llvm/lib/Target/PowerPC/PPCMCInstLower.cpp | 13 +- llvm/lib/Target/PowerPC/PPCSubtarget.cpp | 26 +- ...aix-small-local-dynamic-tls-largeaccess.ll | 182 +- .../aix-small-local-dynamic-tls-types.ll | 1601 ++++++++++++++--- ...ix-small-local-exec-tls-opt-IRattribute.ll | 25 +- .../check-aix-small-local-exec-tls-opt.ll | 14 +- 10 files changed, 1530 insertions(+), 396 deletions(-) diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp index f4998e9b9dcb..714ce64a3939 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp @@ -71,6 +71,8 @@ std::pair PPCXCOFFObjectWriter::getRelocTypeAndSignSize( return {XCOFF::RelocationType::R_TOCL, SignAndSizeForHalf16}; case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForHalf16}; + case MCSymbolRefExpr::VK_PPC_AIX_TLSLD: + return {XCOFF::RelocationType::R_TLS_LD, SignAndSizeForHalf16}; } } break; case PPC::fixup_ppc_half16ds: @@ -86,6 +88,8 @@ std::pair PPCXCOFFObjectWriter::getRelocTypeAndSignSize( return {XCOFF::RelocationType::R_TOCL, 15}; case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: return {XCOFF::RelocationType::R_TLS_LE, 15}; + case MCSymbolRefExpr::VK_PPC_AIX_TLSLD: + return {XCOFF::RelocationType::R_TLS_LD, 15}; } } break; case PPC::fixup_ppc_br24: diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td index 535616d33a80..b962ed28d720 100644 --- a/llvm/lib/Target/PowerPC/PPC.td +++ b/llvm/lib/Target/PowerPC/PPC.td @@ -329,6 +329,15 @@ def FeatureAIXLocalExecTLS : "Produce a TOC-free local-exec TLS sequence for this function " "for 64-bit AIX">; +// Specifies that local-dynamic TLS accesses in any function with this target +// attribute should use the optimized sequence (where the offset is an immediate +// off the module-handle for which the linker might add fix-up code for if the +// immediate is too large). +def FeatureAIXLocalDynamicTLS : + SubtargetFeature<"aix-small-local-dynamic-tls", "HasAIXSmallLocalDynamicTLS", + "true", "Produce a faster local-dynamic TLS sequence for this " + "function for 64-bit AIX">; + def FeaturePredictableSelectIsExpensive : SubtargetFeature<"predictable-select-expensive", "PredictableSelectIsExpensive", diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 16942c6893a1..1c57b92057ff 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -803,7 +803,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { MCInst TmpInst; const bool IsPPC64 = Subtarget->isPPC64(); const bool IsAIX = Subtarget->isAIXABI(); - const bool HasAIXSmallLocalExecTLS = Subtarget->hasAIXSmallLocalExecTLS(); + const bool HasAIXSmallLocalTLS = Subtarget->hasAIXSmallLocalExecTLS() || + Subtarget->hasAIXSmallLocalDynamicTLS(); const Module *M = MF->getFunction().getParent(); PICLevel::Level PL = M->getPICLevel(); @@ -1612,11 +1613,11 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { case PPC::LFD: case PPC::STFD: case PPC::ADDI8: { - // A faster non-TOC-based local-exec sequence is represented by `addi` - // or a load/store instruction (that directly loads or stores off of the - // thread pointer) with an immediate operand having the MO_TPREL_FLAG. + // A faster non-TOC-based local-[exec|dynamic] sequence is represented by + // `addi` or a load/store instruction (that directly loads or stores off of + // the thread pointer) with an immediate operand having the MO_TPREL_FLAG. // Such instructions do not otherwise arise. - if (!HasAIXSmallLocalExecTLS) + if (!HasAIXSmallLocalTLS) break; bool IsMIADDI8 = MI->getOpcode() == PPC::ADDI8; unsigned OpNum = IsMIADDI8 ? 2 : 1; @@ -1624,7 +1625,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { unsigned Flag = MO.getTargetFlags(); if (Flag == PPCII::MO_TPREL_FLAG || Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG || - Flag == PPCII::MO_TPREL_PCREL_FLAG) { + Flag == PPCII::MO_TPREL_PCREL_FLAG || Flag == PPCII::MO_TLSLD_FLAG) { LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); const MCExpr *Expr = getAdjustedLocalExecExpr(MO, MO.getOffset()); @@ -1672,7 +1673,12 @@ const MCExpr *PPCAsmPrinter::getAdjustedLocalExecExpr(const MachineOperand &MO, assert(MO.isGlobal() && "Only expecting a global MachineOperand here!"); const GlobalValue *GValue = MO.getGlobal(); - assert(TM.getTLSModel(GValue) == TLSModel::LocalExec && + // TODO: Handle the aix-small-local-dynamic-tls non-zero offset case. + TLSModel::Model Model = TM.getTLSModel(GValue); + if (Model == TLSModel::LocalDynamic) { + return nullptr; + } + assert(Model == TLSModel::LocalExec && "Only local-exec accesses are handled!"); bool IsGlobalADeclaration = GValue->isDeclarationForLinker(); diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 52d5b7136705..d27932f2915f 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -153,10 +153,10 @@ static SDValue widenVec(SelectionDAG &DAG, SDValue Vec, const SDLoc &dl); static const char AIXSSPCanaryWordName[] = "__ssp_canary_word"; -// A faster local-exec TLS access sequence (enabled with the -// -maix-small-local-exec-tls option) can be produced for TLS variables; -// consistent with the IBM XL compiler, we apply a max size of slightly under -// 32KB. +// A faster local-[exec|dynamic] TLS access sequence (enabled with the +// -maix-small-local-[exec|dynamic]-tls option) can be produced for TLS +// variables; consistent with the IBM XL compiler, we apply a max size of +// slightly under 32KB. constexpr uint64_t AIXSmallTlsPolicySizeLimit = 32751; // FIXME: Remove this once the bug has been fixed! @@ -3434,6 +3434,14 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, } if (Model == TLSModel::LocalDynamic) { + bool HasAIXSmallLocalDynamicTLS = Subtarget.hasAIXSmallLocalDynamicTLS(); + + // We do not implement the 32-bit version of the faster access sequence + // for local-dynamic that is controlled by -maix-small-local-dynamic-tls. + if (!Is64Bit && HasAIXSmallLocalDynamicTLS) + report_fatal_error("The small-local-dynamic TLS access sequence is " + "currently only supported on AIX (64-bit mode)."); + // For local-dynamic on AIX, we need to generate one TOC entry for each // variable offset, and a single module-handle TOC entry for the entire // file. @@ -3454,6 +3462,22 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, SDValue ModuleHandle = DAG.getNode(PPCISD::TLSLD_AIX, dl, PtrVT, ModuleHandleTOC); + // With the -maix-small-local-dynamic-tls option, produce a faster access + // sequence for local-dynamic TLS variables where the offset from the + // module-handle is encoded as an immediate operand. + // + // We only utilize the faster local-dynamic access sequence when the TLS + // variable has a size within the policy limit. We treat types that are + // not sized or are empty as being over the policy size limit. + if (HasAIXSmallLocalDynamicTLS) { + Type *GVType = GV->getValueType(); + if (GVType->isSized() && !GVType->isEmptyTy() && + GV->getParent()->getDataLayout().getTypeAllocSize(GVType) <= + AIXSmallTlsPolicySizeLimit) + return DAG.getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA, + ModuleHandle); + } + return DAG.getNode(ISD::ADD, dl, PtrVT, ModuleHandle, VariableOffset); } diff --git a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp index 9a3ca5a78293..c05bb37e58bf 100644 --- a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp +++ b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp @@ -96,15 +96,18 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; - else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG) { + else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG || + MO.getTargetFlags() == PPCII::MO_TLSLD_FLAG) { assert(MO.isGlobal() && "Only expecting a global MachineOperand here!"); TLSModel::Model Model = TM.getTLSModel(MO.getGlobal()); - // For the local-exec TLS model, we may generate the offset from the TLS - // base as an immediate operand (instead of using a TOC entry). - // Set the relocation type in case the result is used for purposes other - // than a TOC reference. In TOC reference cases, this result is discarded. + // For the local-[exec|dynamic] TLS model, we may generate the offset from + // the TLS base as an immediate operand (instead of using a TOC entry). Set + // the relocation type in case the result is used for purposes other than a + // TOC reference. In TOC reference cases, this result is discarded. if (Model == TLSModel::LocalExec) RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE; + else if (Model == TLSModel::LocalDynamic) + RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLD; } const MachineInstr *MI = MO.getParent(); diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index 653d9bda9919..d1722555f1fc 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -124,22 +124,22 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, // Determine endianness. IsLittleEndian = TM.isLittleEndian(); - if (HasAIXSmallLocalExecTLS) { + if (HasAIXSmallLocalExecTLS || HasAIXSmallLocalDynamicTLS) { if (!TargetTriple.isOSAIX() || !IsPPC64) - report_fatal_error( - "The aix-small-local-exec-tls attribute is only supported on AIX in " - "64-bit mode.\n", - false); - // The aix-small-local-exec-tls attribute should only be used with + report_fatal_error("The aix-small-local-[exec|dynamic]-tls attribute is " + "only supported on AIX in " + "64-bit mode.\n", + false); + // The aix-small-local-[exec|dynamic]-tls attribute should only be used with // -data-sections, as having data sections turned off with this option - // is not ideal for performance. Moreover, the small-local-exec-tls region - // is a limited resource, and should not be used for variables that may - // be replaced. + // is not ideal for performance. Moreover, the + // small-local-[exec|dynamic]-tls region is a limited resource, and should + // not be used for variables that may be replaced. if (!TM.getDataSections()) - report_fatal_error( - "The aix-small-local-exec-tls attribute can only be specified with " - "-data-sections.\n", - false); + report_fatal_error("The aix-small-local-[exec|dynamic]-tls attribute can " + "only be specified with " + "-data-sections.\n", + false); } } diff --git a/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll index eb16bae67150..7db1048c258c 100644 --- a/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll +++ b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll @@ -1,9 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 ; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ -; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s \ +; RUN: -mattr=+aix-small-local-dynamic-tls -mtriple powerpc64-ibm-aix-xcoff < %s \ ; RUN: | FileCheck %s --check-prefix=SMALL-LOCAL-DYNAMIC-SMALLCM64 ; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ -; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: -mattr=+aix-small-local-dynamic-tls -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ ; RUN: < %s | FileCheck %s \ ; RUN: --check-prefix=SMALL-LOCAL-DYNAMIC-LARGECM64 @@ -39,27 +39,23 @@ define signext i32 @test1() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r6, L..C1(r2) # target-flags(ppc-tlsld) @ElementIntTLS2 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r7, L..C2(r2) # target-flags(ppc-tlsld) @ElementIntTLS3 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r8, L..C3(r2) # target-flags(ppc-tlsld) @ElementIntTLS4 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r9, L..C4(r2) # target-flags(ppc-tlsld) @ElementIntTLS5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r6, 4 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r5, L..C5(r2) # target-flags(ppc-tlsld) @ElementIntTLSv1 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 1 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r6, r3, r6 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r7, r3, r7 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r8, r3, r8 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r9, r3, r9 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stwux r4, r3, r5 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 4 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 24(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 2 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 320(r6) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 3 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 324(r7) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 88 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 328(r8) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 332(r9) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r5, 1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r4, ElementIntTLSv1[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r5, ElementIntTLSv1[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r5, ElementIntTLS2[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r6, 24(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 2 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 320(r5) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r4, ElementIntTLS3[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r5, 3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r5, 324(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r4, ElementIntTLS4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r3, ElementIntTLS5[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r6, 328(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 88 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 332(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 102 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) @@ -71,34 +67,25 @@ define signext i32 @test1() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C1@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C2@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r6, 4 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r8, L..C3@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r9, L..C4@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r7, L..C2@l(r7) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r8, L..C3@l(r8) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r9, L..C4@l(r9) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r5, L..C1@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C5@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 1 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r6, L..C5@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r7, r3, r7 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r8, r3, r8 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r9, r3, r9 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r6, r3, r6 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stwux r4, r3, r5 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 4 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 24(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 2 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 320(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 3 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 324(r7) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 88 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 328(r8) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 332(r9) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r5, 1 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r4, ElementIntTLSv1[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r5, ElementIntTLSv1[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r5, ElementIntTLS2[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r6, 24(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 2 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 320(r5) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r4, ElementIntTLS3[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r5, 3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r5, 324(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r4, ElementIntTLS4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r3, ElementIntTLS5[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r6, 328(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 88 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 332(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 102 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) @@ -144,31 +131,26 @@ define i64 @test2() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C6(r2) # target-flags(ppc-tlsld) @ElementLongTLS6 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mr r6, r3 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 212 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r4, r6, r4 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r3, 424(r4) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C7(r2) # target-flags(ppc-tlsld) @ElementLongTLS2 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r3, ElementLongTLS6[UL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 212 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 424(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r3, ElementLongTLS2[TL]@ld(r6) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 203 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r6, r3 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 1200(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C8(r2) # target-flags(ppc-tlsgdm) @MyTLSGDVar -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsgd) @MyTLSGDVar +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tlsgdm) @MyTLSGDVar +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tlsgd) @MyTLSGDVar ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_addr[PR] ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 44 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 440(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C10(r2) # target-flags(ppc-tlsld) @ElementLongTLS3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r3, ElementLongTLS3[TL]@ld(r6) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 6 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r6, r3 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 2000(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @ElementLongTLS4 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 100 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r4, r6, r4 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r3, 6800(r4) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C12(r2) # target-flags(ppc-tlsld) @ElementLongTLS5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r3, ElementLongTLS4[TL]@ld(r6) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 100 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 6800(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r3, ElementLongTLS5[TL]@ld(r6) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 882 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r6, r3 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 8400(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 1191 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 @@ -182,40 +164,30 @@ define i64 @test2() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C6@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 212 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mr r6, r3 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C6@l(r7) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r3, ElementLongTLS6[UL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 424(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C7@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r3, ElementLongTLS2[TL]@ld(r6) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 203 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C7@l(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 1200(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C8@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r4, L..C9@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C8@l(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C9@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r4, L..C2@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C2@l(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_addr[PR] ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 44 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 440(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C10@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r3, ElementLongTLS3[TL]@ld(r6) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 6 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C10@l(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 2000(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C11@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r3, ElementLongTLS4[TL]@ld(r6) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 100 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C11@l(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 6800(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C12@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r3, ElementLongTLS5[TL]@ld(r6) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 882 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C12@l(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 8400(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 1191 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 @@ -257,27 +229,23 @@ define signext i32 @test3() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r8, L..C3(r2) # target-flags(ppc-tlsld) @ElementIntTLSv2 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r6, L..C1(r2) # target-flags(ppc-tlsld) @ElementIntTLS2 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r7, L..C2(r2) # target-flags(ppc-tlsld) @ElementIntTLS3 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r8, L..C3(r2) # target-flags(ppc-tlsld) @ElementIntTLS4 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r9, L..C4(r2) # target-flags(ppc-tlsld) @ElementIntTLS5 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r5, L..C13(r2) # target-flags(ppc-tlsld) @ElementIntTLSv2 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 1 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r6, r3, r6 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r7, r3, r7 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r8, r3, r8 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r9, r3, r9 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stwux r4, r3, r5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r5, ElementIntTLS2[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r6, ElementIntTLS3[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r7, ElementIntTLS4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r9, ElementIntTLS5[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stwux r4, r3, r8 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 4 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 24(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 2 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 320(r6) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 320(r5) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 3 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 324(r7) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 324(r6) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 88 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 328(r8) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 328(r7) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 332(r9) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 102 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 @@ -290,29 +258,21 @@ define signext i32 @test3() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C13@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C3@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C2@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r8, L..C3@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r9, L..C4@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r7, L..C2@l(r7) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r8, L..C3@l(r8) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r9, L..C4@l(r9) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r6, L..C3@l(r6) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r5, L..C13@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C5@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 1 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r6, L..C5@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r7, r3, r7 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r8, r3, r8 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r9, r3, r9 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r6, r3, r6 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stwux r4, r3, r5 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r5, ElementIntTLS2[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r7, ElementIntTLS3[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r8, ElementIntTLS4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r9, ElementIntTLS5[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stwux r4, r3, r6 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 4 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 24(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 2 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 320(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 320(r5) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 324(r7) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 88 diff --git a/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-types.ll b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-types.ll index d996d86a23d8..161a58a90296 100644 --- a/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-types.ll +++ b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-types.ll @@ -1,18 +1,30 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 ; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ -; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s \ +; RUN: -mattr=+aix-small-local-dynamic-tls -mtriple powerpc64-ibm-aix-xcoff < %s \ ; RUN: | FileCheck %s --check-prefix=SMALL-LOCAL-DYNAMIC-SMALLCM64 ; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mattr=+aix-small-local-dynamic-tls -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: < %s | FileCheck %s --check-prefix=SMALL-LOCAL-DYNAMIC-LARGECM64 +; RUN: llc -O0 -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mattr=+aix-small-local-dynamic-tls -mtriple powerpc64-ibm-aix-xcoff < %s \ +; RUN: | FileCheck %s --check-prefix=SMALL-LOCAL-DYNAMIC-SMALLCM64-O0 +; RUN: llc -O0 -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mattr=+aix-small-local-dynamic-tls -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: < %s | FileCheck %s --check-prefix=SMALL-LOCAL-DYNAMIC-LARGECM64-O0 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s \ +; RUN: | FileCheck %s --check-prefix=DEFAULT-LOCAL-DYNAMIC-SMALLCM64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ ; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ ; RUN: < %s | FileCheck %s \ -; RUN: --check-prefix=SMALL-LOCAL-DYNAMIC-LARGECM64 +; RUN: --check-prefix=DEFAULT-LOCAL-DYNAMIC-LARGECM64 ; RUN: llc -O0 -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ ; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s \ -; RUN: | FileCheck %s --check-prefix=SMALL-LOCAL-DYNAMIC-SMALLCM64-O0 +; RUN: | FileCheck %s --check-prefix=DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0 ; RUN: llc -O0 -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ ; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ ; RUN: < %s | FileCheck %s \ -; RUN: --check-prefix=SMALL-LOCAL-DYNAMIC-LARGECM64-O0 +; RUN: --check-prefix=DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0 declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #1 @tlv_int_init = local_unnamed_addr global i32 87, align 4 @@ -27,7 +39,8 @@ declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #1 @internal_tlv_double = internal thread_local(localdynamic) global double 1.000000e+00, align 8 %struct.anon = type { i32 } -@ThreadLocalStruct = thread_local(localdynamic) global %struct.anon zeroinitializer, align 1 +@ThreadLocalStructAlign1 = thread_local(localdynamic) global %struct.anon zeroinitializer, align 1 +@ThreadLocalStructAlign4 = thread_local(localdynamic) global %struct.anon zeroinitializer, align 4 @a = thread_local(localdynamic) global [87 x i32] zeroinitializer, align 4 define nonnull ptr @AddrTest1() local_unnamed_addr { @@ -38,8 +51,7 @@ define nonnull ptr @AddrTest1() local_unnamed_addr { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tlsld) @a -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r3, a[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r3, r3, 12 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) @@ -51,12 +63,10 @@ define nonnull ptr @AddrTest1() local_unnamed_addr { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C1@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C1@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r3, a[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r3, r3, 12 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) @@ -70,8 +80,7 @@ define nonnull ptr @AddrTest1() local_unnamed_addr { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tlsld) @a -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, a[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r3, r3, 12 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) @@ -81,27 +90,212 @@ define nonnull ptr @AddrTest1() local_unnamed_addr { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: AddrTest1: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C0@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, a[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r3, 12 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: AddrTest1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tlsld) @a +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r3, r3, 12 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: AddrTest1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C1@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r3, r3, 12 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: AddrTest1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tlsld) @a +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r3, r3, 12 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: AddrTest1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C0@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r3, 12 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @a) %arrayidx = getelementptr inbounds [87 x i32], ptr %tlv_addr, i64 0, i64 3 ret ptr %arrayidx } +; Demonstrates when offset is zero, addi for the offset is optimized out. +define nonnull ptr @AddrTest2() local_unnamed_addr { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: AddrTest2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r3, a[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: AddrTest2: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r3, a[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: AddrTest2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, a[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: AddrTest2: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, a[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: AddrTest2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tlsld) @a +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: AddrTest2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C1@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: AddrTest2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tlsld) @a +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: AddrTest2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C0@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @a) + %arrayidx = getelementptr inbounds [87 x i32], ptr %tlv_addr, i64 0, i64 0 + ret ptr %arrayidx +} + define signext i32 @testUnaligned() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testUnaligned: ; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry @@ -110,8 +304,8 @@ define signext i32 @testUnaligned() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tlsld) @ThreadLocalStruct -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwax r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r3, ThreadLocalStructAlign1[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwa r3, 0(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 @@ -122,12 +316,11 @@ define signext i32 @testUnaligned() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C2@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C2@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwax r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r3, ThreadLocalStructAlign1[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwa r3, 0(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 @@ -140,8 +333,7 @@ define signext i32 @testUnaligned() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tlsld) @ThreadLocalStruct -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, ThreadLocalStructAlign1[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 0(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) @@ -151,26 +343,213 @@ define signext i32 @testUnaligned() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testUnaligned: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C2@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C2@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, ThreadLocalStructAlign1[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 0(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testUnaligned: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tlsld) @ThreadLocalStructAlign1 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwax r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testUnaligned: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C2@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C2@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lwax r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testUnaligned: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tlsld) @ThreadLocalStructAlign1 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testUnaligned: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C2@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C2@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: - %tlv_addr = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @ThreadLocalStruct) - %x = getelementptr inbounds %struct.anon, ptr %tlv_addr, i32 0, i32 0 - %value = load i32, ptr %x, align 1 - ret i32 %value + %tlv_addr1 = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @ThreadLocalStructAlign1) + %x = getelementptr inbounds %struct.anon, ptr %tlv_addr1, i32 0, i32 0 + %value1 = load i32, ptr %x, align 1 + ret i32 %value1 +} + +define signext i32 @testAligned() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testAligned: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwa r3, ThreadLocalStructAlign4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testAligned: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwa r3, ThreadLocalStructAlign4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testAligned: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, ThreadLocalStructAlign4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testAligned: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, ThreadLocalStructAlign4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testAligned: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C3(r2) # target-flags(ppc-tlsld) @ThreadLocalStructAlign4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwax r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testAligned: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C3@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C3@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lwax r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testAligned: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C3(r2) # target-flags(ppc-tlsld) @ThreadLocalStructAlign4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testAligned: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C3@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C3@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr1 = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 4 @ThreadLocalStructAlign4) + %x = getelementptr inbounds %struct.anon, ptr %tlv_addr1, i32 0, i32 0 + %value1 = load i32, ptr %x, align 1 + ret i32 %value1 } define void @testChar(i8 noundef signext %x) { @@ -182,8 +561,7 @@ define void @testChar(i8 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C3(r2) # target-flags(ppc-tlsld) @tlv_char -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stbx r6, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stb r6, tlv_char[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 @@ -195,12 +573,10 @@ define void @testChar(i8 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mr r6, r3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C3@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C3@l(r7) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stbx r6, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stb r6, tlv_char[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 @@ -217,8 +593,7 @@ define void @testChar(i8 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mr r4, r3 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r5, L..C3(r2) # target-flags(ppc-tlsld) @tlv_char -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r4, r4, r5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r4, tlv_char[TL]@ld(r4) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stb r3, 0(r4) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) @@ -232,21 +607,91 @@ define void @testChar(i8 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C3@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 48(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, 48(r1) # 8-byte Folded Reload ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mr r4, r3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, L..C3@l(r5) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r4, r4, r5 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r4, tlv_char[TL]@ld(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stb r3, 0(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testChar: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mr r6, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C4(r2) # target-flags(ppc-tlsld) @tlv_char +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stbx r6, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testChar: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mr r6, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C4@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C4@l(r7) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stbx r6, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testChar: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mr r4, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r5, L..C4(r2) # target-flags(ppc-tlsld) @tlv_char +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r4, r4, r5 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stb r3, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testChar: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C4@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 48(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, 48(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mr r4, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, L..C4@l(r5) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r4, r4, r5 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stb r3, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @tlv_char) store i8 %x, ptr %tlv_addr, align 1 @@ -262,8 +707,7 @@ define void @testShort(i16 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C4(r2) # target-flags(ppc-tlsld) @tlv_short -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: sthx r6, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: sth r6, tlv_short[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 @@ -275,12 +719,10 @@ define void @testShort(i16 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mr r6, r3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C4@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C4@l(r7) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: sthx r6, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: sth r6, tlv_short[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 @@ -297,8 +739,7 @@ define void @testShort(i16 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mr r4, r3 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r5, L..C4(r2) # target-flags(ppc-tlsld) @tlv_short -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r4, r4, r5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r4, tlv_short[TL]@ld(r4) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: sth r3, 0(r4) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) @@ -312,21 +753,91 @@ define void @testShort(i16 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C4@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 48(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, 48(r1) # 8-byte Folded Reload ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mr r4, r3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, L..C4@l(r5) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r4, r4, r5 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r4, tlv_short[TL]@ld(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: sth r3, 0(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testShort: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mr r6, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C5(r2) # target-flags(ppc-tlsld) @tlv_short +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: sthx r6, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testShort: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mr r6, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C5@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C5@l(r7) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: sthx r6, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testShort: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mr r4, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r5, L..C5(r2) # target-flags(ppc-tlsld) @tlv_short +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r4, r4, r5 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: sth r3, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testShort: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C5@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 48(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, 48(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mr r4, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, L..C5@l(r5) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r4, r4, r5 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: sth r3, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 2 ptr @llvm.threadlocal.address.p0(ptr align 2 @tlv_short) store i16 %x, ptr %tlv_addr, align 2 @@ -341,8 +852,7 @@ define signext i32 @testInt1() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C5(r2) # target-flags(ppc-tlsld) @tlv_int -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwax r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwa r3, tlv_int[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 @@ -353,12 +863,10 @@ define signext i32 @testInt1() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C5@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C5@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwax r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwa r3, tlv_int[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 @@ -371,8 +879,7 @@ define signext i32 @testInt1() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C5(r2) # target-flags(ppc-tlsld) @tlv_int -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, tlv_int[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 0(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) @@ -382,21 +889,81 @@ define signext i32 @testInt1() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testInt1: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C5@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C5@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, tlv_int[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 0(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testInt1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C6(r2) # target-flags(ppc-tlsld) @tlv_int +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwax r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testInt1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C6@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C6@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lwax r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testInt1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C6(r2) # target-flags(ppc-tlsld) @tlv_int +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testInt1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C6@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C6@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @tlv_int) %value = load i32, ptr %tlv_addr, align 4 @@ -411,9 +978,8 @@ define signext i32 @testInt2() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C6(r2) # target-flags(ppc-tlsld) @internal_tlv_int -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwzx r3, r3, r4 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C7(r2) # @tlv_int_init +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C1(r2) # @tlv_int_init +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwz r3, internal_tlv_int[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwz r4, 0(r4) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r4, r3 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: extsw r3, r3 @@ -427,14 +993,12 @@ define signext i32 @testInt2() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C6@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C6@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwzx r3, r3, r4 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r4, L..C7@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C7@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r4, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C1@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwz r3, internal_tlv_int[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwz r4, 0(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r4, r3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: extsw r3, r3 @@ -450,10 +1014,9 @@ define signext i32 @testInt2() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C6(r2) # target-flags(ppc-tlsld) @internal_tlv_int -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, internal_tlv_int[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r4, 0(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C7(r2) # @tlv_int_init +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C1(r2) # @tlv_int_init ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 0(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: extsw r3, r3 @@ -465,26 +1028,104 @@ define signext i32 @testInt2() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testInt2: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C6@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C6@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, internal_tlv_int[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r4, 0(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C7@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C7@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 0(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: extsw r3, r3 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testInt2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C7(r2) # target-flags(ppc-tlsld) @internal_tlv_int +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwzx r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C8(r2) # @tlv_int_init +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwz r4, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r4, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: extsw r3, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testInt2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C7@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C7@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lwzx r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r4, L..C8@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C8@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lwz r4, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r4, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: extsw r3, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testInt2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C7(r2) # target-flags(ppc-tlsld) @internal_tlv_int +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r4, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C8(r2) # @tlv_int_init +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: extsw r3, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testInt2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C7@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C7@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r4, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C8@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C8@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: extsw r3, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @internal_tlv_int) %tlv_val = load i32, ptr %tlv_addr, align 4 @@ -501,8 +1142,7 @@ define signext i64 @testLong1() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C8(r2) # target-flags(ppc-tlsld) @tlv_long -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ldx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 @@ -513,12 +1153,10 @@ define signext i64 @testLong1() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C8@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C8@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ldx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 @@ -531,8 +1169,7 @@ define signext i64 @testLong1() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C8(r2) # target-flags(ppc-tlsld) @tlv_long -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, 0(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) @@ -542,21 +1179,81 @@ define signext i64 @testLong1() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testLong1: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C8@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C8@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, 0(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testLong1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsld) @tlv_long +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ldx r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testLong1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C9@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C9@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ldx r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testLong1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsld) @tlv_long +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testLong1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C9@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C9@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @tlv_long) %value = load i64, ptr %tlv_addr, align 4 @@ -571,10 +1268,9 @@ define void @testLong2(i64 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsld) @internal_tlv_long -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ldx r5, r3, r4 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r5, r5, 9 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdx r5, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, internal_tlv_long[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r4, r4, 9 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, internal_tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 @@ -585,14 +1281,12 @@ define void @testLong2(i64 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C9@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C9@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ldx r5, r3, r4 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r5, r5, 9 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdx r5, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, internal_tlv_long[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r4, r4, 9 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, internal_tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 @@ -605,8 +1299,7 @@ define void @testLong2(i64 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsld) @internal_tlv_long -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r4, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r4, internal_tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, 0(r4) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r3, r3, 9 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r3, 0(r4) @@ -618,23 +1311,91 @@ define void @testLong2(i64 noundef signext %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testLong2: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C9@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C9@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r4, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r4, internal_tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, 0(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r3, 9 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 0(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testLong2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @internal_tlv_long +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ldx r5, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r5, r5, 9 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdx r5, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testLong2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C10@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C10@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ldx r5, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r5, r5, 9 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdx r5, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testLong2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @internal_tlv_long +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r4, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r3, r3, 9 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r3, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testLong2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C10@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C10@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r4, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r3, 9 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @internal_tlv_long) %value = load i64, ptr %tlv_addr, align 8 @@ -651,8 +1412,7 @@ define i32 @testLong3() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C8(r2) # target-flags(ppc-tlsld) @tlv_long -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ldx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 @@ -663,12 +1423,10 @@ define i32 @testLong3() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C8@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C8@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ldx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 @@ -681,8 +1439,7 @@ define i32 @testLong3() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C8(r2) # target-flags(ppc-tlsld) @tlv_long -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, 0(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: clrldi r3, r3, 32 @@ -694,23 +1451,87 @@ define i32 @testLong3() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testLong3: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C8@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C8@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, tlv_long[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, 0(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: clrldi r3, r3, 32 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testLong3: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsld) @tlv_long +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ldx r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testLong3: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C9@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C9@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ldx r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testLong3: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsld) @tlv_long +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: clrldi r3, r3, 32 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testLong3: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C9@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C9@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: clrldi r3, r3, 32 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @tlv_long) %value = load i64, ptr %tlv_addr, align 8 @@ -723,18 +1544,17 @@ define void @testFloat1(float noundef %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: vspltisw v2, 1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: vspltisw v3, 8 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: xvcvsxwdp vs0, vs34 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @tlv_float -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfsx f1, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfs f1, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: fadds f0, f1, f0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: xvcvsxwdp vs1, vs35 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: fadds f0, f0, f1 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfsx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfs f0, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 @@ -744,20 +1564,18 @@ define void @testFloat1(float noundef %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: vspltisw v2, 1 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C10@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: vspltisw v3, 8 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: xvcvsxwdp vs0, vs34 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C10@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lfsx f1, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lfs f1, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: fadds f0, f1, f0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: xvcvsxwdp vs1, vs35 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: fadds f0, f0, f1 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfsx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfs f0, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 @@ -770,13 +1588,12 @@ define void @testFloat1(float noundef %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @tlv_float -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f0, 0(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C11(r2) # %const.1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C2(r2) # %const.1 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f1, 0(r4) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: fadds f0, f0, f1 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C12(r2) # %const.0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C3(r2) # %const.0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f1, 0(r4) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: fadds f0, f0, f1 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stfs f0, 0(r3) @@ -788,30 +1605,120 @@ define void @testFloat1(float noundef %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testFloat1: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C10@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C10@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f0, 0(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r4, L..C11@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C11@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r4, L..C2@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C2@l(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f1, 0(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: fadds f0, f0, f1 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r4, L..C12@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C12@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r4, L..C3@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C3@l(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f1, 0(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: fadds f0, f0, f1 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stfs f0, 0(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testFloat1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: vspltisw v2, 1 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: vspltisw v3, 8 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: xvcvsxwdp vs0, vs34 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @tlv_float +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfsx f1, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: fadds f0, f1, f0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: xvcvsxwdp vs1, vs35 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: fadds f0, f0, f1 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfsx f0, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testFloat1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: vspltisw v2, 1 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C11@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: vspltisw v3, 8 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: xvcvsxwdp vs0, vs34 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C11@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lfsx f1, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: fadds f0, f1, f0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: xvcvsxwdp vs1, vs35 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: fadds f0, f0, f1 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stfsx f0, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testFloat1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @tlv_float +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f0, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C12(r2) # %const.1 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f1, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: fadds f0, f0, f1 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C13(r2) # %const.0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f1, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: fadds f0, f0, f1 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stfs f0, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testFloat1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C11@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C11@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f0, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r4, L..C12@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C12@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f1, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: fadds f0, f0, f1 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r4, L..C13@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C13@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f1, 0(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: fadds f0, f0, f1 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stfs f0, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @tlv_float) %value = load float, ptr %tlv_addr, align 4 @@ -829,8 +1736,7 @@ define i32 @testFloat2() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 80(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @tlv_float -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfsx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfs f0, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r3, r1, 60 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: xscvdpsxws f0, f0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfiwx f0, 0, r3 @@ -845,12 +1751,10 @@ define i32 @testFloat2() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C10@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 80(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C10@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lfsx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lfs f0, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r3, r1, 60 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: xscvdpsxws f0, f0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfiwx f0, 0, r3 @@ -867,8 +1771,7 @@ define i32 @testFloat2() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @tlv_float -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f0, 0(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: fctiwz f0, f0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stfd f0, 56(r1) @@ -884,14 +1787,10 @@ define i32 @testFloat2() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C10@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 48(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 48(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C10@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, tlv_float[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f0, 0(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: fctiwz f0, f0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stfd f0, 56(r1) @@ -901,6 +1800,86 @@ define i32 @testFloat2() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testFloat2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @tlv_float +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfsx f0, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r3, r1, 60 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: xscvdpsxws f0, f0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfiwx f0, 0, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwz r3, 60(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testFloat2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C11@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C11@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lfsx f0, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r3, r1, 60 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: xscvdpsxws f0, f0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stfiwx f0, 0, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lwz r3, 60(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testFloat2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @tlv_float +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f0, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: fctiwz f0, f0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stfd f0, 56(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 60(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: clrldi r3, r3, 32 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testFloat2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C11@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 48(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 48(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C11@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f0, 0(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: fctiwz f0, f0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stfd f0, 56(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 60(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: clrldi r3, r3, 32 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @tlv_float) %value = load float, ptr %tlv_addr, align 4 @@ -916,8 +1895,7 @@ define void @testDouble1(double noundef %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @internal_tlv_double -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfdx f1, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfd f1, internal_tlv_double[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 @@ -928,12 +1906,10 @@ define void @testDouble1(double noundef %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C11@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C11@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfdx f1, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfd f1, internal_tlv_double[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 @@ -946,8 +1922,7 @@ define void @testDouble1(double noundef %x) { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C13(r2) # target-flags(ppc-tlsld) @internal_tlv_double -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, internal_tlv_double[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stxsdx f1, 0, r3 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) @@ -957,21 +1932,81 @@ define void @testDouble1(double noundef %x) { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testDouble1: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C13@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C13@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, internal_tlv_double[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stxsdx f1, 0, r3 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testDouble1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C12(r2) # target-flags(ppc-tlsld) @internal_tlv_double +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfdx f1, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testDouble1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C12@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C12@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stfdx f1, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testDouble1: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C14(r2) # target-flags(ppc-tlsld) @internal_tlv_double +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stxsdx f1, 0, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testDouble1: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C14@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C14@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stxsdx f1, 0, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @internal_tlv_double) store double %x, ptr %tlv_addr, align 8 @@ -986,8 +2021,7 @@ define i32 @testDouble2() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 80(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @internal_tlv_double -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfdx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfd f0, internal_tlv_double[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r3, r1, 60 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: xscvdpsxws f0, f0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfiwx f0, 0, r3 @@ -1002,12 +2036,10 @@ define i32 @testDouble2() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -64(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C11@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 80(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C11@l(r6) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lfdx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lfd f0, internal_tlv_double[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r3, r1, 60 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: xscvdpsxws f0, f0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfiwx f0, 0, r3 @@ -1024,8 +2056,9 @@ define i32 @testDouble2() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C13(r2) # target-flags(ppc-tlsld) @internal_tlv_double -; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfdx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: la r3, internal_tlv_double[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfd f0, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: # kill: def $f1 killed $f0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: xscvdpsxws f0, f0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r3, r1, 52 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stfiwx f0, 0, r3 @@ -1039,25 +2072,103 @@ define i32 @testDouble2() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testDouble2: ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -80(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 96(r1) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C13@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C13@l(r4) -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfdx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: la r3, internal_tlv_double[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfd f0, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $f1 killed $f0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: xscvdpsxws f0, f0 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r1, 68 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r1, 52 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stfiwx f0, 0, r3 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 68(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 52(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: clrldi r3, r3, 32 -; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 80 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-LABEL: testDouble2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C12(r2) # target-flags(ppc-tlsld) @internal_tlv_double +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfdx f0, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r3, r1, 60 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: xscvdpsxws f0, f0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfiwx f0, 0, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwz r3, 60(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-LABEL: testDouble2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C12@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C12@l(r6) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lfdx f0, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r3, r1, 60 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: xscvdpsxws f0, f0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: stfiwx f0, 0, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: lwz r3, 60(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testDouble2: +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -64(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C14(r2) # target-flags(ppc-tlsld) @internal_tlv_double +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfdx f0, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: xscvdpsxws f0, f0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r3, r1, 52 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stfiwx f0, 0, r3 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 52(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: clrldi r3, r3, 32 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testDouble2: +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -80(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 96(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C14@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C14@l(r4) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfdx f0, r3, r4 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: xscvdpsxws f0, f0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r1, 68 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stfiwx f0, 0, r3 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 68(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: clrldi r3, r3, 32 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 80 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; DEFAULT-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr entry: %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @internal_tlv_double) %value = load double, ptr %tlv_addr, align 8 diff --git a/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt-IRattribute.ll b/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt-IRattribute.ll index dc78ae8436df..fc49e9416803 100644 --- a/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt-IRattribute.ll +++ b/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt-IRattribute.ll @@ -8,23 +8,32 @@ ; RUN: -data-sections=false < %s 2>&1 | \ ; RUN: FileCheck %s --check-prefix=CHECK-UNSUPPORTED-NO-DATASEC -define dso_local signext i32 @testWithIRAttr() #0 { +define dso_local signext i32 @testWithIRAttrLocalExec() #0 { entry: ret i32 0 } -; Check that the aix-small-local-exec-tls attribute is not supported on Linux and AIX (32-bit). -; CHECK-NOT-SUPPORTED: The aix-small-local-exec-tls attribute is only supported on AIX in 64-bit mode. -; Check that the aix-small-local-exec-tls attribute is only supported when +define dso_local signext i32 @testWithIRAttrLocalDynamic() #1 { +entry: + ret i32 0 +} + +; Check that the aix-small-local-[exec|dynamic]-tls attribute is not supported on Linux and AIX (32-bit). +; CHECK-NOT-SUPPORTED: The aix-small-local-[exec|dynamic]-tls attribute is only supported on AIX in 64-bit mode. + +; Check that the aix-small-local-[exec|dynamic]-tls attribute is only supported when ; data sections are enabled. -; CHECK-UNSUPPORTED-NO-DATASEC: The aix-small-local-exec-tls attribute can only be specified with -data-sections. +; CHECK-UNSUPPORTED-NO-DATASEC: The aix-small-local-[exec|dynamic]-tls attribute can only be specified with -data-sections. ; Make sure that the test was actually compiled successfully after using the -; aix-small-local-exec-tls attribute. -; CHECK-LABEL: testWithIRAttr: +; aix-small-local-[exec|dynamic]-tls attribute. +; CHECK-LABEL: testWithIRAttrLocalExec: +; CHECK: li r3, 0 +; CHECK-NEXT: blr +; CHECK-LABEL: testWithIRAttrLocalDynamic: ; CHECK: li r3, 0 ; CHECK-NEXT: blr - attributes #0 = { "target-features"="+aix-small-local-exec-tls" } +attributes #1 = { "target-features"="+aix-small-local-dynamic-tls" } diff --git a/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt.ll b/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt.ll index 5104b7c6c839..25bab5b5efcd 100644 --- a/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt.ll +++ b/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt.ll @@ -6,17 +6,25 @@ ; RUN: not llc -mtriple powerpc64le-unknown-linux-gnu -mattr=+aix-small-local-exec-tls \ ; RUN: -ppc-asm-full-reg-names < %s 2>&1 | \ ; RUN: FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -mattr=+aix-small-local-dynamic-tls \ +; RUN: -ppc-asm-full-reg-names < %s | FileCheck %s +; RUN: not llc -mtriple powerpc-ibm-aix-xcoff -mattr=+aix-small-local-dynamic-tls \ +; RUN: -ppc-asm-full-reg-names < %s 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED +; RUN: not llc -mtriple powerpc64le-unknown-linux-gnu -mattr=+aix-small-local-dynamic-tls \ +; RUN: -ppc-asm-full-reg-names < %s 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED define dso_local signext i32 @testNoIRAttr() { entry: ret i32 0 } -; Check that the aix-small-local-exec-tls attribute is not supported on Linux and AIX (32-bit). -; CHECK-NOT-SUPPORTED: The aix-small-local-exec-tls attribute is only supported on AIX in 64-bit mode. +; Check that the aix-small-local-[exec|dynamic]-tls attribute is not supported on Linux and AIX (32-bit). +; CHECK-NOT-SUPPORTED: The aix-small-local-[exec|dynamic]-tls attribute is only supported on AIX in 64-bit mode. ; Make sure that the test was actually compiled successfully after using the -; aix-small-local-exec-tls attribute. +; aix-small-local-[exec|dynamic]-tls attribute. ; CHECK-LABEL: testNoIRAttr: ; CHECK: li r3, 0 ; CHECK-NEXT: blr -- GitLab From 86df55efa1242e308535679cf05c2793ff38f3d9 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Fri, 12 Apr 2024 09:21:17 +0800 Subject: [PATCH 021/464] [X86][BF16] Promote vector ADD/SUB/MUL/DIV to f32 (#87858) --- llvm/lib/Target/X86/X86ISelLowering.cpp | 18 +- llvm/test/CodeGen/X86/bfloat.ll | 286 ++---------------------- 2 files changed, 31 insertions(+), 273 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index f274da6f6f77..b7cb4b7dafeb 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -1978,10 +1978,8 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::STRICT_FP_ROUND, MVT::v16f16, Custom); setOperationAction(ISD::FP_EXTEND, MVT::v16f32, Custom); setOperationAction(ISD::STRICT_FP_EXTEND, MVT::v16f32, Custom); - for (unsigned Opc : {ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FDIV}) { - setOperationPromotedToType(Opc, MVT::v16f16, MVT::v16f32); + for (unsigned Opc : {ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FDIV}) setOperationPromotedToType(Opc, MVT::v32f16, MVT::v32f32); - } for (auto VT : { MVT::v16i32, MVT::v8i64, MVT::v16f32, MVT::v8f64 }) { setOperationAction(ISD::MLOAD, VT, Legal); @@ -2296,15 +2294,15 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::bf16, Custom); for (auto VT : {MVT::v8bf16, MVT::v16bf16}) { setF16Action(VT, Expand); - setOperationAction(ISD::FADD, VT, Expand); - setOperationAction(ISD::FSUB, VT, Expand); - setOperationAction(ISD::FMUL, VT, Expand); - setOperationAction(ISD::FDIV, VT, Expand); setOperationAction(ISD::BUILD_VECTOR, VT, Custom); setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom); setOperationAction(ISD::INSERT_SUBVECTOR, VT, Legal); setOperationAction(ISD::CONCAT_VECTORS, VT, Custom); } + for (unsigned Opc : {ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FDIV}) { + setOperationPromotedToType(Opc, MVT::v8bf16, MVT::v8f32); + setOperationPromotedToType(Opc, MVT::v16bf16, MVT::v16f32); + } setOperationAction(ISD::FP_ROUND, MVT::v8bf16, Custom); addLegalFPImmediate(APFloat::getZero(APFloat::BFloat())); } @@ -2312,10 +2310,8 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, if (!Subtarget.useSoftFloat() && Subtarget.hasBF16()) { addRegisterClass(MVT::v32bf16, &X86::VR512RegClass); setF16Action(MVT::v32bf16, Expand); - setOperationAction(ISD::FADD, MVT::v32bf16, Expand); - setOperationAction(ISD::FSUB, MVT::v32bf16, Expand); - setOperationAction(ISD::FMUL, MVT::v32bf16, Expand); - setOperationAction(ISD::FDIV, MVT::v32bf16, Expand); + for (unsigned Opc : {ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FDIV}) + setOperationPromotedToType(Opc, MVT::v32bf16, MVT::v32f32); setOperationAction(ISD::BUILD_VECTOR, MVT::v32bf16, Custom); setOperationAction(ISD::FP_ROUND, MVT::v16bf16, Custom); setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v32bf16, Custom); diff --git a/llvm/test/CodeGen/X86/bfloat.ll b/llvm/test/CodeGen/X86/bfloat.ll index 6e3020d628ed..8a2109a1c78d 100644 --- a/llvm/test/CodeGen/X86/bfloat.ll +++ b/llvm/test/CodeGen/X86/bfloat.ll @@ -525,101 +525,13 @@ define bfloat @fold_ext_trunc2(bfloat %a) nounwind { define <8 x bfloat> @addv(<8 x bfloat> %a, <8 x bfloat> %b) nounwind { ; X86-LABEL: addv: ; X86: # %bb.0: -; X86-NEXT: pushl %ebp -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %esi -; X86-NEXT: vmovw %xmm1, %eax -; X86-NEXT: shll $16, %eax -; X86-NEXT: vmovd %eax, %xmm2 -; X86-NEXT: vmovw %xmm0, %eax -; X86-NEXT: shll $16, %eax -; X86-NEXT: vmovd %eax, %xmm3 -; X86-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; X86-NEXT: vcvtneps2bf16 %xmm2, %xmm2 -; X86-NEXT: vmovw %xmm2, %ecx -; X86-NEXT: vpextrw $1, %xmm1, %eax -; X86-NEXT: shll $16, %eax -; X86-NEXT: vmovd %eax, %xmm2 -; X86-NEXT: vpextrw $1, %xmm0, %eax -; X86-NEXT: shll $16, %eax -; X86-NEXT: vmovd %eax, %xmm3 -; X86-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; X86-NEXT: vcvtneps2bf16 %xmm2, %xmm2 -; X86-NEXT: vmovw %xmm2, %eax -; X86-NEXT: vpextrw $2, %xmm1, %edx -; X86-NEXT: shll $16, %edx -; X86-NEXT: vmovd %edx, %xmm2 -; X86-NEXT: vpextrw $2, %xmm0, %edx -; X86-NEXT: shll $16, %edx -; X86-NEXT: vmovd %edx, %xmm3 -; X86-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; X86-NEXT: vcvtneps2bf16 %xmm2, %xmm2 -; X86-NEXT: vmovw %xmm2, %edx -; X86-NEXT: vpextrw $3, %xmm1, %esi -; X86-NEXT: shll $16, %esi -; X86-NEXT: vmovd %esi, %xmm2 -; X86-NEXT: vpextrw $3, %xmm0, %esi -; X86-NEXT: shll $16, %esi -; X86-NEXT: vmovd %esi, %xmm3 -; X86-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; X86-NEXT: vcvtneps2bf16 %xmm2, %xmm2 -; X86-NEXT: vmovw %xmm2, %esi -; X86-NEXT: vpextrw $4, %xmm1, %edi -; X86-NEXT: shll $16, %edi -; X86-NEXT: vmovd %edi, %xmm2 -; X86-NEXT: vpextrw $4, %xmm0, %edi -; X86-NEXT: shll $16, %edi -; X86-NEXT: vmovd %edi, %xmm3 -; X86-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; X86-NEXT: vcvtneps2bf16 %xmm2, %xmm2 -; X86-NEXT: vmovw %xmm2, %ebx -; X86-NEXT: vpextrw $5, %xmm1, %edi -; X86-NEXT: shll $16, %edi -; X86-NEXT: vmovd %edi, %xmm2 -; X86-NEXT: vpextrw $5, %xmm0, %edi -; X86-NEXT: shll $16, %edi -; X86-NEXT: vmovd %edi, %xmm3 -; X86-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; X86-NEXT: vcvtneps2bf16 %xmm2, %xmm2 -; X86-NEXT: vmovw %xmm2, %edi -; X86-NEXT: vpextrw $6, %xmm1, %ebp -; X86-NEXT: shll $16, %ebp -; X86-NEXT: vmovd %ebp, %xmm2 -; X86-NEXT: vpextrw $6, %xmm0, %ebp -; X86-NEXT: shll $16, %ebp -; X86-NEXT: vmovd %ebp, %xmm3 -; X86-NEXT: vaddss %xmm2, %xmm3, %xmm3 -; X86-NEXT: vmovw %ecx, %xmm2 -; X86-NEXT: vcvtneps2bf16 %xmm3, %xmm3 -; X86-NEXT: vmovw %xmm3, %ecx -; X86-NEXT: vmovw %ebx, %xmm3 -; X86-NEXT: vpextrw $7, %xmm1, %ebx -; X86-NEXT: shll $16, %ebx -; X86-NEXT: vmovd %ebx, %xmm1 -; X86-NEXT: vpextrw $7, %xmm0, %ebx -; X86-NEXT: shll $16, %ebx -; X86-NEXT: vmovd %ebx, %xmm0 -; X86-NEXT: vaddss %xmm1, %xmm0, %xmm0 -; X86-NEXT: vmovw %ecx, %xmm1 -; X86-NEXT: vcvtneps2bf16 %xmm0, %xmm0 -; X86-NEXT: vmovw %xmm0, %ecx -; X86-NEXT: vmovw %ecx, %xmm0 -; X86-NEXT: vpunpcklwd {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3] -; X86-NEXT: vmovw %edi, %xmm1 -; X86-NEXT: vpunpcklwd {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3] -; X86-NEXT: vmovw %edx, %xmm3 -; X86-NEXT: vpunpckldq {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] -; X86-NEXT: vmovw %esi, %xmm1 -; X86-NEXT: vpunpcklwd {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3] -; X86-NEXT: vmovw %eax, %xmm3 -; X86-NEXT: vpunpcklwd {{.*#+}} xmm2 = xmm2[0],xmm3[0],xmm2[1],xmm3[1],xmm2[2],xmm3[2],xmm2[3],xmm3[3] -; X86-NEXT: vpunpckldq {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[1],xmm1[1] -; X86-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; X86-NEXT: popl %esi -; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx -; X86-NEXT: popl %ebp +; X86-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; X86-NEXT: vpslld $16, %ymm1, %ymm1 +; X86-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; X86-NEXT: vpslld $16, %ymm0, %ymm0 +; X86-NEXT: vaddps %ymm1, %ymm0, %ymm0 +; X86-NEXT: vcvtneps2bf16 %ymm0, %xmm0 +; X86-NEXT: vzeroupper ; X86-NEXT: retl ; ; SSE2-LABEL: addv: @@ -756,176 +668,26 @@ define <8 x bfloat> @addv(<8 x bfloat> %a, <8 x bfloat> %b) nounwind { ; SSE2-NEXT: popq %rbp ; SSE2-NEXT: retq ; -; FP16-LABEL: addv: -; FP16: # %bb.0: -; FP16-NEXT: vmovw %xmm1, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm2 -; FP16-NEXT: vmovw %xmm0, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm3 -; FP16-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; FP16-NEXT: vcvtneps2bf16 %xmm2, %xmm2 -; FP16-NEXT: vmovw %xmm2, %eax -; FP16-NEXT: vmovw %eax, %xmm2 -; FP16-NEXT: vpextrw $1, %xmm1, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm3 -; FP16-NEXT: vpextrw $1, %xmm0, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm4 -; FP16-NEXT: vaddss %xmm3, %xmm4, %xmm3 -; FP16-NEXT: vcvtneps2bf16 %xmm3, %xmm3 -; FP16-NEXT: vmovw %xmm3, %eax -; FP16-NEXT: vmovw %eax, %xmm3 -; FP16-NEXT: vpextrw $2, %xmm1, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm4 -; FP16-NEXT: vpextrw $2, %xmm0, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm5 -; FP16-NEXT: vaddss %xmm4, %xmm5, %xmm4 -; FP16-NEXT: vcvtneps2bf16 %xmm4, %xmm4 -; FP16-NEXT: vmovw %xmm4, %eax -; FP16-NEXT: vmovw %eax, %xmm4 -; FP16-NEXT: vpextrw $3, %xmm1, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm5 -; FP16-NEXT: vpextrw $3, %xmm0, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm6 -; FP16-NEXT: vaddss %xmm5, %xmm6, %xmm5 -; FP16-NEXT: vcvtneps2bf16 %xmm5, %xmm5 -; FP16-NEXT: vmovw %xmm5, %eax -; FP16-NEXT: vmovw %eax, %xmm5 -; FP16-NEXT: vpextrw $4, %xmm1, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm6 -; FP16-NEXT: vpextrw $4, %xmm0, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm7 -; FP16-NEXT: vaddss %xmm6, %xmm7, %xmm6 -; FP16-NEXT: vcvtneps2bf16 %xmm6, %xmm6 -; FP16-NEXT: vmovw %xmm6, %eax -; FP16-NEXT: vmovw %eax, %xmm6 -; FP16-NEXT: vpextrw $5, %xmm1, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm7 -; FP16-NEXT: vpextrw $5, %xmm0, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm8 -; FP16-NEXT: vaddss %xmm7, %xmm8, %xmm7 -; FP16-NEXT: vcvtneps2bf16 %xmm7, %xmm7 -; FP16-NEXT: vmovw %xmm7, %eax -; FP16-NEXT: vmovw %eax, %xmm7 -; FP16-NEXT: vpextrw $6, %xmm1, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm8 -; FP16-NEXT: vpextrw $6, %xmm0, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm9 -; FP16-NEXT: vaddss %xmm8, %xmm9, %xmm8 -; FP16-NEXT: vcvtneps2bf16 %xmm8, %xmm8 -; FP16-NEXT: vmovw %xmm8, %eax -; FP16-NEXT: vmovw %eax, %xmm8 -; FP16-NEXT: vpextrw $7, %xmm1, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm1 -; FP16-NEXT: vpextrw $7, %xmm0, %eax -; FP16-NEXT: shll $16, %eax -; FP16-NEXT: vmovd %eax, %xmm0 -; FP16-NEXT: vaddss %xmm1, %xmm0, %xmm0 -; FP16-NEXT: vcvtneps2bf16 %xmm0, %xmm0 -; FP16-NEXT: vmovw %xmm0, %eax -; FP16-NEXT: vmovw %eax, %xmm0 -; FP16-NEXT: vpunpcklwd {{.*#+}} xmm0 = xmm8[0],xmm0[0],xmm8[1],xmm0[1],xmm8[2],xmm0[2],xmm8[3],xmm0[3] -; FP16-NEXT: vpunpcklwd {{.*#+}} xmm1 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3] -; FP16-NEXT: vpunpckldq {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] -; FP16-NEXT: vpunpcklwd {{.*#+}} xmm1 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3] -; FP16-NEXT: vpunpcklwd {{.*#+}} xmm2 = xmm2[0],xmm3[0],xmm2[1],xmm3[1],xmm2[2],xmm3[2],xmm2[3],xmm3[3] -; FP16-NEXT: vpunpckldq {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[1],xmm1[1] -; FP16-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; FP16-NEXT: retq +; F16-LABEL: addv: +; F16: # %bb.0: +; F16-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; F16-NEXT: vpslld $16, %ymm1, %ymm1 +; F16-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; F16-NEXT: vpslld $16, %ymm0, %ymm0 +; F16-NEXT: vaddps %ymm1, %ymm0, %ymm0 +; F16-NEXT: vcvtneps2bf16 %ymm0, %xmm0 +; F16-NEXT: vzeroupper +; F16-NEXT: retq ; ; AVXNC-LABEL: addv: ; AVXNC: # %bb.0: -; AVXNC-NEXT: vpextrw $7, %xmm1, %eax -; AVXNC-NEXT: shll $16, %eax -; AVXNC-NEXT: vmovd %eax, %xmm2 -; AVXNC-NEXT: vpextrw $7, %xmm0, %eax -; AVXNC-NEXT: shll $16, %eax -; AVXNC-NEXT: vmovd %eax, %xmm3 -; AVXNC-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; AVXNC-NEXT: {vex} vcvtneps2bf16 %xmm2, %xmm2 -; AVXNC-NEXT: vmovd %xmm2, %eax -; AVXNC-NEXT: vpextrw $6, %xmm1, %ecx -; AVXNC-NEXT: shll $16, %ecx -; AVXNC-NEXT: vmovd %ecx, %xmm2 -; AVXNC-NEXT: vpextrw $6, %xmm0, %ecx -; AVXNC-NEXT: shll $16, %ecx -; AVXNC-NEXT: vmovd %ecx, %xmm3 -; AVXNC-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; AVXNC-NEXT: {vex} vcvtneps2bf16 %xmm2, %xmm2 -; AVXNC-NEXT: vmovd %xmm2, %ecx -; AVXNC-NEXT: vpextrw $5, %xmm1, %edx -; AVXNC-NEXT: shll $16, %edx -; AVXNC-NEXT: vmovd %edx, %xmm2 -; AVXNC-NEXT: vpextrw $5, %xmm0, %edx -; AVXNC-NEXT: shll $16, %edx -; AVXNC-NEXT: vmovd %edx, %xmm3 -; AVXNC-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; AVXNC-NEXT: {vex} vcvtneps2bf16 %xmm2, %xmm2 -; AVXNC-NEXT: vmovd %xmm2, %edx -; AVXNC-NEXT: vpextrw $4, %xmm1, %esi -; AVXNC-NEXT: shll $16, %esi -; AVXNC-NEXT: vmovd %esi, %xmm2 -; AVXNC-NEXT: vpextrw $4, %xmm0, %esi -; AVXNC-NEXT: shll $16, %esi -; AVXNC-NEXT: vmovd %esi, %xmm3 -; AVXNC-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; AVXNC-NEXT: {vex} vcvtneps2bf16 %xmm2, %xmm2 -; AVXNC-NEXT: vmovd %xmm2, %esi -; AVXNC-NEXT: vpextrw $3, %xmm1, %edi -; AVXNC-NEXT: shll $16, %edi -; AVXNC-NEXT: vmovd %edi, %xmm2 -; AVXNC-NEXT: vpextrw $3, %xmm0, %edi -; AVXNC-NEXT: shll $16, %edi -; AVXNC-NEXT: vmovd %edi, %xmm3 -; AVXNC-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; AVXNC-NEXT: {vex} vcvtneps2bf16 %xmm2, %xmm2 -; AVXNC-NEXT: vmovd %xmm2, %edi -; AVXNC-NEXT: vpextrw $2, %xmm1, %r8d -; AVXNC-NEXT: shll $16, %r8d -; AVXNC-NEXT: vmovd %r8d, %xmm2 -; AVXNC-NEXT: vpextrw $2, %xmm0, %r8d -; AVXNC-NEXT: shll $16, %r8d -; AVXNC-NEXT: vmovd %r8d, %xmm3 -; AVXNC-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; AVXNC-NEXT: {vex} vcvtneps2bf16 %xmm2, %xmm2 -; AVXNC-NEXT: vmovd %xmm2, %r8d -; AVXNC-NEXT: vpextrw $1, %xmm1, %r9d -; AVXNC-NEXT: shll $16, %r9d -; AVXNC-NEXT: vmovd %r9d, %xmm2 -; AVXNC-NEXT: vpextrw $1, %xmm0, %r9d -; AVXNC-NEXT: shll $16, %r9d -; AVXNC-NEXT: vmovd %r9d, %xmm3 -; AVXNC-NEXT: vaddss %xmm2, %xmm3, %xmm2 -; AVXNC-NEXT: {vex} vcvtneps2bf16 %xmm2, %xmm2 -; AVXNC-NEXT: vmovd %xmm1, %r9d -; AVXNC-NEXT: shll $16, %r9d -; AVXNC-NEXT: vmovd %r9d, %xmm1 -; AVXNC-NEXT: vmovd %xmm0, %r9d -; AVXNC-NEXT: shll $16, %r9d -; AVXNC-NEXT: vmovd %r9d, %xmm0 -; AVXNC-NEXT: vaddss %xmm1, %xmm0, %xmm0 -; AVXNC-NEXT: {vex} vcvtneps2bf16 %xmm0, %xmm0 -; AVXNC-NEXT: vpunpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3] -; AVXNC-NEXT: vpinsrw $2, %r8d, %xmm0, %xmm0 -; AVXNC-NEXT: vpinsrw $3, %edi, %xmm0, %xmm0 -; AVXNC-NEXT: vpinsrw $4, %esi, %xmm0, %xmm0 -; AVXNC-NEXT: vpinsrw $5, %edx, %xmm0, %xmm0 -; AVXNC-NEXT: vpinsrw $6, %ecx, %xmm0, %xmm0 -; AVXNC-NEXT: vpinsrw $7, %eax, %xmm0, %xmm0 +; AVXNC-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVXNC-NEXT: vpslld $16, %ymm1, %ymm1 +; AVXNC-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVXNC-NEXT: vpslld $16, %ymm0, %ymm0 +; AVXNC-NEXT: vaddps %ymm1, %ymm0, %ymm0 +; AVXNC-NEXT: {vex} vcvtneps2bf16 %ymm0, %xmm0 +; AVXNC-NEXT: vzeroupper ; AVXNC-NEXT: retq %add = fadd <8 x bfloat> %a, %b ret <8 x bfloat> %add -- GitLab From 27ce513788e15c95f8c623566fbfca9304bb1844 Mon Sep 17 00:00:00 2001 From: Corbin Robeck Date: Thu, 11 Apr 2024 22:05:01 -0400 Subject: [PATCH 022/464] [AMDGPU] Add Clang builtins for amdgcn s_ttrace intrinsics (#88076) --- clang/include/clang/Basic/BuiltinsAMDGPU.def | 2 ++ .../CodeGenOpenCL/builtins-amdgcn-gfx12.cl | 22 +++++++++++++++++++ llvm/include/llvm/IR/IntrinsicsAMDGPU.td | 3 +++ 3 files changed, 27 insertions(+) diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index c660582cc98e..3e21a2fe2ac6 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -61,6 +61,7 @@ BUILTIN(__builtin_amdgcn_s_waitcnt, "vIi", "n") BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n") BUILTIN(__builtin_amdgcn_s_sendmsghalt, "vIiUi", "n") BUILTIN(__builtin_amdgcn_s_barrier, "v", "n") +BUILTIN(__builtin_amdgcn_s_ttracedata, "vi", "n") BUILTIN(__builtin_amdgcn_wave_barrier, "v", "n") BUILTIN(__builtin_amdgcn_sched_barrier, "vIi", "n") BUILTIN(__builtin_amdgcn_sched_group_barrier, "vIiIiIi", "n") @@ -267,6 +268,7 @@ TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_bf8, "fUiUif", "nc", "dot11-insts") TARGET_BUILTIN(__builtin_amdgcn_permlane16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts") TARGET_BUILTIN(__builtin_amdgcn_permlanex16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts") TARGET_BUILTIN(__builtin_amdgcn_mov_dpp8, "UiUiIUi", "nc", "gfx10-insts") +TARGET_BUILTIN(__builtin_amdgcn_s_ttracedata_imm, "vIs", "n", "gfx10-insts") //===----------------------------------------------------------------------===// // Raytracing builtins. diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx12.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx12.cl index ebd367bba0cd..26c0ee483062 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx12.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx12.cl @@ -235,3 +235,25 @@ unsigned test_s_get_barrier_state(int a) unsigned State = __builtin_amdgcn_s_get_barrier_state(a); return State; } + +// CHECK-LABEL: @test_s_ttracedata( +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.amdgcn.s.ttracedata(i32 1) +// CHECK-NEXT: ret void +// +void test_s_ttracedata() +{ + __builtin_amdgcn_s_ttracedata(1); +} + +// CHECK-LABEL: @test_s_ttracedata_imm( +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.amdgcn.s.ttracedata.imm(i16 1) +// CHECK-NEXT: ret void +// +void test_s_ttracedata_imm() +{ + __builtin_amdgcn_s_ttracedata_imm(1); +} + + diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td index 6bbc13f1de86..ee9a5d7a3439 100644 --- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td @@ -1887,9 +1887,12 @@ def int_amdgcn_s_setprio : IntrHasSideEffects]>; def int_amdgcn_s_ttracedata : + ClangBuiltin<"__builtin_amdgcn_s_ttracedata">, DefaultAttrsIntrinsic<[], [llvm_i32_ty], [IntrNoMem, IntrHasSideEffects]>; + def int_amdgcn_s_ttracedata_imm : + ClangBuiltin<"__builtin_amdgcn_s_ttracedata_imm">, DefaultAttrsIntrinsic<[], [llvm_i16_ty], [IntrNoMem, IntrHasSideEffects, ImmArg>]>; -- GitLab From 6b6f272f355a2cbc753e9057dd7aefb1a74a0409 Mon Sep 17 00:00:00 2001 From: Feng Zou Date: Fri, 12 Apr 2024 10:13:56 +0800 Subject: [PATCH 023/464] [DAGCombiner] Require same type of splat & element for build_vector (#88284) Only allow to change build_vector to concat_vector when the splat type and vector element type is same. It's to fix assertion of failing to bitcast types of different sizes. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 9 ++++--- llvm/test/CodeGen/X86/buildvec-bitcast.ll | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 llvm/test/CodeGen/X86/buildvec-bitcast.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 95c1cde0b934..24f50b87c4cf 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -23428,7 +23428,10 @@ SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *N) { // If X is a build_vector itself, the concat can become a larger build_vector. // TODO: Maybe this is useful for non-splat too? if (!LegalOperations) { - if (SDValue Splat = cast(N)->getSplatValue()) { + SDValue Splat = cast(N)->getSplatValue(); + // Only change build_vector to a concat_vector if the splat value type is + // same as the vector element type. + if (Splat && Splat.getValueType() == VT.getVectorElementType()) { Splat = peekThroughBitcasts(Splat); EVT SrcVT = Splat.getValueType(); if (SrcVT.isVector()) { @@ -23437,8 +23440,8 @@ SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *N) { SrcVT.getVectorElementType(), NumElts); if (!LegalTypes || TLI.isTypeLegal(NewVT)) { SmallVector Ops(N->getNumOperands(), Splat); - SDValue Concat = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), - NewVT, Ops); + SDValue Concat = + DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), NewVT, Ops); return DAG.getBitcast(VT, Concat); } } diff --git a/llvm/test/CodeGen/X86/buildvec-bitcast.ll b/llvm/test/CodeGen/X86/buildvec-bitcast.ll new file mode 100644 index 000000000000..980fd2dee091 --- /dev/null +++ b/llvm/test/CodeGen/X86/buildvec-bitcast.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=x86_64 -mattr=avx512bw | FileCheck %s + +; Verify that the DAGCombiner doesn't change build_vector to concat_vectors if +; the vector element type is different than splat type. The example here: +; v8i1 = build_vector (i8 (bitcast (v8i1 X))), ..., (i8 (bitcast (v8i1 X)))) + +define <8 x i1> @foo(<8 x i1> %mask.i1) { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; CHECK-NEXT: retq +entry: + %0 = and <8 x i1> %mask.i1, + %1 = bitcast <8 x i1> %0 to i8 + %2 = icmp ne i8 %1, 0 + %insert54 = insertelement <8 x i1> zeroinitializer, i1 %2, i64 0 + %splat55 = shufflevector <8 x i1> %insert54, <8 x i1> zeroinitializer, <8 x i32> zeroinitializer + %3 = and <8 x i1> %0, %splat55 + br label %end + +end: ; preds = %entry + %4 = select <8 x i1> %3, <8 x i1> zeroinitializer, <8 x i1> zeroinitializer + ret <8 x i1> %4 +} -- GitLab From 3a2817749eb8a2210320aa551fa20a5f9c8c32e3 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Thu, 11 Apr 2024 19:47:58 -0700 Subject: [PATCH 024/464] [llvm-exegesis] Let ArrayRef infer the array size (NFC) (#88241) --- llvm/tools/llvm-exegesis/lib/X86/Target.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp index 31bec2545926..dbb2bf409316 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp @@ -769,11 +769,9 @@ private: ArrayRef getUnavailableRegisters() const override { if (DisableUpperSSERegisters) - return ArrayRef(kUnavailableRegistersSSE, - sizeof(kUnavailableRegistersSSE) / - sizeof(kUnavailableRegistersSSE[0])); + return ArrayRef(kUnavailableRegistersSSE); - return ArrayRef(kUnavailableRegisters, std::size(kUnavailableRegisters)); + return ArrayRef(kUnavailableRegisters); } bool allowAsBackToBack(const Instruction &Instr) const override { -- GitLab From 334e07f18e6f2fbc84579f7cac3cdd29d0d7cce0 Mon Sep 17 00:00:00 2001 From: Piyou Chen Date: Fri, 12 Apr 2024 10:59:06 +0800 Subject: [PATCH 025/464] [RISCV] Disallow target attribute use in multiversioning (#85899) For RISC-V target only `target_clones` and `target_version` can enable function multiversion(FMV). This patch make target attribute trigger redefinition instead of emit FMV. Here is spec https://github.com/riscv-non-isa/riscv-c-api-doc/blob/master/riscv-c-api.md#__attribute__targetattr-string --- clang/lib/Sema/SemaDecl.cpp | 8 +++++++- clang/test/Sema/attr-target-riscv.c | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 clang/test/Sema/attr-target-riscv.c diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a4699d6ba2c7..691e170cd051 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11911,8 +11911,14 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, return false; } + const llvm::Triple &T = S.getASTContext().getTargetInfo().getTriple(); + // Target attribute on AArch64 is not used for multiversioning - if (NewTA && S.getASTContext().getTargetInfo().getTriple().isAArch64()) + if (NewTA && T.isAArch64()) + return false; + + // Target attribute on RISCV is not used for multiversioning + if (NewTA && T.isRISCV()) return false; if (!OldDecl || !OldDecl->getAsFunction() || diff --git a/clang/test/Sema/attr-target-riscv.c b/clang/test/Sema/attr-target-riscv.c new file mode 100644 index 000000000000..ed4e2915d6c6 --- /dev/null +++ b/clang/test/Sema/attr-target-riscv.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple riscv64-linux-gnu -target-feature +i -fsyntax-only -verify -std=c2x %s + +//expected-note@+1 {{previous definition is here}} +int __attribute__((target("arch=rv64g"))) foo(void) { return 0; } +//expected-error@+1 {{redefinition of 'foo'}} +int __attribute__((target("arch=rv64gc"))) foo(void) { return 0; } -- GitLab From c24efffabbf96c7a138439bb8e219850c4d78887 Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Thu, 11 Apr 2024 20:01:55 -0700 Subject: [PATCH 026/464] [InstallAPI] Handle zippered frameworks (#88205) A zippered framework is a single framework that can be loaded in both macOS and macatalyst processes. Broadly to InstallAPI, it means the same interface can represent two separate platforms. A dylib's symbol table does not distinguish between macOS/macCatalyst. `InstallAPI` provides the ability for the tbd file to distinct symbols between them. The verifier handles this special logic by tracking all unavailable and obsoleted APIs in this context and checking against those when determining dylib symbols with no matching declaration. * If there exists an available decl for either platform, do not warn. * If there is no available decl, emit a diagnostic and print the source location for both decls. --- .../clang/Basic/DiagnosticInstallAPIKinds.td | 4 + .../include/clang/InstallAPI/DylibVerifier.h | 32 +- clang/lib/InstallAPI/DylibVerifier.cpp | 98 ++- .../Inputs/MacOSX13.0.sdk/SDKSettings.json | 19 + .../test/InstallAPI/diagnostics-zippered.test | 765 ++++++++++++++++++ .../InstallAPI/driver-invalid-options.test | 7 + clang/tools/clang-installapi/Options.cpp | 52 +- clang/tools/clang-installapi/Options.h | 3 + 8 files changed, 964 insertions(+), 16 deletions(-) create mode 100644 clang/test/InstallAPI/Inputs/MacOSX13.0.sdk/SDKSettings.json create mode 100644 clang/test/InstallAPI/diagnostics-zippered.test diff --git a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td index 0a477da7186b..396bff0146a3 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -20,6 +20,10 @@ def warn_no_such_excluded_header_file : Warning<"no such excluded %select{public def warn_glob_did_not_match: Warning<"glob '%0' did not match any header file">, InGroup; def err_no_such_umbrella_header_file : Error<"%select{public|private|project}1 umbrella header file not found in input: '%0'">; def err_cannot_find_reexport : Error<"cannot find re-exported %select{framework|library}0: '%1'">; +def err_no_matching_target : Error<"no matching target found for target variant '%0'">; +def err_unsupported_vendor : Error<"vendor '%0' is not supported: '%1'">; +def err_unsupported_environment : Error<"environment '%0' is not supported: '%1'">; +def err_unsupported_os : Error<"os '%0' is not supported: '%1'">; } // end of command line category. let CategoryName = "Verification" in { diff --git a/clang/include/clang/InstallAPI/DylibVerifier.h b/clang/include/clang/InstallAPI/DylibVerifier.h index a3df25f10de4..31de212fc423 100644 --- a/clang/include/clang/InstallAPI/DylibVerifier.h +++ b/clang/include/clang/InstallAPI/DylibVerifier.h @@ -28,6 +28,16 @@ enum class VerificationMode { using LibAttrs = llvm::StringMap; using ReexportedInterfaces = llvm::SmallVector; +// Pointers to information about a zippered declaration used for +// querying and reporting violations against different +// declarations that all map to the same symbol. +struct ZipperedDeclSource { + const FrontendAttrs *FA; + clang::SourceManager *SrcMgr; + Target T; +}; +using ZipperedDeclSources = std::vector; + /// Service responsible to tracking state of verification across the /// lifetime of InstallAPI. /// As declarations are collected during AST traversal, they are @@ -68,10 +78,10 @@ public: DylibVerifier() = default; DylibVerifier(llvm::MachO::Records &&Dylib, ReexportedInterfaces &&Reexports, - DiagnosticsEngine *Diag, VerificationMode Mode, bool Demangle, - StringRef DSYMPath) + DiagnosticsEngine *Diag, VerificationMode Mode, bool Zippered, + bool Demangle, StringRef DSYMPath) : Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), Mode(Mode), - Demangle(Demangle), DSYMPath(DSYMPath), + Zippered(Zippered), Demangle(Demangle), DSYMPath(DSYMPath), Exports(std::make_unique()), Ctx(VerifierContext{Diag}) {} Result verify(GlobalRecord *R, const FrontendAttrs *FA); @@ -118,6 +128,15 @@ private: /// symbols should be omitted from the text-api file. bool shouldIgnoreReexport(const Record *R, SymbolContext &SymCtx) const; + // Ignore and omit unavailable symbols in zippered libraries. + bool shouldIgnoreZipperedAvailability(const Record *R, SymbolContext &SymCtx); + + // Check if an internal declaration in zippered library has an + // external declaration for a different platform. This results + // in the symbol being in a "seperate" platform slice. + bool shouldIgnoreInternalZipperedSymbol(const Record *R, + const SymbolContext &SymCtx) const; + /// Compare the visibility declarations to the linkage of symbol found in /// dylib. Result compareVisibility(const Record *R, SymbolContext &SymCtx, @@ -173,6 +192,9 @@ private: // Controls what class of violations to report. VerificationMode Mode = VerificationMode::Invalid; + // Library is zippered. + bool Zippered = false; + // Attempt to demangle when reporting violations. bool Demangle = false; @@ -182,6 +204,10 @@ private: // Valid symbols in final text file. std::unique_ptr Exports = std::make_unique(); + // Unavailable or obsoleted declarations for a zippered library. + // These are cross referenced against symbols in the dylib. + llvm::StringMap DeferredZipperedSymbols; + // Track current state of verification while traversing AST. VerifierContext Ctx; diff --git a/clang/lib/InstallAPI/DylibVerifier.cpp b/clang/lib/InstallAPI/DylibVerifier.cpp index 4fa2d4e9292c..84d9b5892e88 100644 --- a/clang/lib/InstallAPI/DylibVerifier.cpp +++ b/clang/lib/InstallAPI/DylibVerifier.cpp @@ -176,7 +176,13 @@ void DylibVerifier::addSymbol(const Record *R, SymbolContext &SymCtx, bool DylibVerifier::shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx, const Record *DR) { - return SymCtx.FA->Avail.isObsoleted(); + if (!SymCtx.FA->Avail.isObsoleted()) + return false; + + if (Zippered) + DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back(ZipperedDeclSource{ + SymCtx.FA, &Ctx.Diag->getSourceManager(), Ctx.Target}); + return true; } bool DylibVerifier::shouldIgnoreReexport(const Record *R, @@ -195,6 +201,28 @@ bool DylibVerifier::shouldIgnoreReexport(const Record *R, return false; } +bool DylibVerifier::shouldIgnoreInternalZipperedSymbol( + const Record *R, const SymbolContext &SymCtx) const { + if (!Zippered) + return false; + + return Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName, + SymCtx.ObjCIFKind) != nullptr; +} + +bool DylibVerifier::shouldIgnoreZipperedAvailability(const Record *R, + SymbolContext &SymCtx) { + if (!(Zippered && SymCtx.FA->Avail.isUnavailable())) + return false; + + // Collect source location incase there is an exported symbol to diagnose + // during `verifyRemainingSymbols`. + DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back( + ZipperedDeclSource{SymCtx.FA, SourceManagers.back().get(), Ctx.Target}); + + return true; +} + bool DylibVerifier::compareObjCInterfaceSymbols(const Record *R, SymbolContext &SymCtx, const ObjCInterfaceRecord *DR) { @@ -294,6 +322,9 @@ DylibVerifier::Result DylibVerifier::compareVisibility(const Record *R, if (shouldIgnorePrivateExternAttr(SymCtx.FA->D)) return Result::Ignore; + if (shouldIgnoreInternalZipperedSymbol(R, SymCtx)) + return Result::Ignore; + unsigned ID; Result Outcome; if (Mode == VerificationMode::ErrorsAndWarnings) { @@ -321,6 +352,9 @@ DylibVerifier::Result DylibVerifier::compareAvailability(const Record *R, if (!SymCtx.FA->Avail.isUnavailable()) return Result::Valid; + if (shouldIgnoreZipperedAvailability(R, SymCtx)) + return Result::Ignore; + const bool IsDeclAvailable = SymCtx.FA->Avail.isUnavailable(); switch (Mode) { @@ -588,13 +622,58 @@ void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) { } } + const bool IsLinkerSymbol = SymbolName.starts_with("$ld$"); + + if (R.isVerified()) { + // Check for unavailable symbols. + // This should only occur in the zippered case where we ignored + // availability until all headers have been parsed. + auto It = DeferredZipperedSymbols.find(SymCtx.SymbolName); + if (It == DeferredZipperedSymbols.end()) { + updateState(Result::Valid); + return; + } + + ZipperedDeclSources Locs; + for (const ZipperedDeclSource &ZSource : It->second) { + if (ZSource.FA->Avail.isObsoleted()) { + updateState(Result::Ignore); + return; + } + if (ZSource.T.Arch != Ctx.Target.Arch) + continue; + Locs.emplace_back(ZSource); + } + assert(Locs.size() == 2 && "Expected two decls for zippered symbol"); + + // Print violating declarations per platform. + for (const ZipperedDeclSource &ZSource : Locs) { + unsigned DiagID = 0; + if (Mode == VerificationMode::Pedantic || IsLinkerSymbol) { + updateState(Result::Invalid); + DiagID = diag::err_header_availability_mismatch; + } else if (Mode == VerificationMode::ErrorsAndWarnings) { + updateState(Result::Ignore); + DiagID = diag::warn_header_availability_mismatch; + } else { + updateState(Result::Ignore); + return; + } + // Bypass emitDiag banner and print the target everytime. + Ctx.Diag->setSourceManager(ZSource.SrcMgr); + Ctx.Diag->Report(diag::warn_target) << getTargetTripleName(ZSource.T); + Ctx.Diag->Report(ZSource.FA->Loc, DiagID) + << getAnnotatedName(&R, SymCtx) << ZSource.FA->Avail.isUnavailable() + << ZSource.FA->Avail.isUnavailable(); + } + return; + } + if (shouldIgnoreCpp(SymbolName, R.isWeakDefined())) { updateState(Result::Valid); return; } - const bool IsLinkerSymbol = SymbolName.starts_with("$ld$"); - // All checks at this point classify as some kind of violation. // The different verification modes dictate whether they are reported to the // user. @@ -647,8 +726,6 @@ void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) { } void DylibVerifier::visitGlobal(const GlobalRecord &R) { - if (R.isVerified()) - return; SymbolContext SymCtx; SimpleSymbol Sym = parseSymbol(R.getName()); SymCtx.SymbolName = Sym.Name; @@ -658,8 +735,6 @@ void DylibVerifier::visitGlobal(const GlobalRecord &R) { void DylibVerifier::visitObjCIVar(const ObjCIVarRecord &R, const StringRef Super) { - if (R.isVerified()) - return; SymbolContext SymCtx; SymCtx.SymbolName = ObjCIVarRecord::createScopedName(Super, R.getName()); SymCtx.Kind = EncodeKind::ObjectiveCInstanceVariable; @@ -679,8 +754,6 @@ void DylibVerifier::accumulateSrcLocForDylibSymbols() { } void DylibVerifier::visitObjCInterface(const ObjCInterfaceRecord &R) { - if (R.isVerified()) - return; SymbolContext SymCtx; SymCtx.SymbolName = R.getName(); SymCtx.ObjCIFKind = assignObjCIFSymbolKind(&R); @@ -713,9 +786,12 @@ DylibVerifier::Result DylibVerifier::verifyRemainingSymbols() { DWARFContext DWARFInfo; DWARFCtx = &DWARFInfo; - Ctx.DiscoveredFirstError = false; - Ctx.PrintArch = true; + Ctx.Target = Target(Architecture::AK_unknown, PlatformType::PLATFORM_UNKNOWN); for (std::shared_ptr Slice : Dylib) { + if (Ctx.Target.Arch == Slice->getTarget().Arch) + continue; + Ctx.DiscoveredFirstError = false; + Ctx.PrintArch = true; Ctx.Target = Slice->getTarget(); Ctx.DylibSlice = Slice.get(); Slice->visit(*this); diff --git a/clang/test/InstallAPI/Inputs/MacOSX13.0.sdk/SDKSettings.json b/clang/test/InstallAPI/Inputs/MacOSX13.0.sdk/SDKSettings.json new file mode 100644 index 000000000000..258d8288fc6b --- /dev/null +++ b/clang/test/InstallAPI/Inputs/MacOSX13.0.sdk/SDKSettings.json @@ -0,0 +1,19 @@ +{ + "DefaultVariant": "macos", "DisplayName": "macOS 13", + "Version": "13.0", + "MaximumDeploymentTarget": "13.0.99", + "PropertyConditionFallbackNames": [], "VersionMap": { + "iOSMac_macOS": { + "16.1": "13.0", + "15.0": "12.0", + "13.1": "10.15", + "14.0": "11.0" + }, + "macOS_iOSMac": { + "13.0": "16.1", + "12.0": "15.0", + "11.0": "14.0", + "10.15": "13.1" + } + } +} diff --git a/clang/test/InstallAPI/diagnostics-zippered.test b/clang/test/InstallAPI/diagnostics-zippered.test new file mode 100644 index 000000000000..59fd0bb673a3 --- /dev/null +++ b/clang/test/InstallAPI/diagnostics-zippered.test @@ -0,0 +1,765 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: cp -r %S/Inputs/Foundation/Foundation.framework %t/System/Library/Frameworks/ +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: yaml2obj %t/Mismatch.yaml -o %t/System/Library/Frameworks/Mismatch.framework/Mismatch + +; RUN: not clang-installapi --target=arm64-apple-macos13 \ +; RUN: --target=x86_64-apple-macos13 -darwin-target-variant x86_64-apple-ios16.0-macabi \ +; RUN: -darwin-target-variant arm64-apple-ios16.0-macabi \ +; RUN: -F %t/System/Library/Frameworks -isysroot %S/Inputs/MacOSX13.0.sdk \ +; RUN: -install_name /System/Library/Frameworks/Mismatch.framework/Versions/A/Mismatch \ +; RUN: -current_version 1 -compatibility_version 1 %t/inputs.json -o %t/Mismatch.tbd \ +; RUN: --verify-against=%t/System/Library/Frameworks/Mismatch.framework/Mismatch \ +; RUN: --verify-mode=Pedantic 2>&1 | FileCheck %s + +; CHECK: warning: violations found for x86_64-apple-macos13 +; CHECK: error: declaration has external linkage, but dynamic library doesn't have symbol 'foo_arch_x86' +; CHECK-NEXT: extern int foo_arch_x86(); + +; CHECK: error: symbol exported in dynamic library, but marked hidden in declaration 'baz' +; CHECK-NEXT: int baz() __attribute__((visibility("hidden"))); + +; CHECK-NOT: inlinedFunc + +; CHECK: error: declaration has external linkage, but symbol has internal linkage in dynamic library 'bar' +; CHECK-NEXT: extern int bar(); + +; CHECK: error: declaration has external linkage, but dynamic library doesn't have symbol 'NSFoo' +; CHECK-NEXT: @interface NSFoo + +; CHECK: error: declaration has external linkage, but dynamic library doesn't have symbol 'NSFoo.nsint' +; CHECK-NEXT: int nsint; + +; CHECK: error: declaration has external linkage, but dynamic library doesn't have symbol 'NSFooExcept' +; CHECK-NEXT: @interface NSFooExcept + +; CHECK: warning: violations found for arm64-apple-macos13 +; CHECK: error: declaration has external linkage, but dynamic library doesn't have symbol 'foo_arch_arm' +; CHECK-NEXT: extern int foo_arch_arm(); + +; CHECK: warning: violations found for x86_64 +; CHECK-NEXT: error: no declaration found for exported symbol '_fooBar' in dynamic library + +; CHECK: warning: violations found for arm64 +; CHECK-NEXT: error: no declaration found for exported symbol '_fooBar' in dynamic library +; CHECK: warning: violations found for arm64-apple-macos13 +; CHECK-NEXT: error: declaration 'unavailableSymbol' is marked unavailable, but symbol is exported in dynamic library +; CHECK-NEXT: extern int unavailableSymbol +; CHECK: warning: violations found for arm64-apple-ios16.0-macabi +; CHECK-NEXT: error: declaration 'unavailableSymbol' is marked unavailable, but symbol is exported in dynamic library +; CHECK-NEXT: extern int unavailableSymbol + + +;--- System/Library/Frameworks/Mismatch.framework/Headers/Mismatch.h +#if defined(__x86_64__) +extern int foo_arch_x86(); +#else +extern int foo_arch_arm(); +#endif + +int foo(); +int baz() __attribute__((visibility("hidden"))); + +__attribute__((visibility("hidden"))) inline int inlinedFunc() { return 1; } + +;--- System/Library/Frameworks/Mismatch.framework/PrivateHeaders/Mismatch_Private.h +#include +extern int bar(); + +@interface NSFoo : NSObject { + int nsint; +} +@end + +__attribute__((objc_exception)) +@interface NSFooExcept : NSObject +@end + +extern int unavailableSymbol __attribute__(( + availability(macosx, unavailable), availability(macCatalyst, unavailable))); + + +// Generated from source: +// *** +// int inlinedFunc() { return 1; } +// int foo() { return 1; } +// __attribute__((visibility("hidden"))) int bar() { return 1; } +// int baz() { return 1; } +// int fooBar = 1; +// int unavailableSymbol = 1; +// *** +// xcrun -sdk macosx clang -target x86_64-apple-macos13 --target-variant=x86_64-apple-ios16-macabi -dynamiclib +// xcrun -sdk macosx clang -target arm64-apple-macos13 --target-variant=arm64-apple-ios16-macabi -dynamiclib +// then lipo'ed together. + +;--- Mismatch.yaml +--- !fat-mach-o +FatHeader: + magic: 0xCAFEBABE + nfat_arch: 2 +FatArchs: + - cputype: 0x1000007 + cpusubtype: 0x3 + offset: 0x1000 + size: 20768 + align: 12 + - cputype: 0x100000C + cpusubtype: 0x0 + offset: 0x8000 + size: 49984 + align: 14 +Slices: + - !mach-o + FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 15 + sizeofcmds: 1584 + flags: 0x100085 + reserved: 0x0 + LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: __TEXT + vmaddr: 0 + vmsize: 12288 + fileoff: 0 + filesize: 12288 + maxprot: 5 + initprot: 5 + nsects: 3 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x1090 + size: 59 + offset: 0x1090 + align: 4 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 554889E5B8010000005DC30F1F440000554889E5B8010000005DC30F1F440000554889E5B8010000005DC30F1F440000554889E5B8010000005DC3 + - sectname: __unwind_info + segname: __TEXT + addr: 0x10CC + size: 4152 + offset: 0x10CC + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000001901000003800000038000000CB1000000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - sectname: __eh_frame + segname: __TEXT + addr: 0x2108 + size: 24 + offset: 0x2108 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x6000000B + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 1400000000000000017A520001781001100C070890010000 + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA_CONST + vmaddr: 12288 + vmsize: 4096 + fileoff: 12288 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 16 + Sections: + - sectname: __objc_imageinfo + segname: __DATA_CONST + addr: 0x3000 + size: 8 + offset: 0x3000 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA + vmaddr: 16384 + vmsize: 4096 + fileoff: 16384 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 0 + Sections: + - sectname: __data + segname: __DATA + addr: 0x4000 + size: 8 + offset: 0x4000 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0100000001000000' + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 20480 + vmsize: 288 + fileoff: 20480 + filesize: 288 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 20480 + export_size: 88 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 20576 + nsyms: 7 + stroff: 20688 + strsize: 80 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 1 + iextdefsym: 1 + nextdefsym: 5 + iundefsym: 6 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/Mismatch.framework/Versions/A/Mismatch' + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4421-5555-3144-A16C-E4AA63D66775 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 6 + minos: 1048576 + sdk: 1048576 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 14942208 + compatibility_version: 65536 + Content: '/usr/lib/libobjc.A.dylib' + ZeroPadBytes: 8 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88539136 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 20568 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 20576 + datasize: 0 + LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 5 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 49 + Name: inlinedFunc + Flags: 0x0 + Address: 0x1090 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 54 + Name: foo + Flags: 0x0 + Address: 0x10A0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 64 + Name: Bar + Flags: 0x0 + Address: 0x4000 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 70 + Name: unavailableSymbol + Flags: 0x0 + Address: 0x4004 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 76 + Name: baz + Flags: 0x0 + Address: 0x10C0 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 20 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 4272 + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4240 + - n_strx: 15 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4256 + - n_strx: 25 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4288 + - n_strx: 30 + n_type: 0xF + n_sect: 5 + n_desc: 0 + n_value: 16384 + - n_strx: 38 + n_type: 0xF + n_sect: 5 + n_desc: 0 + n_value: 16388 + - n_strx: 57 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - _inlinedFunc + - _foo + - _bar + - _baz + - _fooBar + - _unavailableSymbol + - dyld_stub_binder + - '' + - '' + - '' + - '' + - '' + - '' + FunctionStarts: [ 0x1090, 0x10A0, 0x10B0, 0x10C0 ] + - !mach-o + FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x6 + ncmds: 16 + sizeofcmds: 1104 + flags: 0x100085 + reserved: 0x0 + LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 0 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x1050 + size: 32 + offset: 0x1050 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 20008052C0035FD620008052C0035FD620008052C0035FD620008052C0035FD6 + - sectname: __unwind_info + segname: __TEXT + addr: 0x1070 + size: 4152 + offset: 0x1070 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000002501000003800000038000000701000000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA_CONST + vmaddr: 16384 + vmsize: 16384 + fileoff: 16384 + filesize: 16384 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 16 + Sections: + - sectname: __objc_imageinfo + segname: __DATA_CONST + addr: 0x4000 + size: 8 + offset: 0x4000 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA + vmaddr: 32768 + vmsize: 16384 + fileoff: 32768 + filesize: 16384 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 0 + Sections: + - sectname: __data + segname: __DATA + addr: 0x8000 + size: 8 + offset: 0x8000 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0100000001000000' + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 49152 + vmsize: 832 + fileoff: 49152 + filesize: 832 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 49152 + export_size: 88 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 49248 + nsyms: 7 + stroff: 49360 + strsize: 80 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 1 + iextdefsym: 1 + nextdefsym: 5 + iundefsym: 6 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/Mismatch.framework/Versions/A/Mismatch' + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4428-5555-3144-A12B-7130A3C946D2 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 6 + minos: 1048576 + sdk: 1048576 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 14942208 + compatibility_version: 65536 + Content: '/usr/lib/libobjc.A.dylib' + ZeroPadBytes: 8 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88539136 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 49240 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 49248 + datasize: 0 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 49440 + datasize: 544 + LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 5 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 49 + Name: inlinedFunc + Flags: 0x0 + Address: 0x1050 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 54 + Name: foo + Flags: 0x0 + Address: 0x1058 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 64 + Name: Bar + Flags: 0x0 + Address: 0x8000 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 70 + Name: unavailableSymbol + Flags: 0x0 + Address: 0x8004 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 76 + Name: baz + Flags: 0x0 + Address: 0x1068 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 20 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 4192 + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4176 + - n_strx: 15 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4184 + - n_strx: 25 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4200 + - n_strx: 30 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 32768 + - n_strx: 38 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 32772 + - n_strx: 57 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - _inlinedFunc + - _foo + - _bar + - _baz + - _fooBar + - _unavailableSymbol + - dyld_stub_binder + - '' + - '' + - '' + - '' + - '' + - '' + FunctionStarts: [ 0x1050, 0x1058, 0x1060, 0x1068 ] +... + +;--- inputs.json.in +{ + "headers": [ + { + "path" : "DSTROOT/System/Library/Frameworks/Mismatch.framework/PrivateHeaders/Mismatch_Private.h", + "type" : "private" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Mismatch.framework/Headers/Mismatch.h", + "type" : "public" + } + ], + "version": "3" +} diff --git a/clang/test/InstallAPI/driver-invalid-options.test b/clang/test/InstallAPI/driver-invalid-options.test index 2b2c551fca20..8efefd1b8c59 100644 --- a/clang/test/InstallAPI/driver-invalid-options.test +++ b/clang/test/InstallAPI/driver-invalid-options.test @@ -19,3 +19,10 @@ // RUN: -isysroot /no/such/path -o tmp.tbd 2> %t // RUN: FileCheck --check-prefix INVALID_ISYSROOT -input-file %t %s // INVALID_ISYSROOT: error: no such sysroot directory: {{.*}}no/such/path' + +/// Check invalid target-variant. +// RUN: not clang-installapi -target x86_64-apple-macosx12 \ +// RUN: -darwin-target-variant arm64-apple-ios15-macabi \ +// RUN: -install_name tmp.dylib -o tmp.tbd 2> %t +// RUN: FileCheck --check-prefix INVALID_TARGET_VARIANT -input-file %t %s +// INVALID_TARGET_VARIANT: error: no matching target found for target variant 'arm64-apple-ios15-macabi' diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index d1f911812800..120ff3da8998 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -104,7 +104,7 @@ bool Options::processDriverOptions(InputArgList &Args) { auto *ArgArch = Args.getLastArgNoClaim(drv::OPT_arch); auto *ArgTarget = Args.getLastArgNoClaim(drv::OPT_target); auto *ArgTargetVariant = - Args.getLastArgNoClaim(drv::OPT_darwin_target_variant_triple); + Args.getLastArgNoClaim(drv::OPT_darwin_target_variant); if (ArgArch && (ArgTarget || ArgTargetVariant)) { Diags->Report(clang::diag::err_drv_argument_not_allowed_with) << ArgArch->getAsString(Args) @@ -135,6 +135,53 @@ bool Options::processDriverOptions(InputArgList &Args) { } } + // Capture target variants. + DriverOpts.Zippered = ArgTargetVariant != nullptr; + for (Arg *A : Args.filtered(drv::OPT_darwin_target_variant)) { + A->claim(); + Triple Variant(A->getValue()); + if (Variant.getVendor() != Triple::Apple) { + Diags->Report(diag::err_unsupported_vendor) + << Variant.getVendorName() << A->getAsString(Args); + return false; + } + + switch (Variant.getOS()) { + default: + Diags->Report(diag::err_unsupported_os) + << Variant.getOSName() << A->getAsString(Args); + return false; + case Triple::MacOSX: + case Triple::IOS: + break; + } + + switch (Variant.getEnvironment()) { + default: + Diags->Report(diag::err_unsupported_environment) + << Variant.getEnvironmentName() << A->getAsString(Args); + return false; + case Triple::UnknownEnvironment: + case Triple::MacABI: + break; + } + + Target TAPIVariant(Variant); + // See if there is a matching --target option for this --target-variant + // option. + auto It = find_if(DriverOpts.Targets, [&](const auto &T) { + return (T.first.Arch == TAPIVariant.Arch) && + (T.first.Platform != PlatformType::PLATFORM_UNKNOWN); + }); + + if (It == DriverOpts.Targets.end()) { + Diags->Report(diag::err_no_matching_target) << Variant.str(); + return false; + } + + DriverOpts.Targets[TAPIVariant] = Variant; + } + DriverOpts.Verbose = Args.hasArgNoClaim(drv::OPT_v); return true; @@ -803,7 +850,8 @@ InstallAPIContext Options::createContext() { Ctx.Verifier = std::make_unique( std::move(*Slices), std::move(ReexportedIFs), Diags, - DriverOpts.VerifyMode, DriverOpts.Demangle, DriverOpts.DSYMPath); + DriverOpts.VerifyMode, DriverOpts.Zippered, DriverOpts.Demangle, + DriverOpts.DSYMPath); return Ctx; } diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h index 6da1469de2c8..984366c94e91 100644 --- a/clang/tools/clang-installapi/Options.h +++ b/clang/tools/clang-installapi/Options.h @@ -75,6 +75,9 @@ struct DriverOptions { /// \brief Verification mode for comparing symbols. VerificationMode VerifyMode = VerificationMode::Pedantic; + /// \brief Whether the library is zippered. + bool Zippered = false; + /// \brief Print demangled symbols when reporting errors. bool Demangle = false; -- GitLab From 9f14914753599f3879e4c273191959e2f1b3632c Mon Sep 17 00:00:00 2001 From: Chelsea Cassanova Date: Thu, 11 Apr 2024 20:15:43 -0700 Subject: [PATCH 027/464] Revert "Fix error in unrecognized register name handling for "SBFrame.register"" (#88468) Reverts llvm/llvm-project#88047. TestFrames.py is failing on x86_64 GreenDragon: https://green.lab.llvm.org/job/llvm.org/view/LLDB/job/lldb-cmake/983/ --- lldb/bindings/interface/SBFrameExtensions.i | 12 +----------- lldb/test/API/python_api/frame/TestFrames.py | 12 ------------ 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/lldb/bindings/interface/SBFrameExtensions.i b/lldb/bindings/interface/SBFrameExtensions.i index e0472280666a..43b22ed7a6b3 100644 --- a/lldb/bindings/interface/SBFrameExtensions.i +++ b/lldb/bindings/interface/SBFrameExtensions.i @@ -44,16 +44,6 @@ STRING_EXTENSION_OUTSIDE(SBFrame) def __init__(self, regs): self.regs = regs - def __iter__(self): - return self.get_registers() - - def get_registers(self): - for i in range(0,len(self.regs)): - rs = self.regs[i] - for j in range (0,rs.num_children): - reg = rs.GetChildAtIndex(j) - yield reg - def __getitem__(self, key): if type(key) is str: for i in range(0,len(self.regs)): @@ -62,7 +52,7 @@ STRING_EXTENSION_OUTSIDE(SBFrame) reg = rs.GetChildAtIndex(j) if reg.name == key: return reg else: - return SBValue() + return lldb.SBValue() return registers_access(self.registers) diff --git a/lldb/test/API/python_api/frame/TestFrames.py b/lldb/test/API/python_api/frame/TestFrames.py index dfa96d51830b..a82b129bc809 100644 --- a/lldb/test/API/python_api/frame/TestFrames.py +++ b/lldb/test/API/python_api/frame/TestFrames.py @@ -73,19 +73,7 @@ class FrameAPITestCase(TestBase): gpr_reg_set = lldbutil.get_GPRs(frame) pc_value = gpr_reg_set.GetChildMemberWithName("pc") self.assertTrue(pc_value, "We should have a valid PC.") - # Make sure we can also get this from the "register" property: - iterator_pc_value = 0 - found_pc = False - for reg in frame.register: - if reg.name == "pc": - found_pc = True - iterator_pc_value = int(reg.GetValue(), 0) - break - pc_value_int = int(pc_value.GetValue(), 0) - self.assertTrue(found_pc, "Found the PC value in the register list") - self.assertEqual(iterator_pc_value, pc_value_int, "The methods of finding pc match") - # Make sure on arm targets we dont mismatch PC value on the basis of thumb bit. # Frame PC will not have thumb bit set in case of a thumb # instruction as PC. -- GitLab From c1a44568911b75c98675a3c19a55b4741d861437 Mon Sep 17 00:00:00 2001 From: Chelsea Cassanova Date: Thu, 11 Apr 2024 20:21:16 -0700 Subject: [PATCH 028/464] =?UTF-8?q?Reland=20"[lldb][lit]=20Add=20MallocNan?= =?UTF-8?q?oZone=20envvar=20to=20Darwin=20ASan=20builds"=20=E2=80=A6=20(#8?= =?UTF-8?q?8442)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …(#88436)" This reverts commit 1f5d130df85c2d0550dc8687ad0fa1d96856c318. The original commit checks that the host system is "Darwin" before setting the `MallocNanoZone` envvar, but on the Shell lit config this attribute does not exist at the point where it is being checked which leads to a build failure. This commit checks the host OS correctly. --- lldb/test/API/lit.cfg.py | 1 + lldb/test/Shell/lit.cfg.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py index f9497b632fc5..9ea389c639a0 100644 --- a/lldb/test/API/lit.cfg.py +++ b/lldb/test/API/lit.cfg.py @@ -121,6 +121,7 @@ if is_configured("llvm_use_sanitizer"): config.environment["DYLD_INSERT_LIBRARIES"] = find_sanitizer_runtime( "libclang_rt.asan_osx_dynamic.dylib" ) + config.environment["MallocNanoZone"] = "0" if "Thread" in config.llvm_use_sanitizer: config.environment["TSAN_OPTIONS"] = "halt_on_error=1" diff --git a/lldb/test/Shell/lit.cfg.py b/lldb/test/Shell/lit.cfg.py index 31afe5151c06..290569576ac8 100644 --- a/lldb/test/Shell/lit.cfg.py +++ b/lldb/test/Shell/lit.cfg.py @@ -52,6 +52,8 @@ llvm_config.with_system_environment( # Enable sanitizer runtime flags. config.environment["ASAN_OPTIONS"] = "detect_stack_use_after_return=1" config.environment["TSAN_OPTIONS"] = "halt_on_error=1" +if platform.system() == "Darwin": + config.environment["MallocNanoZone"] = "0" # Support running the test suite under the lldb-repro wrapper. This makes it # possible to capture a test suite run and then rerun all the test from the -- GitLab From b45c9c313c5107b1942cd325e8ab3b4235948a08 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Fri, 12 Apr 2024 07:44:58 +0400 Subject: [PATCH 029/464] [clang][NFC] Move more functions to `SemaHLSL` (#88354) A follow-up to #87912. I'm moving more HLSL-related functions from `Sema` to `SemaHLSL`. I'm also dropping `HLSL` from their names in the process. --- clang/include/clang/Sema/Sema.h | 15 --- clang/include/clang/Sema/SemaHLSL.h | 27 +++- clang/lib/Parse/ParseHLSL.cpp | 10 +- clang/lib/Sema/SemaDecl.cpp | 130 +------------------ clang/lib/Sema/SemaDeclAttr.cpp | 54 +------- clang/lib/Sema/SemaHLSL.cpp | 186 +++++++++++++++++++++++++++- 6 files changed, 218 insertions(+), 204 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 351b8e1f3113..c4a603cc5a4a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2940,13 +2940,6 @@ public: QualType NewT, QualType OldT); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); - void ActOnHLSLTopLevelFunction(FunctionDecl *FD); - void CheckHLSLEntryPoint(FunctionDecl *FD); - void CheckHLSLSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, - const HLSLAnnotationAttr *AnnotationAttr); - void DiagnoseHLSLAttrStageMismatch( - const Attr *A, HLSLShaderAttr::ShaderType Stage, - std::initializer_list AllowedStages); Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); @@ -3708,14 +3701,6 @@ public: StringRef UuidAsWritten, MSGuidDecl *GuidDecl); BTFDeclTagAttr *mergeBTFDeclTagAttr(Decl *D, const BTFDeclTagAttr &AL); - HLSLNumThreadsAttr *mergeHLSLNumThreadsAttr(Decl *D, - const AttributeCommonInfo &AL, - int X, int Y, int Z); - HLSLShaderAttr *mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLShaderAttr::ShaderType ShaderType); - HLSLParamModifierAttr * - mergeHLSLParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLParamModifierAttr::Spelling Spelling); WebAssemblyImportNameAttr * mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL); diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index acc675963c23..34acaf19517f 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -13,12 +13,16 @@ #ifndef LLVM_CLANG_SEMA_SEMAHLSL_H #define LLVM_CLANG_SEMA_SEMAHLSL_H +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/Expr.h" +#include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaBase.h" +#include namespace clang { @@ -26,10 +30,25 @@ class SemaHLSL : public SemaBase { public: SemaHLSL(Sema &S); - Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer, - SourceLocation KwLoc, IdentifierInfo *Ident, - SourceLocation IdentLoc, SourceLocation LBrace); - void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace); + Decl *ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, + IdentifierInfo *Ident, SourceLocation IdentLoc, + SourceLocation LBrace); + void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace); + HLSLNumThreadsAttr *mergeNumThreadsAttr(Decl *D, + const AttributeCommonInfo &AL, int X, + int Y, int Z); + HLSLShaderAttr *mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLShaderAttr::ShaderType ShaderType); + HLSLParamModifierAttr * + mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLParamModifierAttr::Spelling Spelling); + void ActOnTopLevelFunction(FunctionDecl *FD); + void CheckEntryPoint(FunctionDecl *FD); + void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, + const HLSLAnnotationAttr *AnnotationAttr); + void DiagnoseAttrStageMismatch( + const Attr *A, HLSLShaderAttr::ShaderType Stage, + std::initializer_list AllowedStages); }; } // namespace clang diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp index 5afc958600fa..d97985d42369 100644 --- a/clang/lib/Parse/ParseHLSL.cpp +++ b/clang/lib/Parse/ParseHLSL.cpp @@ -72,9 +72,9 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) { return nullptr; } - Decl *D = Actions.HLSL().ActOnStartHLSLBuffer( - getCurScope(), IsCBuffer, BufferLoc, Identifier, IdentifierLoc, - T.getOpenLocation()); + Decl *D = Actions.HLSL().ActOnStartBuffer(getCurScope(), IsCBuffer, BufferLoc, + Identifier, IdentifierLoc, + T.getOpenLocation()); while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // FIXME: support attribute on constants inside cbuffer/tbuffer. @@ -88,7 +88,7 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) { T.skipToEnd(); DeclEnd = T.getCloseLocation(); BufferScope.Exit(); - Actions.HLSL().ActOnFinishHLSLBuffer(D, DeclEnd); + Actions.HLSL().ActOnFinishBuffer(D, DeclEnd); return nullptr; } } @@ -96,7 +96,7 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) { T.consumeClose(); DeclEnd = T.getCloseLocation(); BufferScope.Exit(); - Actions.HLSL().ActOnFinishHLSLBuffer(D, DeclEnd); + Actions.HLSL().ActOnFinishBuffer(D, DeclEnd); Actions.ProcessDeclAttributeList(Actions.CurScope, D, Attrs); return D; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 691e170cd051..afd9e407946a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -45,6 +45,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/SmallString.h" @@ -2972,10 +2973,10 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, else if (const auto *BTFA = dyn_cast(Attr)) NewAttr = S.mergeBTFDeclTagAttr(D, *BTFA); else if (const auto *NT = dyn_cast(Attr)) - NewAttr = - S.mergeHLSLNumThreadsAttr(D, *NT, NT->getX(), NT->getY(), NT->getZ()); + NewAttr = S.HLSL().mergeNumThreadsAttr(D, *NT, NT->getX(), NT->getY(), + NT->getZ()); else if (const auto *SA = dyn_cast(Attr)) - NewAttr = S.mergeHLSLShaderAttr(D, *SA, SA->getType()); + NewAttr = S.HLSL().mergeShaderAttr(D, *SA, SA->getType()); else if (isa(Attr)) // Do nothing. Each redeclaration should be suppressed separately. NewAttr = nullptr; @@ -10808,10 +10809,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (getLangOpts().HLSL && D.isFunctionDefinition()) { // Any top level function could potentially be specified as an entry. if (!NewFD->isInvalidDecl() && S->getDepth() == 0 && Name.isIdentifier()) - ActOnHLSLTopLevelFunction(NewFD); + HLSL().ActOnTopLevelFunction(NewFD); if (NewFD->hasAttr()) - CheckHLSLEntryPoint(NewFD); + HLSL().CheckEntryPoint(NewFD); } // If this is the first declaration of a library builtin function, add @@ -12665,125 +12666,6 @@ void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) { } } -void Sema::ActOnHLSLTopLevelFunction(FunctionDecl *FD) { - auto &TargetInfo = getASTContext().getTargetInfo(); - - if (FD->getName() != TargetInfo.getTargetOpts().HLSLEntry) - return; - - StringRef Env = TargetInfo.getTriple().getEnvironmentName(); - HLSLShaderAttr::ShaderType ShaderType; - if (HLSLShaderAttr::ConvertStrToShaderType(Env, ShaderType)) { - if (const auto *Shader = FD->getAttr()) { - // The entry point is already annotated - check that it matches the - // triple. - if (Shader->getType() != ShaderType) { - Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch) - << Shader; - FD->setInvalidDecl(); - } - } else { - // Implicitly add the shader attribute if the entry function isn't - // explicitly annotated. - FD->addAttr(HLSLShaderAttr::CreateImplicit(Context, ShaderType, - FD->getBeginLoc())); - } - } else { - switch (TargetInfo.getTriple().getEnvironment()) { - case llvm::Triple::UnknownEnvironment: - case llvm::Triple::Library: - break; - default: - llvm_unreachable("Unhandled environment in triple"); - } - } -} - -void Sema::CheckHLSLEntryPoint(FunctionDecl *FD) { - const auto *ShaderAttr = FD->getAttr(); - assert(ShaderAttr && "Entry point has no shader attribute"); - HLSLShaderAttr::ShaderType ST = ShaderAttr->getType(); - - switch (ST) { - case HLSLShaderAttr::Pixel: - case HLSLShaderAttr::Vertex: - case HLSLShaderAttr::Geometry: - case HLSLShaderAttr::Hull: - case HLSLShaderAttr::Domain: - case HLSLShaderAttr::RayGeneration: - case HLSLShaderAttr::Intersection: - case HLSLShaderAttr::AnyHit: - case HLSLShaderAttr::ClosestHit: - case HLSLShaderAttr::Miss: - case HLSLShaderAttr::Callable: - if (const auto *NT = FD->getAttr()) { - DiagnoseHLSLAttrStageMismatch(NT, ST, - {HLSLShaderAttr::Compute, - HLSLShaderAttr::Amplification, - HLSLShaderAttr::Mesh}); - FD->setInvalidDecl(); - } - break; - - case HLSLShaderAttr::Compute: - case HLSLShaderAttr::Amplification: - case HLSLShaderAttr::Mesh: - if (!FD->hasAttr()) { - Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads) - << HLSLShaderAttr::ConvertShaderTypeToStr(ST); - FD->setInvalidDecl(); - } - break; - } - - for (ParmVarDecl *Param : FD->parameters()) { - if (const auto *AnnotationAttr = Param->getAttr()) { - CheckHLSLSemanticAnnotation(FD, Param, AnnotationAttr); - } else { - // FIXME: Handle struct parameters where annotations are on struct fields. - // See: https://github.com/llvm/llvm-project/issues/57875 - Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation); - Diag(Param->getLocation(), diag::note_previous_decl) << Param; - FD->setInvalidDecl(); - } - } - // FIXME: Verify return type semantic annotation. -} - -void Sema::CheckHLSLSemanticAnnotation( - FunctionDecl *EntryPoint, const Decl *Param, - const HLSLAnnotationAttr *AnnotationAttr) { - auto *ShaderAttr = EntryPoint->getAttr(); - assert(ShaderAttr && "Entry point has no shader attribute"); - HLSLShaderAttr::ShaderType ST = ShaderAttr->getType(); - - switch (AnnotationAttr->getKind()) { - case attr::HLSLSV_DispatchThreadID: - case attr::HLSLSV_GroupIndex: - if (ST == HLSLShaderAttr::Compute) - return; - DiagnoseHLSLAttrStageMismatch(AnnotationAttr, ST, - {HLSLShaderAttr::Compute}); - break; - default: - llvm_unreachable("Unknown HLSLAnnotationAttr"); - } -} - -void Sema::DiagnoseHLSLAttrStageMismatch( - const Attr *A, HLSLShaderAttr::ShaderType Stage, - std::initializer_list AllowedStages) { - SmallVector StageStrings; - llvm::transform(AllowedStages, std::back_inserter(StageStrings), - [](HLSLShaderAttr::ShaderType ST) { - return StringRef( - HLSLShaderAttr::ConvertShaderTypeToStr(ST)); - }); - Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage) - << A << HLSLShaderAttr::ConvertShaderTypeToStr(Stage) - << (AllowedStages.size() != 1) << join(StageStrings, ", "); -} - bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { // FIXME: Need strict checking. In C89, we need to check for // any assignment, increment, decrement, function-calls, or diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8bce04640e74..b91064e28e41 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -39,6 +39,7 @@ #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" @@ -7238,24 +7239,11 @@ static void handleHLSLNumThreadsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - HLSLNumThreadsAttr *NewAttr = S.mergeHLSLNumThreadsAttr(D, AL, X, Y, Z); + HLSLNumThreadsAttr *NewAttr = S.HLSL().mergeNumThreadsAttr(D, AL, X, Y, Z); if (NewAttr) D->addAttr(NewAttr); } -HLSLNumThreadsAttr *Sema::mergeHLSLNumThreadsAttr(Decl *D, - const AttributeCommonInfo &AL, - int X, int Y, int Z) { - if (HLSLNumThreadsAttr *NT = D->getAttr()) { - if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) { - Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL; - Diag(AL.getLoc(), diag::note_conflicting_attribute); - } - return nullptr; - } - return ::new (Context) HLSLNumThreadsAttr(Context, AL, X, Y, Z); -} - static bool isLegalTypeForHLSLSV_DispatchThreadID(QualType T) { if (!T->hasUnsignedIntegerRepresentation()) return false; @@ -7299,24 +7287,11 @@ static void handleHLSLShaderAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // FIXME: check function match the shader stage. - HLSLShaderAttr *NewAttr = S.mergeHLSLShaderAttr(D, AL, ShaderType); + HLSLShaderAttr *NewAttr = S.HLSL().mergeShaderAttr(D, AL, ShaderType); if (NewAttr) D->addAttr(NewAttr); } -HLSLShaderAttr * -Sema::mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLShaderAttr::ShaderType ShaderType) { - if (HLSLShaderAttr *NT = D->getAttr()) { - if (NT->getType() != ShaderType) { - Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL; - Diag(AL.getLoc(), diag::note_conflicting_attribute); - } - return nullptr; - } - return HLSLShaderAttr::Create(Context, ShaderType, AL); -} - static void handleHLSLResourceBindingAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef Space = "space0"; @@ -7391,34 +7366,13 @@ static void handleHLSLResourceBindingAttr(Sema &S, Decl *D, static void handleHLSLParamModifierAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - HLSLParamModifierAttr *NewAttr = S.mergeHLSLParamModifierAttr( + HLSLParamModifierAttr *NewAttr = S.HLSL().mergeParamModifierAttr( D, AL, static_cast(AL.getSemanticSpelling())); if (NewAttr) D->addAttr(NewAttr); } -HLSLParamModifierAttr * -Sema::mergeHLSLParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLParamModifierAttr::Spelling Spelling) { - // We can only merge an `in` attribute with an `out` attribute. All other - // combinations of duplicated attributes are ill-formed. - if (HLSLParamModifierAttr *PA = D->getAttr()) { - if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) || - (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) { - D->dropAttr(); - SourceRange AdjustedRange = {PA->getLocation(), AL.getRange().getEnd()}; - return HLSLParamModifierAttr::Create( - Context, /*MergedSpelling=*/true, AdjustedRange, - HLSLParamModifierAttr::Keyword_inout); - } - Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL; - Diag(PA->getLocation(), diag::note_conflicting_attribute); - return nullptr; - } - return HLSLParamModifierAttr::Create(Context, AL); -} - static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 681849d6e6c8..bb9e37f18d37 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -9,17 +9,25 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaHLSL.h" +#include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Sema.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/TargetParser/Triple.h" +#include using namespace clang; SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S) {} -Decl *SemaHLSL::ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer, - SourceLocation KwLoc, - IdentifierInfo *Ident, - SourceLocation IdentLoc, - SourceLocation LBrace) { +Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer, + SourceLocation KwLoc, IdentifierInfo *Ident, + SourceLocation IdentLoc, + SourceLocation LBrace) { // For anonymous namespace, take the location of the left brace. DeclContext *LexicalParent = SemaRef.getCurLexicalContext(); HLSLBufferDecl *Result = HLSLBufferDecl::Create( @@ -31,8 +39,174 @@ Decl *SemaHLSL::ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer, return Result; } -void SemaHLSL::ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace) { +void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) { auto *BufDecl = cast(Dcl); BufDecl->setRBraceLoc(RBrace); SemaRef.PopDeclContext(); } + +HLSLNumThreadsAttr *SemaHLSL::mergeNumThreadsAttr(Decl *D, + const AttributeCommonInfo &AL, + int X, int Y, int Z) { + if (HLSLNumThreadsAttr *NT = D->getAttr()) { + if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) { + Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL; + Diag(AL.getLoc(), diag::note_conflicting_attribute); + } + return nullptr; + } + return ::new (getASTContext()) + HLSLNumThreadsAttr(getASTContext(), AL, X, Y, Z); +} + +HLSLShaderAttr * +SemaHLSL::mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLShaderAttr::ShaderType ShaderType) { + if (HLSLShaderAttr *NT = D->getAttr()) { + if (NT->getType() != ShaderType) { + Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL; + Diag(AL.getLoc(), diag::note_conflicting_attribute); + } + return nullptr; + } + return HLSLShaderAttr::Create(getASTContext(), ShaderType, AL); +} + +HLSLParamModifierAttr * +SemaHLSL::mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLParamModifierAttr::Spelling Spelling) { + // We can only merge an `in` attribute with an `out` attribute. All other + // combinations of duplicated attributes are ill-formed. + if (HLSLParamModifierAttr *PA = D->getAttr()) { + if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) || + (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) { + D->dropAttr(); + SourceRange AdjustedRange = {PA->getLocation(), AL.getRange().getEnd()}; + return HLSLParamModifierAttr::Create( + getASTContext(), /*MergedSpelling=*/true, AdjustedRange, + HLSLParamModifierAttr::Keyword_inout); + } + Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL; + Diag(PA->getLocation(), diag::note_conflicting_attribute); + return nullptr; + } + return HLSLParamModifierAttr::Create(getASTContext(), AL); +} + +void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) { + auto &TargetInfo = getASTContext().getTargetInfo(); + + if (FD->getName() != TargetInfo.getTargetOpts().HLSLEntry) + return; + + StringRef Env = TargetInfo.getTriple().getEnvironmentName(); + HLSLShaderAttr::ShaderType ShaderType; + if (HLSLShaderAttr::ConvertStrToShaderType(Env, ShaderType)) { + if (const auto *Shader = FD->getAttr()) { + // The entry point is already annotated - check that it matches the + // triple. + if (Shader->getType() != ShaderType) { + Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch) + << Shader; + FD->setInvalidDecl(); + } + } else { + // Implicitly add the shader attribute if the entry function isn't + // explicitly annotated. + FD->addAttr(HLSLShaderAttr::CreateImplicit(getASTContext(), ShaderType, + FD->getBeginLoc())); + } + } else { + switch (TargetInfo.getTriple().getEnvironment()) { + case llvm::Triple::UnknownEnvironment: + case llvm::Triple::Library: + break; + default: + llvm_unreachable("Unhandled environment in triple"); + } + } +} + +void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) { + const auto *ShaderAttr = FD->getAttr(); + assert(ShaderAttr && "Entry point has no shader attribute"); + HLSLShaderAttr::ShaderType ST = ShaderAttr->getType(); + + switch (ST) { + case HLSLShaderAttr::Pixel: + case HLSLShaderAttr::Vertex: + case HLSLShaderAttr::Geometry: + case HLSLShaderAttr::Hull: + case HLSLShaderAttr::Domain: + case HLSLShaderAttr::RayGeneration: + case HLSLShaderAttr::Intersection: + case HLSLShaderAttr::AnyHit: + case HLSLShaderAttr::ClosestHit: + case HLSLShaderAttr::Miss: + case HLSLShaderAttr::Callable: + if (const auto *NT = FD->getAttr()) { + DiagnoseAttrStageMismatch(NT, ST, + {HLSLShaderAttr::Compute, + HLSLShaderAttr::Amplification, + HLSLShaderAttr::Mesh}); + FD->setInvalidDecl(); + } + break; + + case HLSLShaderAttr::Compute: + case HLSLShaderAttr::Amplification: + case HLSLShaderAttr::Mesh: + if (!FD->hasAttr()) { + Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads) + << HLSLShaderAttr::ConvertShaderTypeToStr(ST); + FD->setInvalidDecl(); + } + break; + } + + for (ParmVarDecl *Param : FD->parameters()) { + if (const auto *AnnotationAttr = Param->getAttr()) { + CheckSemanticAnnotation(FD, Param, AnnotationAttr); + } else { + // FIXME: Handle struct parameters where annotations are on struct fields. + // See: https://github.com/llvm/llvm-project/issues/57875 + Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation); + Diag(Param->getLocation(), diag::note_previous_decl) << Param; + FD->setInvalidDecl(); + } + } + // FIXME: Verify return type semantic annotation. +} + +void SemaHLSL::CheckSemanticAnnotation( + FunctionDecl *EntryPoint, const Decl *Param, + const HLSLAnnotationAttr *AnnotationAttr) { + auto *ShaderAttr = EntryPoint->getAttr(); + assert(ShaderAttr && "Entry point has no shader attribute"); + HLSLShaderAttr::ShaderType ST = ShaderAttr->getType(); + + switch (AnnotationAttr->getKind()) { + case attr::HLSLSV_DispatchThreadID: + case attr::HLSLSV_GroupIndex: + if (ST == HLSLShaderAttr::Compute) + return; + DiagnoseAttrStageMismatch(AnnotationAttr, ST, {HLSLShaderAttr::Compute}); + break; + default: + llvm_unreachable("Unknown HLSLAnnotationAttr"); + } +} + +void SemaHLSL::DiagnoseAttrStageMismatch( + const Attr *A, HLSLShaderAttr::ShaderType Stage, + std::initializer_list AllowedStages) { + SmallVector StageStrings; + llvm::transform(AllowedStages, std::back_inserter(StageStrings), + [](HLSLShaderAttr::ShaderType ST) { + return StringRef( + HLSLShaderAttr::ConvertShaderTypeToStr(ST)); + }); + Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage) + << A << HLSLShaderAttr::ConvertShaderTypeToStr(Stage) + << (AllowedStages.size() != 1) << join(StageStrings, ", "); +} -- GitLab From 505a9ae81d620b92284f7b2cbe874c936cf19583 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Fri, 12 Apr 2024 06:49:53 +0200 Subject: [PATCH 030/464] [Clang] Look through type sugar when accessing FunctionProtoType (#88428) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a bug introduced by #84473: if a lambda’s type is type sugar (e.g. an `AttributedType`), we need to use `getAs()` instead of `cast()` to retrieve the `FunctionProtoType`. --- clang/lib/Sema/SemaExpr.cpp | 2 +- clang/lib/Sema/SemaExprCXX.cpp | 2 +- clang/test/SemaCXX/cxx2b-deducing-this.cpp | 12 ++++++++++++ clang/test/SemaCXX/lambda-expressions.cpp | 9 +++++++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 846e7d5d3ab9..ec5ca2b9352e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -20704,7 +20704,7 @@ static void FixDependencyOfIdExpressionsInLambdaWithDependentObjectParameter( if (MD->getType().isNull()) continue; - const auto *Ty = cast(MD->getType()); + const auto *Ty = MD->getType()->getAs(); if (!Ty || !MD->isExplicitObjectMemberFunction() || !Ty->getParamType(0)->isDependentType()) continue; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 763901d4418d..ac39cb99fc93 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1488,7 +1488,7 @@ void Sema::MarkThisReferenced(CXXThisExpr *This) { if (MD->getType().isNull()) return false; - const auto *Ty = cast(MD->getType()); + const auto *Ty = MD->getType()->getAs(); return Ty && MD->isExplicitObjectMemberFunction() && Ty->getParamType(0)->isDependentType(); } diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp index c14c971afd23..5f29a955e053 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -312,6 +312,18 @@ void TestMutationInLambda() { l1(); l2(); } + + // Check that we don't crash if the lambda has type sugar. + const auto l15 = [=](this auto&&) [[clang::annotate_type("foo")]] [[clang::annotate_type("bar")]] { + return x; + }; + + const auto l16 = [=]() [[clang::annotate_type("foo")]] [[clang::annotate_type("bar")]] { + return x; + }; + + l15(); + l16(); } struct Over_Call_Func_Example { diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 151d74f21d64..6be338064452 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -762,3 +762,12 @@ template auto t::operator()(int a) const; // expected-note {{in instantiati } #endif + +namespace GH84473_bug { +void f1() { + int b; + (void) [=] [[gnu::regcall]] () { // expected-warning {{an attribute specifier sequence in this position is a C++23 extension}} + (void) b; + }; +} +} -- GitLab From f21ead06750b670cf8ce72d6666e3550b04056a2 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Fri, 12 Apr 2024 12:51:58 +0800 Subject: [PATCH 031/464] [C++20] [Modules] [Reduced BMI] Remove unreachable decls GMF in redued BMI (#88359) Following of https://github.com/llvm/llvm-project/pull/76930 This follows the idea of "only writes what we writes", which I think is the most natural and efficient way to implement this optimization. We start writing the BMI from the first declaration in module purview instead of the global module fragment, so that everything in the GMF untouched won't be written in the BMI naturally. The exception is, as I said in https://github.com/llvm/llvm-project/pull/76930, when we write a declaration we need to write its decl context, and when we write the decl context, we need to write everything from it. So when we see `std::vector`, we basically need to write everything under namespace std. This violates our intention. To fix this, this patch delays the writing of namespace in the GMF. From my local measurement, the size of the BMI decrease to 90M from 112M for a local modules build. I think this is significant. This feature will be covered under the experimental reduced BMI so that it won't affect any existing users. So I'd like to land this when the CI gets green. Documents will be added seperately. --- .../include/clang/Serialization/ASTBitCodes.h | 4 + clang/include/clang/Serialization/ASTReader.h | 14 ++ clang/include/clang/Serialization/ASTWriter.h | 26 +++- clang/lib/Serialization/ASTReader.cpp | 23 +++ clang/lib/Serialization/ASTReaderDecl.cpp | 9 ++ clang/lib/Serialization/ASTWriter.cpp | 139 +++++++++++++++--- clang/lib/Serialization/ASTWriterDecl.cpp | 27 +++- .../module.glob.frag/cxx20-10-4-ex2.cppm | 58 ++++++++ .../inconsistent-deduction-guide-linkage.cppm | 8 + clang/test/Modules/named-modules-adl-2.cppm | 7 +- clang/test/Modules/named-modules-adl.cppm | 7 +- .../test/Modules/placement-new-reachable.cpp | 9 +- clang/test/Modules/polluted-operator.cppm | 15 +- clang/test/Modules/pr62589.cppm | 4 + clang/test/Modules/preferred_name.cppm | 2 + .../redundant-template-default-arg3.cpp | 10 ++ .../template-function-specialization.cpp | 8 +- 17 files changed, 337 insertions(+), 33 deletions(-) create mode 100644 clang/test/CXX/module/module.glob.frag/cxx20-10-4-ex2.cppm diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index f762116fea95..500098dd3dab 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -698,6 +698,10 @@ enum ASTRecordTypes { /// Record code for an unterminated \#pragma clang assume_nonnull begin /// recorded in a preamble. PP_ASSUME_NONNULL_LOC = 67, + + /// Record code for lexical and visible block for delayed namespace in + /// reduced BMI. + DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD = 68, }; /// Record types used within a source manager block. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index e8b9f28690d9..6656c1c58dec 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -517,6 +517,20 @@ private: /// in the chain. DeclUpdateOffsetsMap DeclUpdateOffsets; + using DelayedNamespaceOffsetMapTy = llvm::DenseMap< + serialization::DeclID, + std::pair>; + + /// Mapping from global declaration IDs to the lexical and visible block + /// offset for delayed namespace in reduced BMI. + /// + /// We can't use the existing DeclUpdate mechanism since the DeclUpdate + /// may only be applied in an outer most read. However, we need to know + /// whether or not a DeclContext has external storage during the recursive + /// reading. So we need to apply the offset immediately after we read the + /// namespace as if it is not delayed. + DelayedNamespaceOffsetMapTy DelayedNamespaceOffsetMap; + struct PendingUpdateRecord { Decl *D; serialization::GlobalDeclID ID; diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 214eb3601148..443f77031047 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -201,6 +201,16 @@ private: /// The declarations and types to emit. std::queue DeclTypesToEmit; + /// The delayed namespace to emit. Only meaningful for reduced BMI. + /// + /// In reduced BMI, we want to elide the unreachable declarations in + /// the global module fragment. However, in ASTWriterDecl, when we see + /// a namespace, all the declarations in the namespace would be emitted. + /// So the optimization become meaningless. To solve the issue, we + /// delay recording all the declarations until we emit all the declarations. + /// Then we can safely record the reached declarations only. + llvm::SmallVector DelayedNamespace; + /// The first ID number we can use for our own declarations. serialization::DeclID FirstDeclID = serialization::NUM_PREDEF_DECL_IDS; @@ -529,7 +539,8 @@ private: void WriteType(QualType T); bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC); - bool isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC); + bool isLookupResultEntirelyExternalOrUnreachable(StoredDeclsList &Result, + DeclContext *DC); void GenerateNameLookupTable(const DeclContext *DC, llvm::SmallVectorImpl &LookupTable); @@ -704,6 +715,15 @@ public: /// declaration. serialization::DeclID getDeclID(const Decl *D); + /// Whether or not the declaration got emitted. If not, it wouldn't be + /// emitted. + /// + /// This may only be called after we've done the job to write the + /// declarations (marked by DoneWritingDeclsAndTypes). + /// + /// A declaration may only be omitted in reduced BMI. + bool wasDeclEmitted(const Decl *D) const; + unsigned getAnonymousDeclarationNumber(const NamedDecl *D); /// Add a string to the given record. @@ -798,6 +818,10 @@ public: return WritingModule && WritingModule->isNamedModule(); } + bool isGeneratingReducedBMI() const { return GeneratingReducedBMI; } + + bool getDoneWritingDeclsAndTypes() const { return DoneWritingDeclsAndTypes; } + private: // ASTDeserializationListener implementation void ReaderInitialized(ASTReader *Reader) override; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 4f6987f92fc8..ce96ce2bdbcc 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3795,6 +3795,29 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, } break; + case DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD: { + if (Record.size() % 3 != 0) + return llvm::createStringError( + std::errc::illegal_byte_sequence, + "invalid DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD block in AST " + "file"); + for (unsigned I = 0, N = Record.size(); I != N; I += 3) { + GlobalDeclID ID = getGlobalDeclID(F, Record[I]); + + uint64_t BaseOffset = F.DeclsBlockStartOffset; + assert(BaseOffset && "Invalid DeclsBlockStartOffset for module file!"); + uint64_t LexicalOffset = Record[I + 1] ? BaseOffset + Record[I + 1] : 0; + uint64_t VisibleOffset = Record[I + 2] ? BaseOffset + Record[I + 2] : 0; + + DelayedNamespaceOffsetMap[ID] = {LexicalOffset, VisibleOffset}; + + assert(!GetExistingDecl(ID) && + "We shouldn't load the namespace in the front of delayed " + "namespace lexical and visible block"); + } + break; + } + case OBJC_CATEGORIES_MAP: if (F.LocalNumObjCCategoriesInMap != 0) return llvm::createStringError( diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 5b7b9f19a106..ff72fc30c718 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4125,6 +4125,15 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // offsets for its tables of lexical and visible declarations. if (auto *DC = dyn_cast(D)) { std::pair Offsets = Reader.VisitDeclContext(DC); + + // Get the lexical and visible block for the delayed namespace. + // It is sufficient to judge if ID is in DelayedNamespaceOffsetMap. + // But it may be more efficient to filter the other cases. + if (!Offsets.first && !Offsets.second && isa(D)) + if (auto Iter = DelayedNamespaceOffsetMap.find(ID); + Iter != DelayedNamespaceOffsetMap.end()) + Offsets = Iter->second; + if (Offsets.first && ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC)) return nullptr; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 330dbd623350..d9ba10ab6087 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -869,6 +869,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(WEAK_UNDECLARED_IDENTIFIERS); RECORD(PENDING_IMPLICIT_INSTANTIATIONS); RECORD(UPDATE_VISIBLE); + RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD); RECORD(DECL_UPDATE_OFFSETS); RECORD(DECL_UPDATES); RECORD(CUDA_SPECIAL_DECL_REFS); @@ -3026,10 +3027,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM); } - // Emit the initializers, if any. + // Emit the reachable initializers. + // The initializer may only be unreachable in reduced BMI. RecordData Inits; for (Decl *D : Context->getModuleInitializers(Mod)) - Inits.push_back(GetDeclRef(D)); + if (wasDeclEmitted(D)) + Inits.push_back(GetDeclRef(D)); if (!Inits.empty()) Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits); @@ -3208,6 +3211,9 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, uint64_t Offset = Stream.GetCurrentBitNo(); SmallVector KindDeclPairs; for (const auto *D : DC->decls()) { + if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D)) + continue; + KindDeclPairs.push_back(D->getKind()); KindDeclPairs.push_back(GetDeclRef(D)); } @@ -3862,8 +3868,14 @@ public: data_type getData(const Coll &Decls) { unsigned Start = DeclIDs.size(); for (NamedDecl *D : Decls) { - DeclIDs.push_back( - Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D))); + NamedDecl *DeclForLocalLookup = + getDeclForLocalLookup(Writer.getLangOpts(), D); + + if (Writer.getDoneWritingDeclsAndTypes() && + !Writer.wasDeclEmitted(DeclForLocalLookup)) + continue; + + DeclIDs.push_back(Writer.GetDeclRef(DeclForLocalLookup)); } return std::make_pair(Start, DeclIDs.size()); } @@ -3972,11 +3984,20 @@ bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result, DC->hasNeedToReconcileExternalVisibleStorage(); } -bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result, - DeclContext *DC) { - for (auto *D : Result.getLookupResult()) - if (!getDeclForLocalLookup(getLangOpts(), D)->isFromASTFile()) - return false; +bool ASTWriter::isLookupResultEntirelyExternalOrUnreachable( + StoredDeclsList &Result, DeclContext *DC) { + for (auto *D : Result.getLookupResult()) { + auto *LocalD = getDeclForLocalLookup(getLangOpts(), D); + if (LocalD->isFromASTFile()) + continue; + + // We can only be sure whether the local declaration is reachable + // after we done writing the declarations and types. + if (DoneWritingDeclsAndTypes && !wasDeclEmitted(LocalD)) + continue; + + return false; + } return true; } @@ -4014,8 +4035,17 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, // don't need to write an entry for the name at all. If we can't // write out a lookup set without performing more deserialization, // just skip this entry. - if (isLookupResultExternal(Result, DC) && - isLookupResultEntirelyExternal(Result, DC)) + // + // Also in reduced BMI, we'd like to avoid writing unreachable + // declarations in GMF, so we need to avoid writing declarations + // that entirely external or unreachable. + // + // FIMXE: It looks sufficient to test + // isLookupResultEntirelyExternalOrUnreachable here. But due to bug we have + // to test isLookupResultExternal here. See + // https://github.com/llvm/llvm-project/issues/61065 for details. + if ((GeneratingReducedBMI || isLookupResultExternal(Result, DC)) && + isLookupResultEntirelyExternalOrUnreachable(Result, DC)) continue; // We also skip empty results. If any of the results could be external and @@ -4206,9 +4236,15 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, continue; } - for (NamedDecl *ND : Result) - if (!ND->isFromASTFile()) - GetDeclRef(ND); + for (NamedDecl *ND : Result) { + if (ND->isFromASTFile()) + continue; + + if (DoneWritingDeclsAndTypes && !wasDeclEmitted(ND)) + continue; + + GetDeclRef(ND); + } } return 0; @@ -4976,9 +5012,18 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); // Force all top level declarations to be emitted. - for (const auto *D : TU->noload_decls()) - if (!D->isFromASTFile()) - GetDeclRef(D); + // + // We start emitting top level declarations from the module purview to + // implement the eliding unreachable declaration feature. + for (const auto *D : TU->noload_decls()) { + if (D->isFromASTFile()) + continue; + + if (GeneratingReducedBMI && D->isFromExplicitGlobalModule()) + continue; + + GetDeclRef(D); + } // If the translation unit has an anonymous namespace, and we don't already // have an update block for it, write it as an update block. @@ -5288,24 +5333,59 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { WriteDecl(Context, DOT.getDecl()); } } while (!DeclUpdates.empty()); - Stream.ExitBlock(); DoneWritingDeclsAndTypes = true; + // DelayedNamespace is only meaningful in reduced BMI. + // See the comments of DelayedNamespace for details. + assert(DelayedNamespace.empty() || GeneratingReducedBMI); + RecordData DelayedNamespaceRecord; + for (NamespaceDecl *NS : DelayedNamespace) { + uint64_t LexicalOffset = WriteDeclContextLexicalBlock(Context, NS); + uint64_t VisibleOffset = WriteDeclContextVisibleBlock(Context, NS); + + // Write the offset relative to current block. + if (LexicalOffset) + LexicalOffset -= DeclTypesBlockStartOffset; + + if (VisibleOffset) + VisibleOffset -= DeclTypesBlockStartOffset; + + DelayedNamespaceRecord.push_back(getDeclID(NS)); + DelayedNamespaceRecord.push_back(LexicalOffset); + DelayedNamespaceRecord.push_back(VisibleOffset); + } + + // The process of writing lexical and visible block for delayed namespace + // shouldn't introduce any new decls, types or update to emit. + assert(DeclTypesToEmit.empty()); + assert(DeclUpdates.empty()); + + Stream.ExitBlock(); + // These things can only be done once we've written out decls and types. WriteTypeDeclOffsets(); if (!DeclUpdatesOffsetsRecord.empty()) Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); + if (!DelayedNamespaceRecord.empty()) + Stream.EmitRecord(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD, + DelayedNamespaceRecord); + const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); // Create a lexical update block containing all of the declarations in the // translation unit that do not come from other AST files. SmallVector NewGlobalKindDeclPairs; for (const auto *D : TU->noload_decls()) { - if (!D->isFromASTFile()) { - NewGlobalKindDeclPairs.push_back(D->getKind()); - NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); - } + if (D->isFromASTFile()) + continue; + + // In reduced BMI, skip unreached declarations. + if (!wasDeclEmitted(D)) + continue; + + NewGlobalKindDeclPairs.push_back(D->getKind()); + NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); } auto Abv = std::make_shared(); @@ -5814,6 +5894,21 @@ DeclID ASTWriter::getDeclID(const Decl *D) { return DeclIDs[D]; } +bool ASTWriter::wasDeclEmitted(const Decl *D) const { + assert(D); + + assert(DoneWritingDeclsAndTypes && + "wasDeclEmitted should only be called after writing declarations"); + + if (D->isFromASTFile()) + return true; + + bool Emitted = DeclIDs.contains(D); + assert((Emitted || GeneratingReducedBMI) && + "The declaration can only be omitted in reduced BMI."); + return Emitted; +} + void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { assert(ID); assert(D); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 87e773be54fa..4b417909751f 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1719,6 +1719,15 @@ void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (D->isFirstDecl()) AddTemplateSpecializations(D); + + // Force emitting the corresponding deduction guide in reduced BMI mode. + // Otherwise, the deduction guide may be optimized out incorrectly. + if (Writer.isGeneratingReducedBMI()) { + auto Name = Context.DeclarationNames.getCXXDeductionGuideName(D); + for (auto *DG : D->getDeclContext()->noload_lookup(Name)) + Writer.GetDeclRef(DG); + } + Code = serialization::DECL_CLASS_TEMPLATE; } @@ -1963,8 +1972,22 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { "You need to update the serializer after you change the " "DeclContextBits"); - Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC)); - Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC)); + uint64_t LexicalOffset = 0; + uint64_t VisibleOffset = 0; + + if (Writer.isGeneratingReducedBMI() && isa(DC) && + cast(DC)->isFromExplicitGlobalModule()) { + // In reduced BMI, delay writing lexical and visible block for namespace + // in the global module fragment. See the comments of DelayedNamespace for + // details. + Writer.DelayedNamespace.push_back(cast(DC)); + } else { + LexicalOffset = Writer.WriteDeclContextLexicalBlock(Context, DC); + VisibleOffset = Writer.WriteDeclContextVisibleBlock(Context, DC); + } + + Record.AddOffset(LexicalOffset); + Record.AddOffset(VisibleOffset); } const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) { diff --git a/clang/test/CXX/module/module.glob.frag/cxx20-10-4-ex2.cppm b/clang/test/CXX/module/module.glob.frag/cxx20-10-4-ex2.cppm new file mode 100644 index 000000000000..edb208cdf4de --- /dev/null +++ b/clang/test/CXX/module/module.glob.frag/cxx20-10-4-ex2.cppm @@ -0,0 +1,58 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 %t/std-10-4-ex2-interface.cppm -emit-reduced-module-interface \ +// RUN: -o %t/M.pcm -Wno-unused-value +// RUN: %clang_cc1 -std=c++20 %t/std-10-4-ex2-implementation.cpp -fmodule-file=M=%t/M.pcm \ +// RUN: -fsyntax-only -verify -Wno-unused-value + +//--- std-10-4-ex2.h + +namespace N { +struct X {}; +int d(); +int e(); +inline int f(X, int = d()) { return e(); } +int g(X); +int h(X); +} // namespace N + +//--- std-10-4-ex2-interface.cppm +module; +#include "std-10-4-ex2.h" +export module M; + +template int use_f() { + N::X x; // N::X, N, and :: are decl-reachable from use_f + return f(x, 123); // N::f is decl-reachable from use_f, + // N::e is indirectly decl-reachable from use_f + // because it is decl-reachable from N::f, and + // N::d is decl-reachable from use_f + // because it is decl-reachable from N::f + // even though it is not used in this call +} + +template int use_g() { + N::X x; // N::X, N, and :: are decl-reachable from use_g + return g((T(), x)); // N::g is not decl-reachable from use_g +} + +template int use_h() { + N::X x; // N::X, N, and :: are decl-reachable from use_h + return h((T(), x)); // N::h is not decl-reachable from use_h, but + // N::h is decl-reachable from use_h +} + +int k = use_h(); +// use_h is decl-reachable from k, so +// N::h is decl-reachable from k + +//--- std-10-4-ex2-implementation.cpp +module M; + +int a = use_f(); +int b = use_g(); +// expected-error@std-10-4-ex2-interface.cppm:17 {{use of undeclared identifier 'g'}} +// expected-note@-2 {{in instantiation of function template specialization 'use_g' requested here}} +int c = use_h(); diff --git a/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm b/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm index 3991e47ce215..eaf033d1d928 100644 --- a/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm +++ b/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm @@ -26,6 +26,10 @@ module; #include "C.h" export module B; +namespace foo { + export using foo::bar; +} + //--- C.h namespace foo { template struct bar { // expected-error {{declaration of 'bar' in module baz:A follows declaration in the global module}} // expected-note {{previous declaration is here}} @@ -40,6 +44,10 @@ module; #include "E.h" export module D; +namespace foo { + export using foo::bar; +} + //--- D-part.cppm export module D:part; import D; diff --git a/clang/test/Modules/named-modules-adl-2.cppm b/clang/test/Modules/named-modules-adl-2.cppm index a14b9a68d74e..88f58d85bc7c 100644 --- a/clang/test/Modules/named-modules-adl-2.cppm +++ b/clang/test/Modules/named-modules-adl-2.cppm @@ -7,7 +7,7 @@ // RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -fsyntax-only -verify // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm -// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -emit-reduced-module-interface -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -emit-reduced-module-interface -o %t/b.pcm -DREDUCED // RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -fsyntax-only -verify //--- a.cppm @@ -35,6 +35,11 @@ void b() { a(s()); } +#ifdef REDUCED +// Mention it to avoid the compiler optimizing it out. +using ::operator+; +#endif + //--- c.cppm // expected-no-diagnostics export module c; diff --git a/clang/test/Modules/named-modules-adl.cppm b/clang/test/Modules/named-modules-adl.cppm index ef250023f91e..079d816200b2 100644 --- a/clang/test/Modules/named-modules-adl.cppm +++ b/clang/test/Modules/named-modules-adl.cppm @@ -5,7 +5,7 @@ // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -fsyntax-only -verify -// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm -DREDUCED // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -fsyntax-only -verify //--- a.h @@ -28,6 +28,11 @@ void a(T x) { n::s() + x; } +#ifdef REDUCED +// Use it to make sure it is not optimized out in reduced BMI. +using n::operator+; +#endif + //--- b.cppm // expected-no-diagnostics export module b; diff --git a/clang/test/Modules/placement-new-reachable.cpp b/clang/test/Modules/placement-new-reachable.cpp index 6b495a60306b..244029470474 100644 --- a/clang/test/Modules/placement-new-reachable.cpp +++ b/clang/test/Modules/placement-new-reachable.cpp @@ -31,12 +31,17 @@ private: void *ptr; }; +// The use of operator new in the current module unit is only in the non-inline +// function definitions. So it may be optimized out. +using ::operator new; + //--- Use.cpp // expected-no-diagnostics import A; void bar(int *); void foo(void *ptr) { - A(nullptr); // Good. It should be OK to construct A. - void *p = ::operator new(sizeof(int), ptr); // Bad. The function shouldn't be visible here. + A a(nullptr); // Good. It should be OK to construct A. + B b(nullptr); + void *p = ::operator new(sizeof(int), ptr); // Bad. The placement allocation in module A is not visible. void *q = new (ptr) int(43); // Good. We don't call the placement allocation function directly. } diff --git a/clang/test/Modules/polluted-operator.cppm b/clang/test/Modules/polluted-operator.cppm index 2179fa098064..45cc5e37d6a6 100644 --- a/clang/test/Modules/polluted-operator.cppm +++ b/clang/test/Modules/polluted-operator.cppm @@ -12,7 +12,8 @@ // RUN: -emit-module-interface -DSKIP_ODR_CHECK_IN_GMF -o %t/b.pcm -verify // RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/a.cppm -o %t/a.pcm -// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -emit-reduced-module-interface -o %t/b.pcm -verify +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -emit-reduced-module-interface \ +// RUN: -o %t/b.pcm -verify -DREDUCED //--- foo.h @@ -53,18 +54,26 @@ module; #include "foo.h" #include "bar.h" export module a; +export namespace std { + using std::variant; + using std::_Traits; + using std::operator&&; +} //--- b.cppm module; #include "bar.h" export module b; import a; +export namespace std { + using std::variant; + using std::_Traits; + using std::operator&&; +} #ifdef SKIP_ODR_CHECK_IN_GMF // expected-no-diagnostics #else // expected-error@* {{has different definitions in different modules; first difference is defined here found data member '_S_copy_ctor' with an initializer}} // expected-note@* {{but in 'a.' found data member '_S_copy_ctor' with a different initializer}} -// expected-error@* {{from module 'a.' is not present in definition of 'variant<_Types...>' provided earlier}} -// expected-note@* {{declaration of 'swap' does not match}} #endif diff --git a/clang/test/Modules/pr62589.cppm b/clang/test/Modules/pr62589.cppm index c5aec3ed8184..54f2ecef22e1 100644 --- a/clang/test/Modules/pr62589.cppm +++ b/clang/test/Modules/pr62589.cppm @@ -73,6 +73,10 @@ export module a; export using ::a; export using ::a_view; +// We need to mention the 'operator==' explicitly to make sure it won't be +// discarded. +export using ::operator==; + //--- b.cpp // expected-no-diagnostics import a; diff --git a/clang/test/Modules/preferred_name.cppm b/clang/test/Modules/preferred_name.cppm index 2f1705867845..806781a81c5c 100644 --- a/clang/test/Modules/preferred_name.cppm +++ b/clang/test/Modules/preferred_name.cppm @@ -42,6 +42,7 @@ inline foo_templ bar() module; #include "foo.h" export module A; +export using ::foo_templ; //--- Use.cppm // expected-no-diagnostics @@ -49,6 +50,7 @@ module; #include "foo.h" export module Use; import A; +export using ::foo_templ; //--- Use1.cpp import A; // expected-warning@foo.h:8 {{attribute declaration must precede definition}} diff --git a/clang/test/Modules/redundant-template-default-arg3.cpp b/clang/test/Modules/redundant-template-default-arg3.cpp index e4464c40e976..da6fe01a5357 100644 --- a/clang/test/Modules/redundant-template-default-arg3.cpp +++ b/clang/test/Modules/redundant-template-default-arg3.cpp @@ -91,6 +91,16 @@ int v9; module; #include "foo.h" export module foo; +export using ::v; +export using ::v2; +export using ::my_array; +export using ::v3; +export using ::v4; +export using ::v5; +export using ::v6; +export using ::v7; +export using ::v8; +export using ::v9; //--- use.cpp import foo; diff --git a/clang/test/Modules/template-function-specialization.cpp b/clang/test/Modules/template-function-specialization.cpp index 1b6bf2de6ba1..d5d7d7e81239 100644 --- a/clang/test/Modules/template-function-specialization.cpp +++ b/clang/test/Modules/template-function-specialization.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only // RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/foo.cppm -o %t/foo.pcm -// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only -DREDUCED //--- foo.cppm module; @@ -51,10 +51,16 @@ import foo; void use() { foo(); foo(); +#ifdef REDUCED + // In reduced BMI, the foo2 template function is optimized out. + foo2(); // expected-error {{use of undeclared identifier 'foo2'}} + foo2(); // expected-error {{use of undeclared identifier 'foo2'}} +#else foo2(); // expected-error {{missing '#include'; 'foo2' must be declared before it is used}} // expected-note@* {{declaration here is not visible}} foo2(); // expected-error {{missing '#include'; 'foo2' must be declared before it is used}} // expected-note@* {{declaration here is not visible}} +#endif foo3(); foo3(); -- GitLab From 506ff547924ab81123865964b7d998a5a378330a Mon Sep 17 00:00:00 2001 From: NimishMishra <42909663+NimishMishra@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:12:14 -0700 Subject: [PATCH 032/464] [flang][Semantics] Fix updating flags of threadprivate symbols in presence of default clause (#78283) Current semantic checks of default clause incorrectly update symbol flags related to threadprivate symbols. This patch adds an additional check to skip such updation should a symbol be already declared threadprivate. Fixes https://github.com/llvm/llvm-project/issues/78282 --- flang/lib/Semantics/resolve-directives.cpp | 5 ++++ flang/test/Lower/OpenMP/default-clause.f90 | 29 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 27af192f606b..f4ac7f198d85 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -2021,6 +2021,11 @@ void OmpAttributeVisitor::Post(const parser::Name &name) { } } } + + if (Symbol * found{currScope().FindSymbol(name.source)}) { + if (found->test(semantics::Symbol::Flag::OmpThreadprivate)) + return; + } std::vector defaultDSASymbols; for (int dirDepth{0}; dirDepth < (int)dirContext_.size(); ++dirDepth) { DirContext &dirContext = dirContext_[dirDepth]; diff --git a/flang/test/Lower/OpenMP/default-clause.f90 b/flang/test/Lower/OpenMP/default-clause.f90 index f86b51aef4e0..9a47e561338f 100644 --- a/flang/test/Lower/OpenMP/default-clause.f90 +++ b/flang/test/Lower/OpenMP/default-clause.f90 @@ -383,3 +383,32 @@ subroutine skipped_default_clause_checks() iii=it(11) !$omp end parallel end subroutine + +!CHECK: func.func @_QPthreadprivate_with_default() { +!CHECK: %[[VAR_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFthreadprivate_with_defaultEi"} +!CHECK: %[[VAR_I_DECLARE:.*]] = hlfir.declare %[[VAR_I]] {uniq_name = "_QFthreadprivate_with_defaultEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[BLK_ADDR:.*]] = fir.address_of(@blk_) : !fir.ref> +!CHECK: %[[BLK_THREADPRIVATE_OUTER:.*]] = omp.threadprivate %[[BLK_ADDR]] : !fir.ref> -> !fir.ref> +!CHECK: %[[CONVERT:.*]] = fir.convert %[[BLK_THREADPRIVATE_OUTER]] : (!fir.ref>) -> !fir.ref> +!CHECK: %[[VAR_C:.*]] = arith.constant 0 : index +!CHECK: %[[BLK_REF:.*]] = fir.coordinate_of %[[CONVERT]], %[[VAR_C]] : (!fir.ref>, index) -> !fir.ref +!CHECK: %[[CONVERT:.*]] = fir.convert %[[BLK_REF]] : (!fir.ref) -> !fir.ref +!CHECK: %[[VAR_X_DECLARE:.*]] = hlfir.declare %[[CONVERT]] {uniq_name = "_QFthreadprivate_with_defaultEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: omp.parallel { +!CHECK: %[[BLK_THREADPRIVATE_INNER:.*]] = omp.threadprivate %[[BLK_ADDR]] : !fir.ref> -> !fir.ref> +!CHECK: %[[CONVERT_INNER:.*]] = fir.convert %[[BLK_THREADPRIVATE_INNER]] : (!fir.ref>) -> !fir.ref> +!CHECK: %[[VAR_C_INNER:.*]] = arith.constant 0 : index +!CHECK: %[[BLK_REF_INNER:.*]] = fir.coordinate_of %[[CONVERT_INNER]], %[[VAR_C_INNER]] : (!fir.ref>, index) -> !fir.ref +!CHECK: %[[CONVERT_INNER:.*]] = fir.convert %[[BLK_REF_INNER]] : (!fir.ref) -> !fir.ref +!CHECK: %[[VAR_X_DECLARE_INNER:.*]] = hlfir.declare %[[CONVERT_INNER]] {uniq_name = "_QFthreadprivate_with_defaultEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +subroutine threadprivate_with_default + integer :: x + common /blk/ x + !$omp threadprivate (/blk/) + + !$omp parallel do default(private) + do i = 1, 4 + x = 4 + end do + !$omp end parallel do +end subroutine -- GitLab From b502dc596ba3ed1e857e163e21ed6426125760ef Mon Sep 17 00:00:00 2001 From: Sirraide Date: Fri, 12 Apr 2024 07:12:57 +0200 Subject: [PATCH 033/464] [Clang] Fix test broken due to unsupported calling convention (#88472) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #88428 ended up breaking CI because it included a test that uses the `regcall` calling convention, which isn’t supported on all targets; I’ve moved it into a separate file that sets the triple. --- clang/test/SemaCXX/gh84473.cpp | 11 +++++++++++ clang/test/SemaCXX/lambda-expressions.cpp | 9 --------- 2 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 clang/test/SemaCXX/gh84473.cpp diff --git a/clang/test/SemaCXX/gh84473.cpp b/clang/test/SemaCXX/gh84473.cpp new file mode 100644 index 000000000000..72f5e9c45b0c --- /dev/null +++ b/clang/test/SemaCXX/gh84473.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 -fsyntax-only -verify %s +// expected-no-diagnostics + +namespace GH84473_bug { +void f1() { + int b; + (void) [=] [[gnu::regcall]] () { + (void) b; + }; +} +} diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 6be338064452..151d74f21d64 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -762,12 +762,3 @@ template auto t::operator()(int a) const; // expected-note {{in instantiati } #endif - -namespace GH84473_bug { -void f1() { - int b; - (void) [=] [[gnu::regcall]] () { // expected-warning {{an attribute specifier sequence in this position is a C++23 extension}} - (void) b; - }; -} -} -- GitLab From 469758c944dfb492102ded9e50eac5e478f85f6a Mon Sep 17 00:00:00 2001 From: Dominik Adamski Date: Fri, 12 Apr 2024 09:11:26 +0200 Subject: [PATCH 034/464] [Flang] Add options frtlib-add-rpath and resource-dir (#88280) frtlib-add-rpath option is used by clang and should also be visible in flang. It is already handled by the toolchains used by both clang and flang. Reported issue: https://github.com/llvm/llvm-project/issues/82553 --- clang/include/clang/Driver/Options.td | 6 ++-- clang/lib/Driver/ToolChains/Flang.cpp | 4 +++ .../Driver/arch-specific-libdir-rpath.f95 | 32 +++++++++++++++++++ flang/test/Driver/driver-help-hidden.f90 | 3 ++ flang/test/Driver/driver-help.f90 | 2 ++ 5 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 flang/test/Driver/arch-specific-libdir-rpath.f95 diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 7ac36222644a..400f72f2250a 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5464,21 +5464,23 @@ def rdynamic : Flag<["-"], "rdynamic">, Group, Visibility<[ClangOption, FlangOption]>; def resource_dir : Separate<["-"], "resource-dir">, Flags<[NoXarchOption, HelpHidden]>, - Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, + Visibility<[ClangOption, CC1Option, CLOption, DXCOption, FlangOption, FC1Option]>, HelpText<"The directory which holds the compiler resource files">, MarshallingInfoString>; def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[NoXarchOption]>, - Visibility<[ClangOption, CLOption, DXCOption]>, + Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Alias; def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; def rtlib_EQ : Joined<["-", "--"], "rtlib=">, Visibility<[ClangOption, CLOption]>, HelpText<"Compiler runtime library to use">; def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>, + Visibility<[ClangOption, FlangOption]>, HelpText<"Add -rpath with architecture-specific resource directory to the linker flags. " "When --hip-link is specified, also add -rpath with HIP runtime library directory to the linker flags">; def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">, Flags<[NoArgumentUnused]>, + Visibility<[ClangOption, FlangOption]>, HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags. " "When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags">; def offload_add_rpath: Flag<["--"], "offload-add-rpath">, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index b00068c8098b..b46bac24503c 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -786,6 +786,10 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, } } + // Pass the path to compiler resource files. + CmdArgs.push_back("-resource-dir"); + CmdArgs.push_back(D.ResourceDir.c_str()); + // Offloading related options addOffloadOptions(C, Inputs, JA, Args, CmdArgs); diff --git a/flang/test/Driver/arch-specific-libdir-rpath.f95 b/flang/test/Driver/arch-specific-libdir-rpath.f95 new file mode 100644 index 000000000000..cc09938f7d1e --- /dev/null +++ b/flang/test/Driver/arch-specific-libdir-rpath.f95 @@ -0,0 +1,32 @@ +! REQUIRES: x86-registered-target +! Test that the driver adds an arch-specific subdirectory in +! {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath' +! +! Test the default behavior when neither -frtlib-add-rpath nor +! -fno-rtlib-add-rpath is specified, which is to skip -rpath +! RUN: %flang %s -### --target=x86_64-linux \ +! RUN: -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_arch_subdir 2>&1 \ +! RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s +! +! Test that -rpath is not added under -fno-rtlib-add-rpath +! RUN: %flang %s -### --target=x86_64-linux \ +! RUN: -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_arch_subdir \ +! RUN: -fno-rtlib-add-rpath 2>&1 \ +! RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s +! +! Test that -rpath is added +! +! Add LIBPATH, RPATH for OpenMP +! +! RUN: %flang %s -### --target=x86_64-linux -fopenmp \ +! RUN: -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_arch_subdir \ +! RUN: -frtlib-add-rpath 2>&1 \ +! RUN: | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s +! +! +! RESDIR: "-resource-dir" "[[RESDIR:[^"]*]]" +! +! LIBPATH-X86_64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}} +! RPATH-X86_64: "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}" +! +! NO-RPATH-X86_64-NOT: "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}" diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90 index 35b188ad3a9e..eb00949c2a95 100644 --- a/flang/test/Driver/driver-help-hidden.f90 +++ b/flang/test/Driver/driver-help-hidden.f90 @@ -68,6 +68,7 @@ ! CHECK-NEXT: -fno-lto Disable LTO mode (default) ! CHECK-NEXT: -fno-ppc-native-vector-element-order ! CHECK-NEXT: Specifies PowerPC non-native vector element order +! CHECK-NEXT: -fno-rtlib-add-rpath Do not add -rpath with architecture-specific resource directory to the linker flags. When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags ! CHECK-NEXT: -fno-signed-zeros Allow optimizations that ignore the sign of floating point zeros ! CHECK-NEXT: -fno-stack-arrays Allocate array temporaries on the heap (default) ! CHECK-NEXT: -fno-version-loops-for-stride @@ -93,6 +94,7 @@ ! CHECK-NEXT: Specifies PowerPC native vector element order (default) ! CHECK-NEXT: -freciprocal-math Allow division operations to be reassociated ! CHECK-NEXT: -fropi Generate read-only position independent code (ARM only) +! CHECK-NEXT: -frtlib-add-rpath Add -rpath with architecture-specific resource directory to the linker flags. When --hip-link is specified, also add -rpath with HIP runtime library directory to the linker flags ! CHECK-NEXT: -frwpi Generate read-write position independent code (ARM only) ! CHECK-NEXT: -fsave-optimization-record= ! CHECK-NEXT: Generate an optimization record file in a specific format @@ -145,6 +147,7 @@ ! CHECK-NEXT: -print-target-triple Print the normalized target triple ! CHECK-NEXT: -pthread Support POSIX threads in generated code ! CHECK-NEXT: -P Disable linemarker output in -E mode +! CHECK-NEXT: -resource-dir The directory which holds the compiler resource files ! CHECK-NEXT: -Rpass-analysis= Report transformation analysis from optimization passes whose name matches the given POSIX regular expression ! CHECK-NEXT: -Rpass-missed= Report missed transformations by optimization passes whose name matches the given POSIX regular expression ! CHECK-NEXT: -Rpass= Report transformations performed by optimization passes whose name matches the given POSIX regular expression diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 index d4dab55f40e8..05f50ea348c2 100644 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -60,6 +60,7 @@ ! HELP-NEXT: -fno-lto Disable LTO mode (default) ! HELP-NEXT: -fno-ppc-native-vector-element-order ! HELP-NEXT: Specifies PowerPC non-native vector element order +! HELP-NEXT: -fno-rtlib-add-rpath Do not add -rpath with architecture-specific resource directory to the linker flags. When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags ! HELP-NEXT: -fno-signed-zeros Allow optimizations that ignore the sign of floating point zeros ! HELP-NEXT: -fno-stack-arrays Allocate array temporaries on the heap (default) ! HELP-NEXT: -fno-version-loops-for-stride @@ -81,6 +82,7 @@ ! HELP-NEXT: Specifies PowerPC native vector element order (default) ! HELP-NEXT: -freciprocal-math Allow division operations to be reassociated ! HELP-NEXT: -fropi Generate read-only position independent code (ARM only) +! HELP-NEXT: -frtlib-add-rpath Add -rpath with architecture-specific resource directory to the linker flags. When --hip-link is specified, also add -rpath with HIP runtime library directory to the linker flags ! HELP-NEXT: -frwpi Generate read-write position independent code (ARM only) ! HELP-NEXT: -fsave-optimization-record= ! HELP-NEXT: Generate an optimization record file in a specific format -- GitLab From 1b8830c56abd01c9ab70bbbb71a00c2506cf2116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 12 Apr 2024 08:52:18 +0200 Subject: [PATCH 035/464] [clang][Interp] Fix comparing to integral function pointers We need to account for the fact that the Function pointer is not accessible here. Add FunctionPointer::isWeak() for that. --- clang/lib/AST/Interp/FunctionPointer.h | 6 ++++++ clang/lib/AST/Interp/Interp.h | 2 +- clang/test/AST/Interp/c.c | 10 ++++++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/Interp/FunctionPointer.h b/clang/lib/AST/Interp/FunctionPointer.h index 840c1101f396..c2ea295b82bd 100644 --- a/clang/lib/AST/Interp/FunctionPointer.h +++ b/clang/lib/AST/Interp/FunctionPointer.h @@ -32,6 +32,12 @@ public: const Function *getFunction() const { return Func; } bool isZero() const { return !Func; } + bool isWeak() const { + if (!Func || !Valid) + return false; + + return Func->getDecl()->isWeak(); + } APValue toAPValue() const { if (!Func) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index c7012aa4ec68..4182254357eb 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -758,7 +758,7 @@ inline bool CmpHelperEQ(InterpState &S, CodePtr OpPC, // We cannot compare against weak declarations at compile time. for (const auto &FP : {LHS, RHS}) { - if (!FP.isZero() && FP.getFunction()->getDecl()->isWeak()) { + if (FP.isWeak()) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison) << FP.toDiagnosticString(S.getCtx()); diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index cdecd3e83a99..e0b18120fd21 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-linux -fexperimental-new-constant-interpreter -verify=expected,all -std=c11 -Wcast-qual %s -// RUN: %clang_cc1 -triple x86_64-linux -fexperimental-new-constant-interpreter -pedantic -verify=pedantic-expected,all -std=c11 -Wcast-qual %s +// RUN: %clang_cc1 -triple x86_64-linux -fexperimental-new-constant-interpreter -pedantic -verify=pedantic,pedantic-expected,all -std=c11 -Wcast-qual %s // RUN: %clang_cc1 -triple x86_64-linux -verify=ref,all -std=c11 -Wcast-qual %s -// RUN: %clang_cc1 -triple x86_64-linux -pedantic -verify=pedantic-ref,all -std=c11 -Wcast-qual %s +// RUN: %clang_cc1 -triple x86_64-linux -pedantic -verify=pedantic,pedantic-ref,all -std=c11 -Wcast-qual %s typedef __INTPTR_TYPE__ intptr_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; @@ -227,3 +227,9 @@ int castViaInt[*(int*)(unsigned long)"test"]; // ref-error {{variable length arr // pedantic-ref-error {{variable length array}} \ // expected-error {{variable length array}} \ // pedantic-expected-error {{variable length array}} + +const void (*const funcp)(void) = (void*)123; // pedantic-warning {{converts between void pointer and function pointer}} +_Static_assert(funcp == (void*)0, ""); // all-error {{failed due to requirement 'funcp == (void *)0'}} \ + // pedantic-warning {{expression is not an integer constant expression}} +_Static_assert(funcp == (void*)123, ""); // pedantic-warning {{equality comparison between function pointer and void pointer}} \ + // pedantic-warning {{expression is not an integer constant expression}} -- GitLab From ff9bc3a0fa4e3790c437e62450903bf399df37f9 Mon Sep 17 00:00:00 2001 From: Johannes Reifferscheid Date: Fri, 12 Apr 2024 09:42:04 +0200 Subject: [PATCH 036/464] Fix overflows in complex sqrt lowering. (#88480) This ports XLA's complex sqrt lowering. The accuracy was tested with its exhaustive_unary_test_complex test. Note: rsqrt is still broken. --- .../ComplexToStandard/ComplexToStandard.cpp | 166 ++++++---- .../convert-to-standard.mlir | 296 +++++++++++------- .../ComplexToStandard/full-conversion.mlir | 2 +- 3 files changed, 280 insertions(+), 184 deletions(-) diff --git a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp index 9c82e8105f06..0664b053fc9e 100644 --- a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp +++ b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp @@ -27,35 +27,52 @@ using namespace mlir; namespace { +// Returns the absolute value or its square root. +Value computeAbs(Value real, Value imag, arith::FastMathFlags fmf, + ImplicitLocOpBuilder &b, bool returnSqrt = false) { + Value one = b.create(real.getType(), + b.getFloatAttr(real.getType(), 1.0)); + + Value absReal = b.create(real, fmf); + Value absImag = b.create(imag, fmf); + + Value max = b.create(absReal, absImag, fmf); + Value min = b.create(absReal, absImag, fmf); + Value ratio = b.create(min, max, fmf); + Value ratioSq = b.create(ratio, ratio, fmf); + Value ratioSqPlusOne = b.create(ratioSq, one, fmf); + Value result; + + if (returnSqrt) { + Value quarter = b.create( + real.getType(), b.getFloatAttr(real.getType(), 0.25)); + // sqrt(sqrt(a*b)) would avoid the pow, but will overflow more easily. + Value sqrt = b.create(max, fmf); + Value p025 = b.create(ratioSqPlusOne, quarter, fmf); + result = b.create(sqrt, p025, fmf); + } else { + Value sqrt = b.create(ratioSqPlusOne, fmf); + result = b.create(max, sqrt, fmf); + } + + Value isNaN = + b.create(arith::CmpFPredicate::UNO, result, result, fmf); + return b.create(isNaN, min, result); +} + struct AbsOpConversion : public OpConversionPattern { using OpConversionPattern::OpConversionPattern; LogicalResult matchAndRewrite(complex::AbsOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - mlir::ImplicitLocOpBuilder b(op.getLoc(), rewriter); + ImplicitLocOpBuilder b(op.getLoc(), rewriter); arith::FastMathFlags fmf = op.getFastMathFlagsAttr().getValue(); - Type elementType = op.getType(); - Value one = b.create(elementType, - b.getFloatAttr(elementType, 1.0)); - Value real = b.create(adaptor.getComplex()); Value imag = b.create(adaptor.getComplex()); - Value absReal = b.create(real, fmf); - Value absImag = b.create(imag, fmf); - - Value max = b.create(absReal, absImag, fmf); - Value min = b.create(absReal, absImag, fmf); - Value ratio = b.create(min, max, fmf); - Value ratioSq = b.create(ratio, ratio, fmf); - Value ratioSqPlusOne = b.create(ratioSq, one, fmf); - Value sqrt = b.create(ratioSqPlusOne, fmf); - Value result = b.create(max, sqrt, fmf); - Value isNaN = - b.create(arith::CmpFPredicate::UNO, result, result, fmf); - rewriter.replaceOpWithNewOp(op, isNaN, min, result); + rewriter.replaceOp(op, computeAbs(real, imag, fmf, b)); return success(); } @@ -829,60 +846,71 @@ struct SqrtOpConversion : public OpConversionPattern { LogicalResult matchAndRewrite(complex::SqrtOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { - mlir::ImplicitLocOpBuilder b(op.getLoc(), rewriter); + ImplicitLocOpBuilder b(op.getLoc(), rewriter); auto type = cast(op.getType()); - Type elementType = type.getElementType(); - Value arg = adaptor.getComplex(); - arith::FastMathFlagsAttr fmf = op.getFastMathFlagsAttr(); - - Value zero = - b.create(elementType, b.getZeroAttr(elementType)); - - Value real = b.create(elementType, adaptor.getComplex()); - Value imag = b.create(elementType, adaptor.getComplex()); - - Value absLhs = b.create(real, fmf); - Value absArg = b.create(elementType, arg, fmf); - Value addAbs = b.create(absLhs, absArg, fmf); + auto elementType = type.getElementType().cast(); + arith::FastMathFlags fmf = op.getFastMathFlagsAttr().getValue(); + auto cst = [&](APFloat v) { + return b.create(elementType, + b.getFloatAttr(elementType, v)); + }; + const auto &floatSemantics = elementType.getFloatSemantics(); + Value zero = cst(APFloat::getZero(floatSemantics)); Value half = b.create(elementType, b.getFloatAttr(elementType, 0.5)); - Value halfAddAbs = b.create(addAbs, half, fmf); - Value sqrtAddAbs = b.create(halfAddAbs, fmf); - - Value realIsNegative = - b.create(arith::CmpFPredicate::OLT, real, zero); - Value imagIsNegative = - b.create(arith::CmpFPredicate::OLT, imag, zero); - - Value resultReal = sqrtAddAbs; - - Value imagDivTwoResultReal = b.create( - imag, b.create(resultReal, resultReal, fmf), fmf); - - Value negativeResultReal = b.create(resultReal); + Value real = b.create(elementType, adaptor.getComplex()); + Value imag = b.create(elementType, adaptor.getComplex()); + Value absSqrt = computeAbs(real, imag, fmf, b, /*returnSqrt=*/true); + Value argArg = b.create(imag, real, fmf); + Value sqrtArg = b.create(argArg, half, fmf); + Value cos = b.create(sqrtArg, fmf); + Value sin = b.create(sqrtArg, fmf); + // sin(atan2(0, inf)) = 0, sqrt(abs(inf)) = inf, but we can't multiply + // 0 * inf. + Value sinIsZero = + b.create(arith::CmpFPredicate::OEQ, sin, zero, fmf); + + Value resultReal = b.create(absSqrt, cos, fmf); Value resultImag = b.create( - realIsNegative, - b.create(imagIsNegative, negativeResultReal, - resultReal), - imagDivTwoResultReal); - - resultReal = b.create( - realIsNegative, - b.create( - imag, b.create(resultImag, resultImag, fmf), fmf), - resultReal); - - Value realIsZero = - b.create(arith::CmpFPredicate::OEQ, real, zero); - Value imagIsZero = - b.create(arith::CmpFPredicate::OEQ, imag, zero); - Value argIsZero = b.create(realIsZero, imagIsZero); - - resultReal = b.create(argIsZero, zero, resultReal); - resultImag = b.create(argIsZero, zero, resultImag); + sinIsZero, zero, b.create(absSqrt, sin, fmf)); + if (!arith::bitEnumContainsAll(fmf, arith::FastMathFlags::nnan | + arith::FastMathFlags::ninf)) { + Value inf = cst(APFloat::getInf(floatSemantics)); + Value negInf = cst(APFloat::getInf(floatSemantics, true)); + Value nan = cst(APFloat::getNaN(floatSemantics)); + Value absImag = b.create(elementType, imag, fmf); + + Value absImagIsInf = + b.create(arith::CmpFPredicate::OEQ, absImag, inf, fmf); + Value absImagIsNotInf = + b.create(arith::CmpFPredicate::ONE, absImag, inf, fmf); + Value realIsInf = + b.create(arith::CmpFPredicate::OEQ, real, inf, fmf); + Value realIsNegInf = + b.create(arith::CmpFPredicate::OEQ, real, negInf, fmf); + + resultReal = b.create( + b.create(realIsNegInf, absImagIsNotInf), zero, + resultReal); + resultReal = b.create( + b.create(absImagIsInf, realIsInf), inf, resultReal); + + Value imagSignInf = b.create(inf, imag, fmf); + resultImag = b.create( + b.create(arith::CmpFPredicate::UNO, absSqrt, absSqrt), + nan, resultImag); + resultImag = b.create( + b.create(absImagIsInf, realIsNegInf), imagSignInf, + resultImag); + } + + Value resultIsZero = + b.create(arith::CmpFPredicate::OEQ, absSqrt, zero, fmf); + resultReal = b.create(resultIsZero, zero, resultReal); + resultImag = b.create(resultIsZero, zero, resultImag); rewriter.replaceOpWithNewOp(op, type, resultReal, resultImag); @@ -1065,7 +1093,7 @@ static Value powOpConversionImpl(mlir::ImplicitLocOpBuilder &builder, // Case 2: // 1^(c + d*i) = 1 + 0*i Value lhsEqOne = builder.create( - builder.create(arith::CmpFPredicate::OEQ, a, one), + builder.create(arith::CmpFPredicate::OEQ, a, one, fmf), bEqZero); Value cutoff2 = builder.create(lhsEqOne, complexOne, cutoff1); @@ -1073,11 +1101,11 @@ static Value powOpConversionImpl(mlir::ImplicitLocOpBuilder &builder, // Case 3: // inf^(c + 0*i) = inf + 0*i, c > 0 Value lhsEqInf = builder.create( - builder.create(arith::CmpFPredicate::OEQ, a, inf), + builder.create(arith::CmpFPredicate::OEQ, a, inf, fmf), bEqZero); Value rhsGt0 = builder.create( dEqZero, - builder.create(arith::CmpFPredicate::OGT, c, zero)); + builder.create(arith::CmpFPredicate::OGT, c, zero, fmf)); Value cutoff3 = builder.create( builder.create(lhsEqInf, rhsGt0), complexInf, cutoff2); @@ -1085,7 +1113,7 @@ static Value powOpConversionImpl(mlir::ImplicitLocOpBuilder &builder, // inf^(c + 0*i) = 0 + 0*i, c < 0 Value rhsLt0 = builder.create( dEqZero, - builder.create(arith::CmpFPredicate::OLT, c, zero)); + builder.create(arith::CmpFPredicate::OLT, c, zero, fmf)); Value cutoff4 = builder.create( builder.create(lhsEqInf, rhsLt0), complexZero, cutoff3); diff --git a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir index 8d2fb09daa87..b22c1acacaea 100644 --- a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir +++ b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir @@ -8,9 +8,9 @@ func.func @complex_abs(%arg: complex) -> f32 { return %abs : f32 } -// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[REAL:.*]] = complex.re %[[ARG]] : complex // CHECK: %[[IMAG:.*]] = complex.im %[[ARG]] : complex +// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL]] : f32 // CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] : f32 // CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] : f32 @@ -250,9 +250,9 @@ func.func @complex_log(%arg: complex) -> complex { %log = complex.log %arg: complex return %log : complex } -// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[REAL:.*]] = complex.re %[[ARG]] : complex // CHECK: %[[IMAG:.*]] = complex.im %[[ARG]] : complex +// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL]] : f32 // CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] : f32 // CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] : f32 @@ -493,9 +493,9 @@ func.func @complex_sign(%arg: complex) -> complex { // CHECK: %[[REAL_IS_ZERO:.*]] = arith.cmpf oeq, %[[REAL]], %[[ZERO]] : f32 // CHECK: %[[IMAG_IS_ZERO:.*]] = arith.cmpf oeq, %[[IMAG]], %[[ZERO]] : f32 // CHECK: %[[IS_ZERO:.*]] = arith.andi %[[REAL_IS_ZERO]], %[[IMAG_IS_ZERO]] : i1 -// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[REAL2:.*]] = complex.re %[[ARG]] : complex // CHECK: %[[IMAG2:.*]] = complex.im %[[ARG]] : complex +// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL2]] : f32 // CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG2]] : f32 // CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] : f32 @@ -697,45 +697,95 @@ func.func @complex_sqrt(%arg: complex) -> complex { return %sqrt : complex } -// CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 -// CHECK: %[[VAR0:.*]] = complex.re %[[ARG]] : complex -// CHECK: %[[VAR1:.*]] = complex.im %[[ARG]] : complex -// CHECK: %[[VAR2:.*]] = math.absf %[[VAR0]] : f32 +// CHECK: %[[ZERO:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[HALF:.*]] = arith.constant 5.000000e-01 : f32 +// CHECK: %[[RE:.*]] = complex.re %[[ARG]] : complex +// CHECK: %[[IM:.*]] = complex.im %[[ARG]] : complex // CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 -// CHECK: %[[REAL:.*]] = complex.re %[[ARG]] : complex -// CHECK: %[[IMAG:.*]] = complex.im %[[ARG]] : complex -// CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL]] : f32 -// CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] : f32 -// CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] : f32 -// CHECK: %[[MIN:.*]] = arith.minimumf %[[ABS_REAL]], %[[ABS_IMAG]] : f32 +// CHECK: %[[ABSRE:.*]] = math.absf %[[RE]] : f32 +// CHECK: %[[ABSIM:.*]] = math.absf %[[IM]] : f32 +// CHECK: %[[MAX:.*]] = arith.maximumf %[[ABSRE]], %[[ABSIM]] : f32 +// CHECK: %[[MIN:.*]] = arith.minimumf %[[ABSRE]], %[[ABSIM]] : f32 // CHECK: %[[RATIO:.*]] = arith.divf %[[MIN]], %[[MAX]] : f32 // CHECK: %[[RATIO_SQ:.*]] = arith.mulf %[[RATIO]], %[[RATIO]] : f32 // CHECK: %[[RATIO_SQ_PLUS_ONE:.*]] = arith.addf %[[RATIO_SQ]], %[[ONE]] : f32 -// CHECK: %[[SQRT:.*]] = math.sqrt %[[RATIO_SQ_PLUS_ONE]] : f32 -// CHECK: %[[ABS_OR_NAN:.*]] = arith.mulf %[[MAX]], %[[SQRT]] : f32 -// CHECK: %[[IS_NAN:.*]] = arith.cmpf uno, %[[ABS_OR_NAN]], %[[ABS_OR_NAN]] : f32 -// CHECK: %[[ABS:.*]] = arith.select %[[IS_NAN]], %[[MIN]], %[[ABS_OR_NAN]] : f32 -// CHECK: %[[VAR23:.*]] = arith.addf %[[VAR2]], %[[ABS]] : f32 -// CHECK: %[[CST2:.*]] = arith.constant 5.000000e-01 : f32 -// CHECK: %[[VAR24:.*]] = arith.mulf %[[VAR23]], %[[CST2]] : f32 -// CHECK: %[[VAR25:.*]] = math.sqrt %[[VAR24]] : f32 -// CHECK: %[[VAR26:.*]] = arith.cmpf olt, %[[VAR0]], %cst : f32 -// CHECK: %[[VAR27:.*]] = arith.cmpf olt, %[[VAR1]], %cst : f32 -// CHECK: %[[VAR28:.*]] = arith.addf %[[VAR25]], %[[VAR25]] : f32 -// CHECK: %[[VAR29:.*]] = arith.divf %[[VAR1]], %[[VAR28]] : f32 -// CHECK: %[[VAR30:.*]] = arith.negf %[[VAR25]] : f32 -// CHECK: %[[VAR31:.*]] = arith.select %[[VAR27]], %[[VAR30]], %[[VAR25]] : f32 -// CHECK: %[[VAR32:.*]] = arith.select %[[VAR26]], %[[VAR31]], %[[VAR29]] : f32 -// CHECK: %[[VAR33:.*]] = arith.addf %[[VAR32]], %[[VAR32]] : f32 -// CHECK: %[[VAR34:.*]] = arith.divf %[[VAR1]], %[[VAR33]] : f32 -// CHECK: %[[VAR35:.*]] = arith.select %[[VAR26]], %[[VAR34]], %[[VAR25]] : f32 -// CHECK: %[[VAR36:.*]] = arith.cmpf oeq, %[[VAR0]], %cst : f32 -// CHECK: %[[VAR37:.*]] = arith.cmpf oeq, %[[VAR1]], %cst : f32 -// CHECK: %[[VAR38:.*]] = arith.andi %[[VAR36]], %[[VAR37]] : i1 -// CHECK: %[[VAR39:.*]] = arith.select %[[VAR38]], %cst, %[[VAR35]] : f32 -// CHECK: %[[VAR40:.*]] = arith.select %[[VAR38]], %cst, %[[VAR32]] : f32 -// CHECK: %[[VAR41:.*]] = complex.create %[[VAR39]], %[[VAR40]] : complex -// CHECK: return %[[VAR41]] : complex +// CHECK: %[[QUARTER:.*]] = arith.constant 2.500000e-01 : f32 +// CHECK: %[[SQRT_MAX:.*]] = math.sqrt %[[MAX]] : f32 +// CHECK: %[[POW:.*]] = math.powf %[[RATIO_SQ_PLUS_ONE]], %[[QUARTER]] : f32 +// CHECK: %[[SQRT_ABS_OR_NAN:.*]] = arith.mulf %[[SQRT_MAX]], %[[POW]] : f32 +// CHECK: %[[IS_NAN:.*]] = arith.cmpf uno, %[[SQRT_ABS_OR_NAN]], %[[SQRT_ABS_OR_NAN]] : f32 +// CHECK: %[[SQRT_ABS:.*]] = arith.select %[[IS_NAN]], %[[MIN]], %[[SQRT_ABS_OR_NAN]] : f32 +// CHECK: %[[ARGARG:.*]] = math.atan2 %[[IM]], %[[RE]] : f32 +// CHECK: %[[SQRTARG:.*]] = arith.mulf %[[ARGARG]], %[[HALF]] : f32 +// CHECK: %[[COS:.*]] = math.cos %[[SQRTARG]] : f32 +// CHECK: %[[SIN:.*]] = math.sin %[[SQRTARG]] : f32 +// CHECK: %[[SIN_ZERO:.*]] = arith.cmpf oeq, %[[SIN]], %[[ZERO]] : f32 +// CHECK: %[[RESULT_RE:.*]] = arith.mulf %[[SQRT_ABS]], %[[COS]] : f32 +// CHECK: %[[RESULT_IM:.*]] = arith.mulf %[[SQRT_ABS]], %[[SIN]] : f32 +// CHECK: %[[RESULT_IM2:.*]] = arith.select %[[SIN_ZERO]], %[[ZERO]], %[[RESULT_IM]] : f32 +// CHECK: %[[INF:.*]] = arith.constant 0x7F800000 : f32 +// CHECK: %[[NINF:.*]] = arith.constant 0xFF800000 : f32 +// CHECK: %[[NAN:.*]] = arith.constant 0x7FC00000 : f32 +// CHECK: %[[ABSIM:.*]] = math.absf %[[IM]] : f32 +// CHECK: %[[ABSIMINF:.*]] = arith.cmpf oeq, %[[ABSIM]], %[[INF]] : f32 +// CHECK: %[[ABSIMNOTINF:.*]] = arith.cmpf one, %[[ABSIM]], %[[INF]] : f32 +// CHECK: %[[REINF:.*]] = arith.cmpf oeq, %[[RE]], %[[INF]] : f32 +// CHECK: %[[RENINF:.*]] = arith.cmpf oeq, %[[RE]], %[[NINF]] : f32 +// CHECK: %[[RESULT_RE_ZERO:.*]] = arith.andi %[[RENINF]], %[[ABSIMNOTINF]] : i1 +// CHECK: %[[RESULT_RE2:.*]] = arith.select %[[RESULT_RE_ZERO]], %[[ZERO]], %[[RESULT_RE]] : f32 +// CHECK: %[[RESUL_IM_INF:.*]] = arith.ori %[[ABSIMINF]], %[[REINF]] : i1 +// CHECK: %[[RESULT_RE3:.*]] = arith.select %[[RESUL_IM_INF]], %[[INF]], %[[RESULT_RE2]] : f32 +// CHECK: %[[INF_IM_SIGN:.*]] = math.copysign %[[INF]], %[[IM]] : f32 +// CHECK: %[[RESULT_IM_NAN:.*]] = arith.cmpf uno, %[[SQRT_ABS]], %[[SQRT_ABS]] : f32 +// CHECK: %[[RESULT_IM3:.*]] = arith.select %[[RESULT_IM_NAN]], %[[NAN]], %[[RESULT_IM2]] : f32 +// CHECK: %[[RESULT_IM_INF:.*]] = arith.ori %[[ABSIMINF]], %[[RENINF]] : i1 +// CHECK: %[[RESULT_IM4:.*]] = arith.select %[[RESULT_IM_INF]], %[[INF_IM_SIGN]], %[[RESULT_IM3]] : f32 +// CHECK: %[[RESULT_ZERO:.*]] = arith.cmpf oeq, %[[SQRT_ABS]], %[[ZERO]] : f32 +// CHECK: %[[RESULT_RE4:.*]] = arith.select %[[RESULT_ZERO]], %[[ZERO]], %[[RESULT_RE3]] : f32 +// CHECK: %[[RESULT_IM5:.*]] = arith.select %[[RESULT_ZERO]], %[[ZERO]], %[[RESULT_IM4]] : f32 +// CHECK: %[[RESULT:.*]] = complex.create %[[RESULT_RE4]], %[[RESULT_IM5]] : complex +// CHECK: return %[[RESULT]] : complex + +// ----- + +// CHECK-LABEL: func @complex_sqrt_nnan_ninf +// CHECK-SAME: %[[ARG:.*]]: complex +func.func @complex_sqrt_nnan_ninf(%arg: complex) -> complex { + %sqrt = complex.sqrt %arg fastmath : complex + return %sqrt : complex +} + +// CHECK: %[[ZERO:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[HALF:.*]] = arith.constant 5.000000e-01 : f32 +// CHECK: %[[RE:.*]] = complex.re %[[ARG]] : complex +// CHECK: %[[IM:.*]] = complex.im %[[ARG]] : complex +// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[ABSRE:.*]] = math.absf %[[RE]] fastmath : f32 +// CHECK: %[[ABSIM:.*]] = math.absf %[[IM]] fastmath : f32 +// CHECK: %[[MAX:.*]] = arith.maximumf %[[ABSRE]], %[[ABSIM]] fastmath : f32 +// CHECK: %[[MIN:.*]] = arith.minimumf %[[ABSRE]], %[[ABSIM]] fastmath : f32 +// CHECK: %[[RATIO:.*]] = arith.divf %[[MIN]], %[[MAX]] fastmath : f32 +// CHECK: %[[RATIO_SQ:.*]] = arith.mulf %[[RATIO]], %[[RATIO]] fastmath : f32 +// CHECK: %[[RATIO_SQ_PLUS_ONE:.*]] = arith.addf %[[RATIO_SQ]], %[[ONE]] fastmath : f32 +// CHECK: %[[QUARTER:.*]] = arith.constant 2.500000e-01 : f32 +// CHECK: %[[SQRT_MAX:.*]] = math.sqrt %[[MAX]] fastmath : f32 +// CHECK: %[[POW:.*]] = math.powf %[[RATIO_SQ_PLUS_ONE]], %[[QUARTER]] fastmath : f32 +// CHECK: %[[SQRT_ABS_OR_NAN:.*]] = arith.mulf %[[SQRT_MAX]], %[[POW]] fastmath : f32 +// CHECK: %[[IS_NAN:.*]] = arith.cmpf uno, %[[SQRT_ABS_OR_NAN]], %[[SQRT_ABS_OR_NAN]] fastmath : f32 +// CHECK: %[[SQRT_ABS:.*]] = arith.select %[[IS_NAN]], %[[MIN]], %[[SQRT_ABS_OR_NAN]] : f32 +// CHECK: %[[ARGARG:.*]] = math.atan2 %[[IM]], %[[RE]] fastmath : f32 +// CHECK: %[[SQRTARG:.*]] = arith.mulf %[[ARGARG]], %[[HALF]] fastmath : f32 +// CHECK: %[[COS:.*]] = math.cos %[[SQRTARG]] fastmath : f32 +// CHECK: %[[SIN:.*]] = math.sin %[[SQRTARG]] fastmath : f32 +// CHECK: %[[SIN_ZERO:.*]] = arith.cmpf oeq, %[[SIN]], %[[ZERO]] fastmath : f32 +// CHECK: %[[RESULT_RE:.*]] = arith.mulf %[[SQRT_ABS]], %[[COS]] fastmath : f32 +// CHECK: %[[RESULT_IM:.*]] = arith.mulf %[[SQRT_ABS]], %[[SIN]] fastmath : f32 +// CHECK: %[[RESULT_IM2:.*]] = arith.select %[[SIN_ZERO]], %[[ZERO]], %[[RESULT_IM]] : f32 +// CHECK: %[[RESULT_ZERO:.*]] = arith.cmpf oeq, %[[SQRT_ABS]], %[[ZERO]] fastmath : f32 +// CHECK: %[[RESULT_RE2:.*]] = arith.select %[[RESULT_ZERO]], %[[ZERO]], %[[RESULT_RE]] : f32 +// CHECK: %[[RESULT_IM3:.*]] = arith.select %[[RESULT_ZERO]], %[[ZERO]], %[[RESULT_IM2]] : f32 +// CHECK: %[[RESULT:.*]] = complex.create %[[RESULT_RE2]], %[[RESULT_IM3]] : complex +// CHECK: return %[[RESULT]] : complex // ----- @@ -808,9 +858,9 @@ func.func @complex_abs_with_fmf(%arg: complex) -> f32 { %abs = complex.abs %arg fastmath : complex return %abs : f32 } -// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[REAL:.*]] = complex.re %[[ARG]] : complex // CHECK: %[[IMAG:.*]] = complex.im %[[ARG]] : complex +// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL]] fastmath : f32 // CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] fastmath : f32 // CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] fastmath : f32 @@ -907,9 +957,9 @@ func.func @complex_log_with_fmf(%arg: complex) -> complex { %log = complex.log %arg fastmath : complex return %log : complex } -// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[REAL:.*]] = complex.re %[[ARG]] : complex // CHECK: %[[IMAG:.*]] = complex.im %[[ARG]] : complex +// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL]] fastmath : f32 // CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] fastmath : f32 // CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] fastmath : f32 @@ -1285,44 +1335,53 @@ func.func @complex_atan2_with_fmf(%lhs: complex, // CHECK: %[[VAR184:.*]] = complex.im %[[VAR179]] : complex // CHECK: %[[VAR185:.*]] = arith.addf %[[VAR183]], %[[VAR184]] fastmath : f32 // CHECK: %[[VAR186:.*]] = complex.create %[[VAR182]], %[[VAR185]] : complex -// CHECK: %[[CST_6:.*]] = arith.constant 0.000000e+00 : f32 -// CHECK: %[[VAR187:.*]] = complex.re %[[VAR186]] : complex -// CHECK: %[[VAR188:.*]] = complex.im %[[VAR186]] : complex -// CHECK: %[[VAR189:.*]] = math.absf %[[VAR187]] fastmath : f32 +// CHECK: %[[ZERO:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[HALF:.*]] = arith.constant 5.000000e-01 : f32 +// CHECK: %[[RE:.*]] = complex.re %[[VAR186]] : complex +// CHECK: %[[IM:.*]] = complex.im %[[VAR186]] : complex // CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 -// CHECK: %[[REAL:.*]] = complex.re %[[VAR186]] : complex -// CHECK: %[[IMAG:.*]] = complex.im %[[VAR186]] : complex -// CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL]] fastmath : f32 -// CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] fastmath : f32 -// CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] fastmath : f32 -// CHECK: %[[MIN:.*]] = arith.minimumf %[[ABS_REAL]], %[[ABS_IMAG]] fastmath : f32 -// CHECK: %[[RATIO:.*]] = arith.divf %[[MIN]], %[[MAX]] fastmath : f32 -// CHECK: %[[RATIO_SQ:.*]] = arith.mulf %[[RATIO]], %[[RATIO]] fastmath : f32 -// CHECK: %[[RATIO_SQ_PLUS_ONE:.*]] = arith.addf %[[RATIO_SQ]], %[[ONE]] fastmath : f32 -// CHECK: %[[SQRT:.*]] = math.sqrt %[[RATIO_SQ_PLUS_ONE]] fastmath : f32 -// CHECK: %[[ABS_OR_NAN:.*]] = arith.mulf %[[MAX]], %[[SQRT]] fastmath : f32 -// CHECK: %[[IS_NAN:.*]] = arith.cmpf uno, %[[ABS_OR_NAN]], %[[ABS_OR_NAN]] fastmath : f32 -// CHECK: %[[ABS:.*]] = arith.select %[[IS_NAN]], %[[MIN]], %[[ABS_OR_NAN]] : f32 -// CHECK: %[[VAR210:.*]] = arith.addf %[[VAR189]], %[[ABS]] fastmath : f32 -// CHECK: %[[CST_9:.*]] = arith.constant 5.000000e-01 : f32 -// CHECK: %[[VAR211:.*]] = arith.mulf %[[VAR210]], %[[CST_9]] fastmath : f32 -// CHECK: %[[VAR212:.*]] = math.sqrt %[[VAR211]] fastmath : f32 -// CHECK: %[[VAR213:.*]] = arith.cmpf olt, %[[VAR187]], %[[CST_6]] : f32 -// CHECK: %[[VAR214:.*]] = arith.cmpf olt, %[[VAR188]], %[[CST_6]] : f32 -// CHECK: %[[VAR215:.*]] = arith.addf %[[VAR212]], %[[VAR212]] fastmath : f32 -// CHECK: %[[VAR216:.*]] = arith.divf %[[VAR188]], %[[VAR215]] fastmath : f32 -// CHECK: %[[VAR217:.*]] = arith.negf %[[VAR212]] : f32 -// CHECK: %[[VAR218:.*]] = arith.select %[[VAR214]], %[[VAR217]], %[[VAR212]] : f32 -// CHECK: %[[VAR219:.*]] = arith.select %[[VAR213]], %[[VAR218]], %[[VAR216]] : f32 -// CHECK: %[[VAR220:.*]] = arith.addf %[[VAR219]], %[[VAR219]] fastmath : f32 -// CHECK: %[[VAR221:.*]] = arith.divf %[[VAR188]], %[[VAR220]] fastmath : f32 -// CHECK: %[[VAR222:.*]] = arith.select %[[VAR213]], %[[VAR221]], %[[VAR212]] : f32 -// CHECK: %[[VAR223:.*]] = arith.cmpf oeq, %[[VAR187]], %[[CST_6]] : f32 -// CHECK: %[[VAR224:.*]] = arith.cmpf oeq, %[[VAR188]], %[[CST_6]] : f32 -// CHECK: %[[VAR225:.*]] = arith.andi %[[VAR223]], %[[VAR224]] : i1 -// CHECK: %[[VAR226:.*]] = arith.select %[[VAR225]], %[[CST_6]], %[[VAR222]] : f32 -// CHECK: %[[VAR227:.*]] = arith.select %[[VAR225]], %[[CST_6]], %[[VAR219]] : f32 -// CHECK: %[[VAR228:.*]] = complex.create %[[VAR226]], %[[VAR227]] : complex +// CHECK: %[[ABSRE:.*]] = math.absf %[[RE]] fastmath : f32 +// CHECK: %[[ABSIM:.*]] = math.absf %[[IM]] fastmath : f32 +// CHECK: %[[MAX:.*]] = arith.maximumf %[[ABSRE]], %[[ABSIM]] fastmath : f32 +// CHECK: %[[MIN:.*]] = arith.minimumf %[[ABSRE]], %[[ABSIM]] fastmath : f32 +// CHECK: %[[RATIO:.*]] = arith.divf %[[MIN]], %[[MAX]] fastmath : f32 +// CHECK: %[[RATIO_SQ:.*]] = arith.mulf %[[RATIO]], %[[RATIO]] fastmath : f32 +// CHECK: %[[RATIO_SQ_PLUS_ONE:.*]] = arith.addf %[[RATIO_SQ]], %[[ONE]] fastmath : f32 +// CHECK: %[[QUARTER:.*]] = arith.constant 2.500000e-01 : f32 +// CHECK: %[[SQRT_MAX:.*]] = math.sqrt %[[MAX]] fastmath : f32 +// CHECK: %[[POW:.*]] = math.powf %[[RATIO_SQ_PLUS_ONE]], %[[QUARTER]] fastmath : f32 +// CHECK: %[[SQRT_ABS_OR_NAN:.*]] = arith.mulf %[[SQRT_MAX]], %[[POW]] fastmath : f32 +// CHECK: %[[IS_NAN:.*]] = arith.cmpf uno, %[[SQRT_ABS_OR_NAN]], %[[SQRT_ABS_OR_NAN]] fastmath : f32 +// CHECK: %[[SQRT_ABS:.*]] = arith.select %[[IS_NAN]], %[[MIN]], %[[SQRT_ABS_OR_NAN]] : f32 +// CHECK: %[[ARGARG:.*]] = math.atan2 %[[IM]], %[[RE]] fastmath : f32 +// CHECK: %[[SQRTARG:.*]] = arith.mulf %[[ARGARG]], %[[HALF]] fastmath : f32 +// CHECK: %[[COS:.*]] = math.cos %[[SQRTARG]] fastmath : f32 +// CHECK: %[[SIN:.*]] = math.sin %[[SQRTARG]] fastmath : f32 +// CHECK: %[[SIN_ZERO:.*]] = arith.cmpf oeq, %[[SIN]], %[[ZERO]] fastmath : f32 +// CHECK: %[[RESULT_RE:.*]] = arith.mulf %[[SQRT_ABS]], %[[COS]] fastmath : f32 +// CHECK: %[[RESULT_IM:.*]] = arith.mulf %[[SQRT_ABS]], %[[SIN]] fastmath : f32 +// CHECK: %[[RESULT_IM2:.*]] = arith.select %[[SIN_ZERO]], %[[ZERO]], %[[RESULT_IM]] : f32 +// CHECK: %[[INF:.*]] = arith.constant 0x7F800000 : f32 +// CHECK: %[[NINF:.*]] = arith.constant 0xFF800000 : f32 +// CHECK: %[[NAN:.*]] = arith.constant 0x7FC00000 : f32 +// CHECK: %[[ABSIM:.*]] = math.absf %[[IM]] fastmath : f32 +// CHECK: %[[ABSIMINF:.*]] = arith.cmpf oeq, %[[ABSIM]], %[[INF]] fastmath : f32 +// CHECK: %[[ABSIMNOTINF:.*]] = arith.cmpf one, %[[ABSIM]], %[[INF]] fastmath : f32 +// CHECK: %[[REINF:.*]] = arith.cmpf oeq, %[[RE]], %[[INF]] fastmath : f32 +// CHECK: %[[RENINF:.*]] = arith.cmpf oeq, %[[RE]], %[[NINF]] fastmath : f32 +// CHECK: %[[RESULT_RE_ZERO:.*]] = arith.andi %[[RENINF]], %[[ABSIMNOTINF]] : i1 +// CHECK: %[[RESULT_RE2:.*]] = arith.select %[[RESULT_RE_ZERO]], %[[ZERO]], %[[RESULT_RE]] : f32 +// CHECK: %[[RESUL_IM_INF:.*]] = arith.ori %[[ABSIMINF]], %[[REINF]] : i1 +// CHECK: %[[RESULT_RE3:.*]] = arith.select %[[RESUL_IM_INF]], %[[INF]], %[[RESULT_RE2]] : f32 +// CHECK: %[[INF_IM_SIGN:.*]] = math.copysign %[[INF]], %[[IM]] fastmath : f32 +// CHECK: %[[RESULT_IM_NAN:.*]] = arith.cmpf uno, %[[SQRT_ABS]], %[[SQRT_ABS]] : f32 +// CHECK: %[[RESULT_IM3:.*]] = arith.select %[[RESULT_IM_NAN]], %[[NAN]], %[[RESULT_IM2]] : f32 +// CHECK: %[[RESULT_IM_INF:.*]] = arith.ori %[[ABSIMINF]], %[[RENINF]] : i1 +// CHECK: %[[RESULT_IM4:.*]] = arith.select %[[RESULT_IM_INF]], %[[INF_IM_SIGN]], %[[RESULT_IM3]] : f32 +// CHECK: %[[RESULT_ZERO:.*]] = arith.cmpf oeq, %[[SQRT_ABS]], %[[ZERO]] fastmath : f32 +// CHECK: %[[RESULT_RE4:.*]] = arith.select %[[RESULT_ZERO]], %[[ZERO]], %[[RESULT_RE3]] : f32 +// CHECK: %[[RESULT_IM5:.*]] = arith.select %[[RESULT_ZERO]], %[[ZERO]], %[[RESULT_IM4]] : f32 +// CHECK: %[[VAR228:.*]] = complex.create %[[RESULT_RE4]], %[[RESULT_IM5]] : complex // CHECK: %[[CST_10:.*]] = arith.constant 0.000000e+00 : f32 // CHECK: %[[CST_11:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[VAR229:.*]] = complex.create %[[CST_10]], %[[CST_11]] : complex @@ -1519,9 +1578,9 @@ func.func @complex_atan2_with_fmf(%lhs: complex, // CHECK: %[[VAR413:.*]] = arith.select %[[VAR412]], %[[VAR408]], %[[VAR402]] : f32 // CHECK: %[[VAR414:.*]] = arith.select %[[VAR412]], %[[VAR409]], %[[VAR403]] : f32 // CHECK: %[[VAR415:.*]] = complex.create %[[VAR413]], %[[VAR414]] : complex -// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[REAL:.*]] = complex.re %[[VAR415]] : complex // CHECK: %[[IMAG:.*]] = complex.im %[[VAR415]] : complex +// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL]] fastmath : f32 // CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] fastmath : f32 // CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] fastmath : f32 @@ -1756,45 +1815,54 @@ func.func @complex_sqrt_with_fmf(%arg: complex) -> complex { return %sqrt : complex } -// CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 -// CHECK: %[[VAR0:.*]] = complex.re %[[ARG]] : complex -// CHECK: %[[VAR1:.*]] = complex.im %[[ARG]] : complex -// CHECK: %[[VAR2:.*]] = math.absf %[[VAR0]] fastmath : f32 +// CHECK: %[[ZERO:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[HALF:.*]] = arith.constant 5.000000e-01 : f32 +// CHECK: %[[RE:.*]] = complex.re %[[ARG]] : complex +// CHECK: %[[IM:.*]] = complex.im %[[ARG]] : complex // CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 -// CHECK: %[[REAL:.*]] = complex.re %[[ARG]] : complex -// CHECK: %[[IMAG:.*]] = complex.im %[[ARG]] : complex -// CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL]] fastmath : f32 -// CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] fastmath : f32 -// CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] fastmath : f32 -// CHECK: %[[MIN:.*]] = arith.minimumf %[[ABS_REAL]], %[[ABS_IMAG]] fastmath : f32 +// CHECK: %[[ABSRE:.*]] = math.absf %[[RE]] fastmath : f32 +// CHECK: %[[ABSIM:.*]] = math.absf %[[IM]] fastmath : f32 +// CHECK: %[[MAX:.*]] = arith.maximumf %[[ABSRE]], %[[ABSIM]] fastmath : f32 +// CHECK: %[[MIN:.*]] = arith.minimumf %[[ABSRE]], %[[ABSIM]] fastmath : f32 // CHECK: %[[RATIO:.*]] = arith.divf %[[MIN]], %[[MAX]] fastmath : f32 // CHECK: %[[RATIO_SQ:.*]] = arith.mulf %[[RATIO]], %[[RATIO]] fastmath : f32 // CHECK: %[[RATIO_SQ_PLUS_ONE:.*]] = arith.addf %[[RATIO_SQ]], %[[ONE]] fastmath : f32 -// CHECK: %[[SQRT:.*]] = math.sqrt %[[RATIO_SQ_PLUS_ONE]] fastmath : f32 -// CHECK: %[[ABS_OR_NAN:.*]] = arith.mulf %[[MAX]], %[[SQRT]] fastmath : f32 -// CHECK: %[[IS_NAN:.*]] = arith.cmpf uno, %[[ABS_OR_NAN]], %[[ABS_OR_NAN]] fastmath : f32 -// CHECK: %[[ABS:.*]] = arith.select %[[IS_NAN]], %[[MIN]], %[[ABS_OR_NAN]] : f32 -// CHECK: %[[VAR23:.*]] = arith.addf %[[VAR2]], %[[ABS]] fastmath : f32 -// CHECK: %[[CST2:.*]] = arith.constant 5.000000e-01 : f32 -// CHECK: %[[VAR24:.*]] = arith.mulf %[[VAR23]], %[[CST2]] fastmath : f32 -// CHECK: %[[VAR25:.*]] = math.sqrt %[[VAR24]] fastmath : f32 -// CHECK: %[[VAR26:.*]] = arith.cmpf olt, %[[VAR0]], %cst : f32 -// CHECK: %[[VAR27:.*]] = arith.cmpf olt, %[[VAR1]], %cst : f32 -// CHECK: %[[VAR28:.*]] = arith.addf %[[VAR25]], %[[VAR25]] fastmath : f32 -// CHECK: %[[VAR29:.*]] = arith.divf %[[VAR1]], %[[VAR28]] fastmath : f32 -// CHECK: %[[VAR30:.*]] = arith.negf %[[VAR25]] : f32 -// CHECK: %[[VAR31:.*]] = arith.select %[[VAR27]], %[[VAR30]], %[[VAR25]] : f32 -// CHECK: %[[VAR32:.*]] = arith.select %[[VAR26]], %[[VAR31]], %[[VAR29]] : f32 -// CHECK: %[[VAR33:.*]] = arith.addf %[[VAR32]], %[[VAR32]] fastmath : f32 -// CHECK: %[[VAR34:.*]] = arith.divf %[[VAR1]], %[[VAR33]] fastmath : f32 -// CHECK: %[[VAR35:.*]] = arith.select %[[VAR26]], %[[VAR34]], %[[VAR25]] : f32 -// CHECK: %[[VAR36:.*]] = arith.cmpf oeq, %[[VAR0]], %cst : f32 -// CHECK: %[[VAR37:.*]] = arith.cmpf oeq, %[[VAR1]], %cst : f32 -// CHECK: %[[VAR38:.*]] = arith.andi %[[VAR36]], %[[VAR37]] : i1 -// CHECK: %[[VAR39:.*]] = arith.select %[[VAR38]], %cst, %[[VAR35]] : f32 -// CHECK: %[[VAR40:.*]] = arith.select %[[VAR38]], %cst, %[[VAR32]] : f32 -// CHECK: %[[VAR41:.*]] = complex.create %[[VAR39]], %[[VAR40]] : complex -// CHECK: return %[[VAR41]] : complex +// CHECK: %[[QUARTER:.*]] = arith.constant 2.500000e-01 : f32 +// CHECK: %[[SQRT_MAX:.*]] = math.sqrt %[[MAX]] fastmath : f32 +// CHECK: %[[POW:.*]] = math.powf %[[RATIO_SQ_PLUS_ONE]], %[[QUARTER]] fastmath : f32 +// CHECK: %[[SQRT_ABS_OR_NAN:.*]] = arith.mulf %[[SQRT_MAX]], %[[POW]] fastmath : f32 +// CHECK: %[[IS_NAN:.*]] = arith.cmpf uno, %[[SQRT_ABS_OR_NAN]], %[[SQRT_ABS_OR_NAN]] fastmath : f32 +// CHECK: %[[SQRT_ABS:.*]] = arith.select %[[IS_NAN]], %[[MIN]], %[[SQRT_ABS_OR_NAN]] : f32 +// CHECK: %[[ARGARG:.*]] = math.atan2 %[[IM]], %[[RE]] fastmath : f32 +// CHECK: %[[SQRTARG:.*]] = arith.mulf %[[ARGARG]], %[[HALF]] fastmath : f32 +// CHECK: %[[COS:.*]] = math.cos %[[SQRTARG]] fastmath : f32 +// CHECK: %[[SIN:.*]] = math.sin %[[SQRTARG]] fastmath : f32 +// CHECK: %[[SIN_ZERO:.*]] = arith.cmpf oeq, %[[SIN]], %[[ZERO]] fastmath : f32 +// CHECK: %[[RESULT_RE:.*]] = arith.mulf %[[SQRT_ABS]], %[[COS]] fastmath : f32 +// CHECK: %[[RESULT_IM:.*]] = arith.mulf %[[SQRT_ABS]], %[[SIN]] fastmath : f32 +// CHECK: %[[RESULT_IM2:.*]] = arith.select %[[SIN_ZERO]], %[[ZERO]], %[[RESULT_IM]] : f32 +// CHECK: %[[INF:.*]] = arith.constant 0x7F800000 : f32 +// CHECK: %[[NINF:.*]] = arith.constant 0xFF800000 : f32 +// CHECK: %[[NAN:.*]] = arith.constant 0x7FC00000 : f32 +// CHECK: %[[ABSIM:.*]] = math.absf %[[IM]] fastmath : f32 +// CHECK: %[[ABSIMINF:.*]] = arith.cmpf oeq, %[[ABSIM]], %[[INF]] fastmath : f32 +// CHECK: %[[ABSIMNOTINF:.*]] = arith.cmpf one, %[[ABSIM]], %[[INF]] fastmath : f32 +// CHECK: %[[REINF:.*]] = arith.cmpf oeq, %[[RE]], %[[INF]] fastmath : f32 +// CHECK: %[[RENINF:.*]] = arith.cmpf oeq, %[[RE]], %[[NINF]] fastmath : f32 +// CHECK: %[[RESULT_RE_ZERO:.*]] = arith.andi %[[RENINF]], %[[ABSIMNOTINF]] : i1 +// CHECK: %[[RESULT_RE2:.*]] = arith.select %[[RESULT_RE_ZERO]], %[[ZERO]], %[[RESULT_RE]] : f32 +// CHECK: %[[RESUL_IM_INF:.*]] = arith.ori %[[ABSIMINF]], %[[REINF]] : i1 +// CHECK: %[[RESULT_RE3:.*]] = arith.select %[[RESUL_IM_INF]], %[[INF]], %[[RESULT_RE2]] : f32 +// CHECK: %[[INF_IM_SIGN:.*]] = math.copysign %[[INF]], %[[IM]] fastmath : f32 +// CHECK: %[[RESULT_IM_NAN:.*]] = arith.cmpf uno, %[[SQRT_ABS]], %[[SQRT_ABS]] : f32 +// CHECK: %[[RESULT_IM3:.*]] = arith.select %[[RESULT_IM_NAN]], %[[NAN]], %[[RESULT_IM2]] : f32 +// CHECK: %[[RESULT_IM_INF:.*]] = arith.ori %[[ABSIMINF]], %[[RENINF]] : i1 +// CHECK: %[[RESULT_IM4:.*]] = arith.select %[[RESULT_IM_INF]], %[[INF_IM_SIGN]], %[[RESULT_IM3]] : f32 +// CHECK: %[[RESULT_ZERO:.*]] = arith.cmpf oeq, %[[SQRT_ABS]], %[[ZERO]] fastmath : f32 +// CHECK: %[[RESULT_RE4:.*]] = arith.select %[[RESULT_ZERO]], %[[ZERO]], %[[RESULT_RE3]] : f32 +// CHECK: %[[RESULT_IM5:.*]] = arith.select %[[RESULT_ZERO]], %[[ZERO]], %[[RESULT_IM4]] : f32 +// CHECK: %[[RESULT:.*]] = complex.create %[[RESULT_RE4]], %[[RESULT_IM5]] : complex +// CHECK: return %[[RESULT]] : complex // ----- @@ -1857,9 +1925,9 @@ func.func @complex_sign_with_fmf(%arg: complex) -> complex { // CHECK: %[[REAL_IS_ZERO:.*]] = arith.cmpf oeq, %[[REAL]], %[[ZERO]] : f32 // CHECK: %[[IMAG_IS_ZERO:.*]] = arith.cmpf oeq, %[[IMAG]], %[[ZERO]] : f32 // CHECK: %[[IS_ZERO:.*]] = arith.andi %[[REAL_IS_ZERO]], %[[IMAG_IS_ZERO]] : i1 -// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[REAL2:.*]] = complex.re %[[ARG]] : complex // CHECK: %[[IMAG2:.*]] = complex.im %[[ARG]] : complex +// CHECK: %[[ONE:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[ABS_REAL:.*]] = math.absf %[[REAL2]] fastmath : f32 // CHECK: %[[ABS_IMAG:.*]] = math.absf %[[IMAG2]] fastmath : f32 // CHECK: %[[MAX:.*]] = arith.maximumf %[[ABS_REAL]], %[[ABS_IMAG]] fastmath : f32 diff --git a/mlir/test/Conversion/ComplexToStandard/full-conversion.mlir b/mlir/test/Conversion/ComplexToStandard/full-conversion.mlir index 2649d004a76a..110a78631fb9 100644 --- a/mlir/test/Conversion/ComplexToStandard/full-conversion.mlir +++ b/mlir/test/Conversion/ComplexToStandard/full-conversion.mlir @@ -6,10 +6,10 @@ func.func @complex_abs(%arg: complex) -> f32 { %abs = complex.abs %arg: complex return %abs : f32 } -// CHECK: %[[ONE:.*]] = llvm.mlir.constant(1.000000e+00 : f32) : f32 // CHECK: %[[REAL:.*]] = llvm.extractvalue %[[ARG]][0] : ![[C_TY]] // CHECK: %[[IMAG:.*]] = llvm.extractvalue %[[ARG]][1] : ![[C_TY]] +// CHECK: %[[ONE:.*]] = llvm.mlir.constant(1.000000e+00 : f32) : f32 // CHECK: %[[ABS_REAL:.*]] = llvm.intr.fabs(%[[REAL]]) : (f32) -> f32 // CHECK: %[[ABS_IMAG:.*]] = llvm.intr.fabs(%[[IMAG]]) : (f32) -> f32 // CHECK: %[[MAX:.*]] = llvm.intr.maximum(%[[ABS_REAL]], %[[ABS_IMAG]]) : (f32, f32) -> f32 -- GitLab From 1e7763557bbace002b6bb811167942ebebf50f99 Mon Sep 17 00:00:00 2001 From: wanglei Date: Fri, 12 Apr 2024 16:15:02 +0800 Subject: [PATCH 037/464] [LoongArch] Add support for getNumberOfRegisters() (#88372) The `TTI` hooks are used during vectorization for calculating register pressure. The default implementation defined wrong value for register number (all register class are 8 registers). This patch also defines LoongArch's own register classes. --- .../LoongArchTargetTransformInfo.cpp | 41 +++++++++++++++++ .../LoongArch/LoongArchTargetTransformInfo.h | 4 ++ .../LoopVectorize/LoongArch/reg-usage.ll | 44 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 llvm/test/Transforms/LoopVectorize/LoongArch/reg-usage.ll diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp index d47dded9ea6e..add1c60d89d2 100644 --- a/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp @@ -40,4 +40,45 @@ TypeSize LoongArchTTIImpl::getRegisterBitWidth( llvm_unreachable("Unsupported register kind"); } +unsigned LoongArchTTIImpl::getNumberOfRegisters(unsigned ClassID) const { + switch (ClassID) { + case LoongArchRegisterClass::GPRRC: + // 30 = 32 GPRs - r0 (zero register) - r21 (non-allocatable) + return 30; + case LoongArchRegisterClass::FPRRC: + return ST->hasBasicF() ? 32 : 0; + case LoongArchRegisterClass::VRRC: + return ST->hasExtLSX() ? 32 : 0; + } + llvm_unreachable("unknown register class"); +} + +unsigned LoongArchTTIImpl::getRegisterClassForType(bool Vector, + Type *Ty) const { + if (Vector) + return LoongArchRegisterClass::VRRC; + if (!Ty) + return LoongArchRegisterClass::GPRRC; + + Type *ScalarTy = Ty->getScalarType(); + if ((ScalarTy->isFloatTy() && ST->hasBasicF()) || + (ScalarTy->isDoubleTy() && ST->hasBasicD())) { + return LoongArchRegisterClass::FPRRC; + } + + return LoongArchRegisterClass::GPRRC; +} + +const char *LoongArchTTIImpl::getRegisterClassName(unsigned ClassID) const { + switch (ClassID) { + case LoongArchRegisterClass::GPRRC: + return "LoongArch::GPRRC"; + case LoongArchRegisterClass::FPRRC: + return "LoongArch::FPRRC"; + case LoongArchRegisterClass::VRRC: + return "LoongArch::VRRC"; + } + llvm_unreachable("unknown register class"); +} + // TODO: Implement more hooks to provide TTI machinery for LoongArch. diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h b/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h index d296c9ed576f..34c18163bbdb 100644 --- a/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h +++ b/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.h @@ -28,6 +28,7 @@ class LoongArchTTIImpl : public BasicTTIImplBase { typedef TargetTransformInfo TTI; friend BaseT; + enum LoongArchRegisterClass { GPRRC, FPRRC, VRRC }; const LoongArchSubtarget *ST; const LoongArchTargetLowering *TLI; @@ -40,6 +41,9 @@ public: TLI(ST->getTargetLowering()) {} TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const; + unsigned getNumberOfRegisters(unsigned ClassID) const; + unsigned getRegisterClassForType(bool Vector, Type *Ty = nullptr) const; + const char *getRegisterClassName(unsigned ClassID) const; // TODO: Implement more hooks to provide TTI machinery for LoongArch. }; diff --git a/llvm/test/Transforms/LoopVectorize/LoongArch/reg-usage.ll b/llvm/test/Transforms/LoopVectorize/LoongArch/reg-usage.ll new file mode 100644 index 000000000000..f45a2f0f5b7e --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/LoongArch/reg-usage.ll @@ -0,0 +1,44 @@ +; REQUIRES: asserts +; RUN: opt --passes=loop-vectorize --mtriple loongarch64-linux-gnu \ +; RUN: --mattr=+lsx -debug-only=loop-vectorize --force-vector-width=1 \ +; RUN: -S < %s 2>&1 | FileCheck %s --check-prefix=CHECK-SCALAR +; RUN: opt --passes=loop-vectorize --mtriple loongarch64-linux-gnu \ +; RUN: --mattr=+lsx -debug-only=loop-vectorize --force-vector-width=4 \ +; RUN: -S < %s 2>&1 | FileCheck %s --check-prefix=CHECK-VECTOR + +define void @bar(ptr %A, i32 signext %n) { +; CHECK-LABEL: bar +; CHECK-SCALAR: LV(REG): Found max usage: 2 item +; CHECK-SCALAR-NEXT: LV(REG): RegisterClass: LoongArch::GPRRC, 2 registers +; CHECK-SCALAR-NEXT: LV(REG): RegisterClass: LoongArch::FPRRC, 1 registers +; CHECK-SCALAR-NEXT: LV(REG): Found invariant usage: 1 item +; CHECK-SCALAR-NEXT: LV(REG): RegisterClass: LoongArch::GPRRC, 1 registers +; CHECK-SCALAR-NEXT: LV: The target has 30 registers of LoongArch::GPRRC register class +; CHECK-SCALAR-NEXT: LV: The target has 32 registers of LoongArch::FPRRC register class +; CHECK-VECTOR: LV(REG): Found max usage: 1 item +; CHECK-VECTOR-NEXT: LV(REG): RegisterClass: LoongArch::VRRC, 3 registers +; CHECK-VECTOR-NEXT: LV(REG): Found invariant usage: 1 item +; CHECK-VECTOR-NEXT: LV(REG): RegisterClass: LoongArch::GPRRC, 1 registers +; CHECK-VECTOR-NEXT: LV: The target has 32 registers of LoongArch::VRRC register class + +entry: + %cmp4 = icmp sgt i32 %n, 0 + br i1 %cmp4, label %for.body.preheader, label %for.cond.cleanup + +for.body.preheader: ; preds = %entry + %wide.trip.count = zext nneg i32 %n to i64 + br label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + ret void + +for.body: ; preds = %for.body.preheader, %for.body + %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] + %0 = trunc i64 %indvars.iv to i32 + %conv = sitofp i32 %0 to float + %arrayidx = getelementptr inbounds float, ptr %A, i64 %indvars.iv + store float %conv, ptr %arrayidx, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count + br i1 %exitcond.not, label %for.cond.cleanup, label %for.body +} -- GitLab From a5ed14bc8e122fa5ac0aa81f8d8390931bd6b4e4 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Fri, 12 Apr 2024 16:16:56 +0800 Subject: [PATCH 038/464] [X86][BF16] Fix a typo, NFCI VR128X is not enabled under AVXNECONVERT. --- llvm/lib/Target/X86/X86InstrSSE.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/X86/X86InstrSSE.td b/llvm/lib/Target/X86/X86InstrSSE.td index 2b391b60f2c9..5d799fc00df9 100644 --- a/llvm/lib/Target/X86/X86InstrSSE.td +++ b/llvm/lib/Target/X86/X86InstrSSE.td @@ -8314,7 +8314,7 @@ let Predicates = [HasAVXNECONVERT] in { f256mem>, T8; defm VCVTNEPS2BF16 : VCVTNEPS2BF16_BASE, VEX, T8, XS, ExplicitVEXPrefix; - def : Pat<(v8bf16 (X86cvtneps2bf16 (v4f32 VR128X:$src))), + def : Pat<(v8bf16 (X86cvtneps2bf16 (v4f32 VR128:$src))), (VCVTNEPS2BF16rr VR128:$src)>; def : Pat<(v8bf16 (X86cvtneps2bf16 (loadv4f32 addr:$src))), (VCVTNEPS2BF16rm addr:$src)>; -- GitLab From ad4e1aba3fd12f81de71ce3985ae66ff80773d90 Mon Sep 17 00:00:00 2001 From: jeanPerier Date: Fri, 12 Apr 2024 10:29:01 +0200 Subject: [PATCH 039/464] [flang] Pass VALUE CHARACTER arg by register in BIND(C) calls (#87774) Fortran mandates "CHARACTER(1), VALUE" be passed as a C "char" in calls to BIND(C) procedures (F'2023 18.3.7 (4)). Lowering passed them by memory instead. Update call interface lowering code to pass them by register. Fix related test and update it to use HLFIR. --- flang/lib/Lower/CallInterface.cpp | 24 ++++--- flang/lib/Lower/ConvertCall.cpp | 16 +++-- flang/lib/Lower/ConvertVariable.cpp | 9 ++- flang/test/Lower/call-by-value.f90 | 106 +++++++++++++++++----------- 4 files changed, 101 insertions(+), 54 deletions(-) diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp index 29cdb3cff589..05a0c10c7097 100644 --- a/flang/lib/Lower/CallInterface.cpp +++ b/flang/lib/Lower/CallInterface.cpp @@ -1136,14 +1136,22 @@ private: addPassedArg(PassEntityBy::Box, entity, characteristics); } else if (dynamicType.category() == Fortran::common::TypeCategory::Character) { - // Pass as fir.box_char - mlir::Type boxCharTy = - fir::BoxCharType::get(&mlirContext, dynamicType.kind()); - addFirOperand(boxCharTy, nextPassedArgPosition(), Property::BoxChar, - attrs); - addPassedArg(isValueAttr ? PassEntityBy::CharBoxValueAttribute - : PassEntityBy::BoxChar, - entity, characteristics); + if (isValueAttr && isBindC) { + // Pass as fir.char<1> + mlir::Type charTy = + fir::CharacterType::getSingleton(&mlirContext, dynamicType.kind()); + addFirOperand(charTy, nextPassedArgPosition(), Property::Value, attrs); + addPassedArg(PassEntityBy::Value, entity, characteristics); + } else { + // Pass as fir.box_char + mlir::Type boxCharTy = + fir::BoxCharType::get(&mlirContext, dynamicType.kind()); + addFirOperand(boxCharTy, nextPassedArgPosition(), Property::BoxChar, + attrs); + addPassedArg(isValueAttr ? PassEntityBy::CharBoxValueAttribute + : PassEntityBy::BoxChar, + entity, characteristics); + } } else { // Pass as fir.ref unless it's by VALUE and BIND(C). Also pass-by-value // for numerical/logical scalar without OPTIONAL so that the behavior is diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index 315a3f6736aa..c6f7d3410ad5 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -1494,11 +1494,19 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals, value = hlfir::Entity{genRecordCPtrValueArg(builder, loc, value, eleTy)}; } - } else if (fir::isa_derived(value.getFortranElementType())) { - // BIND(C), VALUE derived type. The derived type value must really + } else if (fir::isa_derived(value.getFortranElementType()) || + value.isCharacter()) { + // BIND(C), VALUE derived type or character. The value must really // be loaded here. - auto [derived, cleanup] = hlfir::convertToValue(loc, builder, value); - mlir::Value loadedValue = fir::getBase(derived); + auto [exv, cleanup] = hlfir::convertToValue(loc, builder, value); + mlir::Value loadedValue = fir::getBase(exv); + // Character actual arguments may have unknown length or a length longer + // than one. Cast the memory ref to the dummy type so that the load is + // valid and only loads what is needed. + if (mlir::Type baseTy = fir::dyn_cast_ptrEleTy(loadedValue.getType())) + if (fir::isa_char(baseTy)) + loadedValue = builder.createConvert( + loc, fir::ReferenceType::get(argTy), loadedValue); if (fir::isa_ref_type(loadedValue.getType())) loadedValue = builder.create(loc, loadedValue); caller.placeInput(arg, loadedValue); diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index 01473f7f6cd7..2d2d9eba905b 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -2100,10 +2100,15 @@ void Fortran::lower::mapSymbolAttributes( if (ba.isChar()) { if (arg) { assert(!preAlloc && "dummy cannot be pre-allocated"); - if (arg.getType().isa()) + if (mlir::isa(arg.getType())) { std::tie(addr, len) = charHelp.createUnboxChar(arg); - else if (!addr) + } else if (mlir::isa(arg.getType())) { + // fir.char<1> passed by value (BIND(C) with VALUE attribute). + addr = builder.create(loc, arg.getType()); + builder.create(loc, arg, addr); + } else if (!addr) { addr = arg; + } // Ensure proper type is given to array/scalar that was transmitted as a // fir.boxchar arg or is a statement function actual argument with // a different length than the dummy. diff --git a/flang/test/Lower/call-by-value.f90 b/flang/test/Lower/call-by-value.f90 index e489ea432305..d4694f4575d0 100644 --- a/flang/test/Lower/call-by-value.f90 +++ b/flang/test/Lower/call-by-value.f90 @@ -1,9 +1,10 @@ ! Test for PassBy::Value -! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: bbc -emit-fir %s -o - | FileCheck %s !CHECK-LABEL: func @_QQmain() -!CHECK: %[[LOGICAL:.*]] = fir.alloca !fir.logical<1> !CHECK: %false = arith.constant false +!CHECK: %[[LOGICAL_ALLOC:.*]] = fir.alloca !fir.logical<1> +!CHECK: %[[LOGICAL:.*]] = fir.declare %[[LOGICAL_ALLOC]] !CHECK: %[[VALUE:.*]] = fir.convert %false : (i1) -> !fir.logical<1> !CHECK: fir.store %[[VALUE]] to %[[LOGICAL]] !CHECK: %[[LOAD:.*]] = fir.load %[[LOGICAL]] @@ -23,39 +24,42 @@ program call_by_value call omp_set_nested(do_nested) end program call_by_value -! CHECK-LABEL: func.func @test_integer_value( -! CHECK-SAME: %[[VAL_0:.*]]: i32 {fir.bindc_name = "x"}) attributes {fir.bindc_name = "test_integer_value"} { -! CHECK: %[[VAL_1:.*]] = fir.alloca i32 -! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref -! CHECK: fir.call @_QPinternal_call(%[[VAL_1]]) {{.*}}: (!fir.ref) -> () -! CHECK: return -! CHECK: } +! CHECK-LABEL: func.func @test_integer_value( +! CHECK-SAME: %[[VAL_0:.*]]: i32 +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 +! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref +! CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] +! CHECK: fir.call @_QPinternal_call(%[[VAL_2]]) {{.*}}: (!fir.ref) -> () +! CHECK: return +! CHECK: } subroutine test_integer_value(x) bind(c) integer, value :: x call internal_call(x) end +! CHECK-LABEL: func.func @test_real_value( +! CHECK-SAME: %[[VAL_0:.*]]: f32 +! CHECK: %[[VAL_1:.*]] = fir.alloca f32 +! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref +! CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] +! CHECK: fir.call @_QPinternal_call2(%[[VAL_2]]) {{.*}}: (!fir.ref) -> () +! CHECK: return +! CHECK: } -! CHECK-LABEL: func.func @test_real_value( -! CHECK-SAME: %[[VAL_0:.*]]: f32 {fir.bindc_name = "x"}) attributes {fir.bindc_name = "test_real_value"} { -! CHECK: %[[VAL_1:.*]] = fir.alloca f32 -! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref -! CHECK: fir.call @_QPinternal_call2(%[[VAL_1]]) {{.*}}: (!fir.ref) -> () -! CHECK: return -! CHECK: } subroutine test_real_value(x) bind(c) real, value :: x call internal_call2(x) end +! CHECK-LABEL: func.func @test_complex_value( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.complex<4> +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.complex<4> +! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref> +! CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] +! CHECK: fir.call @_QPinternal_call3(%[[VAL_2]]) {{.*}}: (!fir.ref>) -> () +! CHECK: return +! CHECK: } -! CHECK-LABEL: func.func @test_complex_value( -! CHECK-SAME: %[[VAL_0:.*]]: !fir.complex<4> {fir.bindc_name = "x"}) attributes {fir.bindc_name = "test_complex_value"} { -! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.complex<4> -! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref> -! CHECK: fir.call @_QPinternal_call3(%[[VAL_1]]) {{.*}}: (!fir.ref>) -> () -! CHECK: return -! CHECK: } subroutine test_complex_value(x) bind(c) complex, value :: x @@ -63,12 +67,13 @@ subroutine test_complex_value(x) bind(c) end ! CHECK-LABEL: func.func @test_char_value( -! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "x"}) attributes {fir.bindc_name = "test_char_value"} { -! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref>, index) -! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.ref>) -> !fir.ref> -! CHECK: %[[VAL_2:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_5:.*]] = fir.emboxchar %[[VAL_3]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.boxchar<1> -! CHECK: fir.call @_QPinternal_call4(%[[VAL_5]]) fastmath : (!fir.boxchar<1>) -> () +! CHECK-SAME: %[[VAL_0:.*]]: !fir.char<1> +! CHECK: %[[VAL_1:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.char<1> +! CHECK: fir.store %[[VAL_0]] to %[[VAL_2]] : !fir.ref> +! CHECK: %[[VAL_3:.*]] = fir.declare %[[VAL_2]] typeparams %[[VAL_1]] +! CHECK: %[[VAL_4:.*]] = fir.emboxchar %[[VAL_3]], %[[VAL_1]] : (!fir.ref>, index) -> !fir.boxchar<1> +! CHECK: fir.call @_QPinternal_call4(%[[VAL_4]]) {{.*}}: (!fir.boxchar<1>) -> () ! CHECK: return ! CHECK: } @@ -77,19 +82,40 @@ subroutine test_char_value(x) bind(c) call internal_call4(x) end -! CHECK-LABEL: func.func @_QPtest_cptr_value( -! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> -! CHECK: %[[VAL_2:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> -! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, !fir.field) -> !fir.ref -! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_0]] : (!fir.ref) -> i64 -! CHECK: fir.store %[[VAL_4]] to %[[VAL_3]] : !fir.ref -! CHECK: fir.call @_QPinternal_call5(%[[VAL_1]]) {{.*}}: (!fir.ref>) -> () -! CHECK: return -! CHECK: } +! CHECK-LABEL: func.func @_QPtest_call_char_value( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> +! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref>, index) +! CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 +! CHECK: %[[VAL_3:.*]] = fir.emboxchar %[[VAL_2]], %[[VAL_1]]#1 : (!fir.ref>, index) -> !fir.boxchar<1> +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_2]] : (!fir.ref>) -> !fir.ref> +! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref> +! CHECK: fir.call @test_char_value(%[[VAL_5]]) {{.*}}: (!fir.char<1>) -> () +! CHECK: return +! CHECK: } +subroutine test_call_char_value(x) + character(*) :: x + interface + subroutine test_char_value(x) bind(c) + character(1), value :: x + end + end interface + call test_char_value(x) +end subroutine + +! CHECK-LABEL: func.func @_QPtest_cptr_value( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> +! CHECK: %[[VAL_2:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> +! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, !fir.field) -> !fir.ref +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_0]] : (!fir.ref) -> i64 +! CHECK: fir.store %[[VAL_4]] to %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_1]] +! CHECK: fir.call @_QPinternal_call5(%[[VAL_5]]) fastmath : (!fir.ref>) -> () +! CHECK: return +! CHECK: } subroutine test_cptr_value(x) - use iso_c_binding + use iso_c_binding, only: c_ptr type(c_ptr), value :: x call internal_call5(x) end -- GitLab From d488b2225d484027eb2c21a06d27decf008e878b Mon Sep 17 00:00:00 2001 From: Beal Wang Date: Fri, 12 Apr 2024 16:37:50 +0800 Subject: [PATCH 040/464] [mlir][ods] Do not print default-valued properties when the value is equal to the default (#87970) This diff causes the `tblgen`-erated printProperties() function to skip printing a `DefaultValuedAttr` property when the value is equal to the default. Co-authored-by: Biao Wang --- .../include/mlir/Dialect/XeGPU/IR/XeGPUOps.td | 3 +- mlir/include/mlir/IR/OpDefinition.h | 31 ++++++++++++------- mlir/lib/IR/Operation.cpp | 30 ++++++++++++++---- mlir/test/IR/properties.mlir | 5 +++ mlir/test/lib/Dialect/Test/TestOps.td | 17 +++++++--- mlir/tools/mlir-tblgen/OpFormatGen.cpp | 23 +++++++++++++- 6 files changed, 85 insertions(+), 24 deletions(-) diff --git a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUOps.td b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUOps.td index 93c56ad05b43..b8ebd1a40c60 100644 --- a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUOps.td +++ b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUOps.td @@ -27,7 +27,8 @@ class XeGPU_Op traits = []>: code extraBaseClassDeclaration = [{ void printProperties(::mlir::MLIRContext *ctx, - ::mlir::OpAsmPrinter &p, const Properties &prop) { + ::mlir::OpAsmPrinter &p, const Properties &prop, + ::mlir::ArrayRef<::llvm::StringRef> elidedProps) { Attribute propAttr = getPropertiesAsAttr(ctx, prop); if (propAttr) p << "<" << propAttr << ">"; diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h index 2d1dee2303e8..f4355c8ce26a 100644 --- a/mlir/include/mlir/IR/OpDefinition.h +++ b/mlir/include/mlir/IR/OpDefinition.h @@ -226,8 +226,10 @@ protected: static ParseResult genericParseProperties(OpAsmParser &parser, Attribute &result); - /// Print the properties as a Attribute. - static void genericPrintProperties(OpAsmPrinter &p, Attribute properties); + /// Print the properties as a Attribute with names not included within + /// 'elidedProps' + static void genericPrintProperties(OpAsmPrinter &p, Attribute properties, + ArrayRef elidedProps = {}); /// Print an operation name, eliding the dialect prefix if necessary. static void printOpName(Operation *op, OpAsmPrinter &p, @@ -1805,10 +1807,13 @@ private: template using detect_has_print = llvm::is_detected; - /// Trait to check if printProperties(OpAsmPrinter, T) exist + /// Trait to check if printProperties(OpAsmPrinter, T, ArrayRef) + /// exist template - using has_print_properties = decltype(printProperties( - std::declval(), std::declval())); + using has_print_properties = + decltype(printProperties(std::declval(), + std::declval(), + std::declval>())); template using detect_has_print_properties = llvm::is_detected; @@ -1974,16 +1979,18 @@ public: static void populateDefaultProperties(OperationName opName, InferredProperties &properties) {} - /// Print the operation properties. Unless overridden, this method will try to - /// dispatch to a `printProperties` free-function if it exists, and otherwise - /// by converting the properties to an Attribute. + /// Print the operation properties with names not included within + /// 'elidedProps'. Unless overridden, this method will try to dispatch to a + /// `printProperties` free-function if it exists, and otherwise by converting + /// the properties to an Attribute. template static void printProperties(MLIRContext *ctx, OpAsmPrinter &p, - const T &properties) { + const T &properties, + ArrayRef elidedProps = {}) { if constexpr (detect_has_print_properties::value) - return printProperties(p, properties); - genericPrintProperties(p, - ConcreteType::getPropertiesAsAttr(ctx, properties)); + return printProperties(p, properties, elidedProps); + genericPrintProperties( + p, ConcreteType::getPropertiesAsAttr(ctx, properties), elidedProps); } /// Parser the properties. Unless overridden, this method will print by diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp index ca5ff9f72e3e..db903d540761 100644 --- a/mlir/lib/IR/Operation.cpp +++ b/mlir/lib/IR/Operation.cpp @@ -790,15 +790,33 @@ void OpState::printOpName(Operation *op, OpAsmPrinter &p, /// Parse properties as a Attribute. ParseResult OpState::genericParseProperties(OpAsmParser &parser, Attribute &result) { - if (parser.parseLess() || parser.parseAttribute(result) || - parser.parseGreater()) - return failure(); + if (succeeded(parser.parseOptionalLess())) { // The less is optional. + if (parser.parseAttribute(result) || parser.parseGreater()) + return failure(); + } return success(); } -/// Print the properties as a Attribute. -void OpState::genericPrintProperties(OpAsmPrinter &p, Attribute properties) { - p << "<" << properties << ">"; +/// Print the properties as a Attribute with names not included within +/// 'elidedProps' +void OpState::genericPrintProperties(OpAsmPrinter &p, Attribute properties, + ArrayRef elidedProps) { + auto dictAttr = dyn_cast_or_null<::mlir::DictionaryAttr>(properties); + if (dictAttr && !elidedProps.empty()) { + ArrayRef attrs = dictAttr.getValue(); + llvm::SmallDenseSet elidedAttrsSet(elidedProps.begin(), + elidedProps.end()); + bool atLeastOneAttr = llvm::any_of(attrs, [&](NamedAttribute attr) { + return !elidedAttrsSet.contains(attr.getName().strref()); + }); + if (atLeastOneAttr) { + p << "<"; + p.printOptionalAttrDict(dictAttr.getValue(), elidedProps); + p << ">"; + } + } else { + p << "<" << properties << ">"; + } } /// Emit an error about fatal conditions with this operation, reporting up to diff --git a/mlir/test/IR/properties.mlir b/mlir/test/IR/properties.mlir index 3c4bd57859ef..1d22cb1940f2 100644 --- a/mlir/test/IR/properties.mlir +++ b/mlir/test/IR/properties.mlir @@ -33,3 +33,8 @@ test.using_property_in_custom [1, 4, 20] // GENERIC-SAME: second = 4 // GENERIC-SAME: }> test.using_property_ref_in_custom 1 + 4 = 5 + +// CHECK: test.with_default_valued_properties {{$}} +// GENERIC: "test.with_default_valued_properties"() +// GENERIC-SAME: <{a = 0 : i32}> +test.with_default_valued_properties <{a = 0 : i32}> diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index e6c3601d08da..edca05fde5a5 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -2909,7 +2909,8 @@ def TestOpWithNiceProperties : TEST_Op<"with_nice_properties"> { ); let extraClassDeclaration = [{ void printProperties(::mlir::MLIRContext *ctx, ::mlir::OpAsmPrinter &p, - const Properties &prop); + const Properties &prop, + ::mlir::ArrayRef<::llvm::StringRef> elidedProps); static ::mlir::ParseResult parseProperties(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); static ::mlir::LogicalResult readFromMlirBytecode( @@ -2938,7 +2939,8 @@ def TestOpWithNiceProperties : TEST_Op<"with_nice_properties"> { writer.writeVarInt(prop.value); } void TestOpWithNiceProperties::printProperties(::mlir::MLIRContext *ctx, - ::mlir::OpAsmPrinter &p, const Properties &prop) { + ::mlir::OpAsmPrinter &p, const Properties &prop, + ::mlir::ArrayRef<::llvm::StringRef> elidedProps) { customPrintProperties(p, prop.prop); } ::mlir::ParseResult TestOpWithNiceProperties::parseProperties( @@ -2971,7 +2973,8 @@ def TestOpWithVersionedProperties : TEST_Op<"with_versioned_properties"> { ); let extraClassDeclaration = [{ void printProperties(::mlir::MLIRContext *ctx, ::mlir::OpAsmPrinter &p, - const Properties &prop); + const Properties &prop, + ::mlir::ArrayRef<::llvm::StringRef> elidedProps); static ::mlir::ParseResult parseProperties(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); static ::mlir::LogicalResult readFromMlirBytecode( @@ -2983,7 +2986,8 @@ def TestOpWithVersionedProperties : TEST_Op<"with_versioned_properties"> { }]; let extraClassDefinition = [{ void TestOpWithVersionedProperties::printProperties(::mlir::MLIRContext *ctx, - ::mlir::OpAsmPrinter &p, const Properties &prop) { + ::mlir::OpAsmPrinter &p, const Properties &prop, + ::mlir::ArrayRef<::llvm::StringRef> elidedProps) { customPrintProperties(p, prop.prop); } ::mlir::ParseResult TestOpWithVersionedProperties::parseProperties( @@ -2997,6 +3001,11 @@ def TestOpWithVersionedProperties : TEST_Op<"with_versioned_properties"> { }]; } +def TestOpWithDefaultValuedProperties : TEST_Op<"with_default_valued_properties"> { + let assemblyFormat = "prop-dict attr-dict"; + let arguments = (ins DefaultValuedAttr:$a); +} + //===----------------------------------------------------------------------===// // Test Dataflow //===----------------------------------------------------------------------===// diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp index c8e0476d45b9..5963b5e689da 100644 --- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp @@ -1775,9 +1775,30 @@ const char *enumAttrBeginPrinterCode = R"( /// Generate the printer for the 'prop-dict' directive. static void genPropDictPrinter(OperationFormat &fmt, Operator &op, MethodBody &body) { + body << " ::llvm::SmallVector<::llvm::StringRef, 2> elidedProps;\n"; + // Add code to check attributes for equality with the default value + // for attributes with the elidePrintingDefaultValue bit set. + for (const NamedAttribute &namedAttr : op.getAttributes()) { + const Attribute &attr = namedAttr.attr; + if (!attr.isDerivedAttr() && attr.hasDefaultValue()) { + const StringRef &name = namedAttr.name; + FmtContext fctx; + fctx.withBuilder("odsBuilder"); + std::string defaultValue = std::string( + tgfmt(attr.getConstBuilderTemplate(), &fctx, attr.getDefaultValue())); + body << " {\n"; + body << " ::mlir::Builder odsBuilder(getContext());\n"; + body << " ::mlir::Attribute attr = " << op.getGetterName(name) + << "Attr();\n"; + body << " if(attr && (attr == " << defaultValue << "))\n"; + body << " elidedProps.push_back(\"" << name << "\");\n"; + body << " }\n"; + } + } + body << " _odsPrinter << \" \";\n" << " printProperties(this->getContext(), _odsPrinter, " - "getProperties());\n"; + "getProperties(), elidedProps);\n"; } /// Generate the printer for the 'attr-dict' directive. -- GitLab From d019b9aaaaa60c858ee82fdbaf5de16e048e9db2 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Fri, 12 Apr 2024 12:20:22 +0300 Subject: [PATCH 041/464] [clang][NFC] Refactor `CXXSpecialMember` In preparation for `SemaCUDA`, which requires this enum to be forward-declarable. --- clang/include/clang/Sema/Sema.h | 64 ++- clang/lib/Sema/SemaAccess.cpp | 14 +- clang/lib/Sema/SemaCUDA.cpp | 2 +- clang/lib/Sema/SemaDecl.cpp | 51 +- clang/lib/Sema/SemaDeclCXX.cpp | 522 ++++++++++-------- clang/lib/Sema/SemaInit.cpp | 6 +- clang/lib/Sema/SemaLookup.cpp | 78 +-- clang/lib/Sema/SemaOverload.cpp | 16 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 7 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 +- clang/lib/Sema/SemaType.cpp | 3 +- 11 files changed, 424 insertions(+), 347 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index c4a603cc5a4a..90c916628270 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -60,6 +60,7 @@ #include "clang/Sema/TypoCorrection.h" #include "clang/Sema/Weak.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -423,6 +424,17 @@ enum class TemplateDeductionResult { AlreadyDiagnosed }; +/// Kinds of C++ special members. +enum class CXXSpecialMemberKind { + DefaultConstructor, + CopyConstructor, + MoveConstructor, + CopyAssignment, + MoveAssignment, + Destructor, + Invalid +}; + /// Sema - This implements semantic analysis and AST building for C. /// \nosubgrouping class Sema final : public SemaBase { @@ -4077,22 +4089,11 @@ public: SourceRange SpecificationRange, ArrayRef DynamicExceptions, ArrayRef DynamicExceptionRanges, Expr *NoexceptExpr); - /// Kinds of C++ special members. - enum CXXSpecialMember { - CXXDefaultConstructor, - CXXCopyConstructor, - CXXMoveConstructor, - CXXCopyAssignment, - CXXMoveAssignment, - CXXDestructor, - CXXInvalid - }; - class InheritedConstructorInfo; /// Determine if a special member function should have a deleted /// definition when it is defaulted. - bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, InheritedConstructorInfo *ICI = nullptr, bool Diagnose = false); @@ -4458,7 +4459,7 @@ public: void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD); bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, - CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, SourceLocation DefaultLoc); void CheckDelayedMemberExceptionSpecs(); @@ -4618,7 +4619,7 @@ public: void CheckCXXDefaultArguments(FunctionDecl *FD); void CheckExtraCXXDefaultArguments(Declarator &D); - CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD) { + CXXSpecialMemberKind getSpecialMember(const CXXMethodDecl *MD) { return getDefaultedFunctionKind(MD).asSpecialMember(); } @@ -4645,7 +4646,8 @@ public: AccessSpecifier AS, const ParsedAttr &MSPropertyAttr); - void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM); + void DiagnoseNontrivial(const CXXRecordDecl *Record, + CXXSpecialMemberKind CSM); enum TrivialABIHandling { /// The triviality of a method unaffected by "trivial_abi". @@ -4655,26 +4657,31 @@ public: TAH_ConsiderTrivialABI }; - bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, TrivialABIHandling TAH = TAH_IgnoreTrivialABI, bool Diagnose = false); /// For a defaulted function, the kind of defaulted function that it is. class DefaultedFunctionKind { + LLVM_PREFERRED_TYPE(CXXSpecialMemberKind) unsigned SpecialMember : 8; unsigned Comparison : 8; public: DefaultedFunctionKind() - : SpecialMember(CXXInvalid), + : SpecialMember(llvm::to_underlying(CXXSpecialMemberKind::Invalid)), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {} - DefaultedFunctionKind(CXXSpecialMember CSM) - : SpecialMember(CSM), + DefaultedFunctionKind(CXXSpecialMemberKind CSM) + : SpecialMember(llvm::to_underlying(CSM)), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {} DefaultedFunctionKind(DefaultedComparisonKind Comp) - : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(Comp)) {} + : SpecialMember(llvm::to_underlying(CXXSpecialMemberKind::Invalid)), + Comparison(llvm::to_underlying(Comp)) {} - bool isSpecialMember() const { return SpecialMember != CXXInvalid; } + bool isSpecialMember() const { + return static_cast(SpecialMember) != + CXXSpecialMemberKind::Invalid; + } bool isComparison() const { return static_cast(Comparison) != DefaultedComparisonKind::None; @@ -4684,8 +4691,8 @@ public: return isSpecialMember() || isComparison(); } - CXXSpecialMember asSpecialMember() const { - return static_cast(SpecialMember); + CXXSpecialMemberKind asSpecialMember() const { + return static_cast(SpecialMember); } DefaultedComparisonKind asComparison() const { return static_cast(Comparison); @@ -4693,7 +4700,8 @@ public: /// Get the index of this function kind for use in diagnostics. unsigned getDiagnosticIndex() const { - static_assert(CXXInvalid > CXXDestructor, + static_assert(llvm::to_underlying(CXXSpecialMemberKind::Invalid) > + llvm::to_underlying(CXXSpecialMemberKind::Destructor), "invalid should have highest index"); static_assert((unsigned)DefaultedComparisonKind::None == 0, "none should be equal to zero"); @@ -4799,7 +4807,7 @@ public: /// definition in this translation unit. llvm::MapVector UndefinedButUsed; - typedef llvm::PointerIntPair + typedef llvm::PointerIntPair SpecialMemberDecl; /// The C++ special members which we are currently in the process of @@ -7493,7 +7501,7 @@ public: }; SpecialMemberOverloadResult - LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, bool ConstArg, + LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMemberKind SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis); @@ -10014,7 +10022,7 @@ public: unsigned NumCallArgs; /// The special member being declared or defined. - CXXSpecialMember SpecialMember; + CXXSpecialMemberKind SpecialMember; }; ArrayRef template_arguments() const { @@ -13109,7 +13117,7 @@ public: /// The result of this call is implicit CUDA target attribute(s) attached to /// the member declaration. bool inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, - CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, CXXMethodDecl *MemberDecl, bool ConstRHS, bool Diagnose); diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 4af3c0f30a8e..6a707eeb66d0 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -10,8 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Basic/Specifiers.h" -#include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" @@ -19,9 +17,12 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DependentDiagnostic.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/Specifiers.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "llvm/ADT/STLForwardCompat.h" using namespace clang; using namespace sema; @@ -1658,21 +1659,24 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, case InitializedEntity::EK_Base: PD = PDiag(diag::err_access_base_ctor); PD << Entity.isInheritedVirtualBase() - << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor); + << Entity.getBaseSpecifier()->getType() + << llvm::to_underlying(getSpecialMember(Constructor)); break; case InitializedEntity::EK_Member: case InitializedEntity::EK_ParenAggInitMember: { const FieldDecl *Field = cast(Entity.getDecl()); PD = PDiag(diag::err_access_field_ctor); - PD << Field->getType() << getSpecialMember(Constructor); + PD << Field->getType() + << llvm::to_underlying(getSpecialMember(Constructor)); break; } case InitializedEntity::EK_LambdaCapture: { StringRef VarName = Entity.getCapturedVarName(); PD = PDiag(diag::err_access_lambda_capture); - PD << VarName << Entity.getType() << getSpecialMember(Constructor); + PD << VarName << Entity.getType() + << llvm::to_underlying(getSpecialMember(Constructor)); break; } diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index 4d4f4b6a2d4d..1596222e3d1d 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -358,7 +358,7 @@ resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1, } bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, - CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, CXXMethodDecl *MemberDecl, bool ConstRHS, bool Diagnose) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index afd9e407946a..b448bacd49f3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -48,6 +48,7 @@ #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TargetParser/Triple.h" @@ -4049,13 +4050,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, } else { Diag(NewMethod->getLocation(), diag::err_definition_of_implicitly_declared_member) - << New << getSpecialMember(OldMethod); + << New << llvm::to_underlying(getSpecialMember(OldMethod)); return true; } } else if (OldMethod->getFirstDecl()->isExplicitlyDefaulted() && !isFriend) { Diag(NewMethod->getLocation(), diag::err_definition_of_explicitly_defaulted_member) - << getSpecialMember(OldMethod); + << llvm::to_underlying(getSpecialMember(OldMethod)); return true; } } @@ -18847,22 +18848,22 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { // because otherwise we'll never get complaints about // copy constructors. - CXXSpecialMember member = CXXInvalid; + CXXSpecialMemberKind member = CXXSpecialMemberKind::Invalid; // We're required to check for any non-trivial constructors. Since the // implicit default constructor is suppressed if there are any // user-declared constructors, we just need to check that there is a // trivial default constructor and a trivial copy constructor. (We don't // worry about move constructors here, since this is a C++98 check.) if (RDecl->hasNonTrivialCopyConstructor()) - member = CXXCopyConstructor; + member = CXXSpecialMemberKind::CopyConstructor; else if (!RDecl->hasTrivialDefaultConstructor()) - member = CXXDefaultConstructor; + member = CXXSpecialMemberKind::DefaultConstructor; else if (RDecl->hasNonTrivialCopyAssignment()) - member = CXXCopyAssignment; + member = CXXSpecialMemberKind::CopyAssignment; else if (RDecl->hasNonTrivialDestructor()) - member = CXXDestructor; + member = CXXSpecialMemberKind::Destructor; - if (member != CXXInvalid) { + if (member != CXXSpecialMemberKind::Invalid) { if (!getLangOpts().CPlusPlus11 && getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) { // Objective-C++ ARC: it is an error to have a non-trivial field of @@ -18879,10 +18880,13 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { } } - Diag(FD->getLocation(), getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member : - diag::err_illegal_union_or_anon_struct_member) - << FD->getParent()->isUnion() << FD->getDeclName() << member; + Diag( + FD->getLocation(), + getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member + : diag::err_illegal_union_or_anon_struct_member) + << FD->getParent()->isUnion() << FD->getDeclName() + << llvm::to_underlying(member); DiagnoseNontrivial(RDecl, member); return !getLangOpts().CPlusPlus11; } @@ -19132,10 +19136,10 @@ static void ComputeSelectedDestructor(Sema &S, CXXRecordDecl *Record) { static bool AreSpecialMemberFunctionsSameKind(ASTContext &Context, CXXMethodDecl *M1, CXXMethodDecl *M2, - Sema::CXXSpecialMember CSM) { + CXXSpecialMemberKind CSM) { // We don't want to compare templates to non-templates: See // https://github.com/llvm/llvm-project/issues/59206 - if (CSM == Sema::CXXDefaultConstructor) + if (CSM == CXXSpecialMemberKind::DefaultConstructor) return bool(M1->getDescribedFunctionTemplate()) == bool(M2->getDescribedFunctionTemplate()); // FIXME: better resolve CWG @@ -19158,7 +19162,7 @@ static bool AreSpecialMemberFunctionsSameKind(ASTContext &Context, /// [CWG2595], if any, are satisfied is more constrained. static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record, ArrayRef Methods, - Sema::CXXSpecialMember CSM) { + CXXSpecialMemberKind CSM) { SmallVector SatisfactionStatus; for (CXXMethodDecl *Method : Methods) { @@ -19216,7 +19220,8 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record, // DR1734 and DR1496. if (!AnotherMethodIsMoreConstrained) { Method->setIneligibleOrNotSelected(false); - Record->addedEligibleSpecialMemberFunction(Method, 1 << CSM); + Record->addedEligibleSpecialMemberFunction(Method, + 1 << llvm::to_underlying(CSM)); } } } @@ -19255,13 +19260,15 @@ static void ComputeSpecialMemberFunctionsEligiblity(Sema &S, } SetEligibleMethods(S, Record, DefaultConstructors, - Sema::CXXDefaultConstructor); - SetEligibleMethods(S, Record, CopyConstructors, Sema::CXXCopyConstructor); - SetEligibleMethods(S, Record, MoveConstructors, Sema::CXXMoveConstructor); + CXXSpecialMemberKind::DefaultConstructor); + SetEligibleMethods(S, Record, CopyConstructors, + CXXSpecialMemberKind::CopyConstructor); + SetEligibleMethods(S, Record, MoveConstructors, + CXXSpecialMemberKind::MoveConstructor); SetEligibleMethods(S, Record, CopyAssignmentOperators, - Sema::CXXCopyAssignment); + CXXSpecialMemberKind::CopyAssignment); SetEligibleMethods(S, Record, MoveAssignmentOperators, - Sema::CXXMoveAssignment); + CXXSpecialMemberKind::MoveAssignment); } void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, @@ -19630,7 +19637,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (CXXRecord) { auto *Dtor = CXXRecord->getDestructor(); if (Dtor && Dtor->isImplicit() && - ShouldDeleteSpecialMember(Dtor, CXXDestructor)) { + ShouldDeleteSpecialMember(Dtor, CXXSpecialMemberKind::Destructor)) { CXXRecord->setImplicitDestructorIsDeleted(); SetDeclDeleted(Dtor, CXXRecord->getLocation()); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 858951580ea4..51c14443d2d8 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -46,6 +46,7 @@ #include "clang/Sema/Template.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -657,13 +658,13 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // is ill-formed. This can only happen for constructors. if (isa(New) && New->getMinRequiredArguments() < Old->getMinRequiredArguments()) { - CXXSpecialMember NewSM = getSpecialMember(cast(New)), - OldSM = getSpecialMember(cast(Old)); + CXXSpecialMemberKind NewSM = getSpecialMember(cast(New)), + OldSM = getSpecialMember(cast(Old)); if (NewSM != OldSM) { ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments()); assert(NewParam->hasDefaultArg()); Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special) - << NewParam->getDefaultArgRange() << NewSM; + << NewParam->getDefaultArgRange() << llvm::to_underlying(NewSM); Diag(Old->getLocation(), diag::note_previous_declaration); } } @@ -6779,7 +6780,7 @@ void Sema::propagateDLLAttrToBaseClassTemplate( /// /// If the function is both a default constructor and a copy / move constructor /// (due to having a default argument for the first parameter), this picks -/// CXXDefaultConstructor. +/// CXXSpecialMemberKind::DefaultConstructor. /// /// FIXME: Check that case is properly handled by all callers. Sema::DefaultedFunctionKind @@ -6787,23 +6788,23 @@ Sema::getDefaultedFunctionKind(const FunctionDecl *FD) { if (auto *MD = dyn_cast(FD)) { if (const CXXConstructorDecl *Ctor = dyn_cast(FD)) { if (Ctor->isDefaultConstructor()) - return Sema::CXXDefaultConstructor; + return CXXSpecialMemberKind::DefaultConstructor; if (Ctor->isCopyConstructor()) - return Sema::CXXCopyConstructor; + return CXXSpecialMemberKind::CopyConstructor; if (Ctor->isMoveConstructor()) - return Sema::CXXMoveConstructor; + return CXXSpecialMemberKind::MoveConstructor; } if (MD->isCopyAssignmentOperator()) - return Sema::CXXCopyAssignment; + return CXXSpecialMemberKind::CopyAssignment; if (MD->isMoveAssignmentOperator()) - return Sema::CXXMoveAssignment; + return CXXSpecialMemberKind::MoveAssignment; if (isa(FD)) - return Sema::CXXDestructor; + return CXXSpecialMemberKind::Destructor; } switch (FD->getDeclName().getCXXOverloadedOperator()) { @@ -6843,26 +6844,26 @@ static void DefineDefaultedFunction(Sema &S, FunctionDecl *FD, return S.DefineDefaultedComparison(DefaultLoc, FD, DFK.asComparison()); switch (DFK.asSpecialMember()) { - case Sema::CXXDefaultConstructor: + case CXXSpecialMemberKind::DefaultConstructor: S.DefineImplicitDefaultConstructor(DefaultLoc, cast(FD)); break; - case Sema::CXXCopyConstructor: + case CXXSpecialMemberKind::CopyConstructor: S.DefineImplicitCopyConstructor(DefaultLoc, cast(FD)); break; - case Sema::CXXCopyAssignment: + case CXXSpecialMemberKind::CopyAssignment: S.DefineImplicitCopyAssignment(DefaultLoc, cast(FD)); break; - case Sema::CXXDestructor: + case CXXSpecialMemberKind::Destructor: S.DefineImplicitDestructor(DefaultLoc, cast(FD)); break; - case Sema::CXXMoveConstructor: + case CXXSpecialMemberKind::MoveConstructor: S.DefineImplicitMoveConstructor(DefaultLoc, cast(FD)); break; - case Sema::CXXMoveAssignment: + case CXXSpecialMemberKind::MoveAssignment: S.DefineImplicitMoveAssignment(DefaultLoc, cast(FD)); break; - case Sema::CXXInvalid: + case CXXSpecialMemberKind::Invalid: llvm_unreachable("Invalid special member."); } } @@ -7182,9 +7183,9 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // For an explicitly defaulted or deleted special member, we defer // determining triviality until the class is complete. That time is now! - CXXSpecialMember CSM = getSpecialMember(M); + CXXSpecialMemberKind CSM = getSpecialMember(M); if (!M->isImplicit() && !M->isUserProvided()) { - if (CSM != CXXInvalid) { + if (CSM != CXXSpecialMemberKind::Invalid) { M->setTrivial(SpecialMemberIsTrivial(M, CSM)); // Inform the class that we've finished declaring this member. Record->finishedDefaultedOrDeletedMember(M); @@ -7197,8 +7198,10 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // Set triviality for the purpose of calls if this is a user-provided // copy/move constructor or destructor. - if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor || - CSM == CXXDestructor) && M->isUserProvided()) { + if ((CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::MoveConstructor || + CSM == CXXSpecialMemberKind::Destructor) && + M->isUserProvided()) { M->setTrivialForCall(HasTrivialABI); Record->setTrivialForCallFlags(M); } @@ -7207,8 +7210,9 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { M->hasAttr()) { if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) && M->isTrivial() && - (CSM == CXXDefaultConstructor || CSM == CXXCopyConstructor || - CSM == CXXDestructor)) + (CSM == CXXSpecialMemberKind::DefaultConstructor || + CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::Destructor)) M->dropAttr(); if (M->hasAttr()) { @@ -7220,8 +7224,8 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // Define defaulted constexpr virtual functions that override a base class // function right away. // FIXME: We can defer doing this until the vtable is marked as used. - if (CSM != CXXInvalid && !M->isDeleted() && M->isDefaulted() && - M->isConstexpr() && M->size_overridden_methods()) + if (CSM != CXXSpecialMemberKind::Invalid && !M->isDeleted() && + M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods()) DefineDefaultedFunction(*this, M, M->getLocation()); if (!Incomplete) @@ -7343,15 +7347,18 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { /// \param ConstRHS True if this is a copy operation with a const object /// on its RHS, that is, if the argument to the outer special member /// function is 'const' and this is not a field marked 'mutable'. -static Sema::SpecialMemberOverloadResult lookupCallFromSpecialMember( - Sema &S, CXXRecordDecl *Class, Sema::CXXSpecialMember CSM, - unsigned FieldQuals, bool ConstRHS) { +static Sema::SpecialMemberOverloadResult +lookupCallFromSpecialMember(Sema &S, CXXRecordDecl *Class, + CXXSpecialMemberKind CSM, unsigned FieldQuals, + bool ConstRHS) { unsigned LHSQuals = 0; - if (CSM == Sema::CXXCopyAssignment || CSM == Sema::CXXMoveAssignment) + if (CSM == CXXSpecialMemberKind::CopyAssignment || + CSM == CXXSpecialMemberKind::MoveAssignment) LHSQuals = FieldQuals; unsigned RHSQuals = FieldQuals; - if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor) + if (CSM == CXXSpecialMemberKind::DefaultConstructor || + CSM == CXXSpecialMemberKind::Destructor) RHSQuals = 0; else if (ConstRHS) RHSQuals |= Qualifiers::Const; @@ -7447,12 +7454,10 @@ public: /// Is the special member function which would be selected to perform the /// specified operation on the specified class type a constexpr constructor? -static bool -specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, - Sema::CXXSpecialMember CSM, unsigned Quals, - bool ConstRHS, - CXXConstructorDecl *InheritedCtor = nullptr, - Sema::InheritedConstructorInfo *Inherited = nullptr) { +static bool specialMemberIsConstexpr( + Sema &S, CXXRecordDecl *ClassDecl, CXXSpecialMemberKind CSM, unsigned Quals, + bool ConstRHS, CXXConstructorDecl *InheritedCtor = nullptr, + Sema::InheritedConstructorInfo *Inherited = nullptr) { // Suppress duplicate constraint checking here, in case a constraint check // caused us to decide to do this. Any truely recursive checks will get // caught during these checks anyway. @@ -7461,16 +7466,16 @@ specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, // If we're inheriting a constructor, see if we need to call it for this base // class. if (InheritedCtor) { - assert(CSM == Sema::CXXDefaultConstructor); + assert(CSM == CXXSpecialMemberKind::DefaultConstructor); auto BaseCtor = Inherited->findConstructorForBase(ClassDecl, InheritedCtor).first; if (BaseCtor) return BaseCtor->isConstexpr(); } - if (CSM == Sema::CXXDefaultConstructor) + if (CSM == CXXSpecialMemberKind::DefaultConstructor) return ClassDecl->hasConstexprDefaultConstructor(); - if (CSM == Sema::CXXDestructor) + if (CSM == CXXSpecialMemberKind::Destructor) return ClassDecl->hasConstexprDestructor(); Sema::SpecialMemberOverloadResult SMOR = @@ -7485,8 +7490,8 @@ specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, /// Determine whether the specified special member function would be constexpr /// if it were implicitly defined. static bool defaultedSpecialMemberIsConstexpr( - Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM, - bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr, + Sema &S, CXXRecordDecl *ClassDecl, CXXSpecialMemberKind CSM, bool ConstArg, + CXXConstructorDecl *InheritedCtor = nullptr, Sema::InheritedConstructorInfo *Inherited = nullptr) { if (!S.getLangOpts().CPlusPlus11) return false; @@ -7495,7 +7500,7 @@ static bool defaultedSpecialMemberIsConstexpr( // In the definition of a constexpr constructor [...] bool Ctor = true; switch (CSM) { - case Sema::CXXDefaultConstructor: + case CXXSpecialMemberKind::DefaultConstructor: if (Inherited) break; // Since default constructor lookup is essentially trivial (and cannot @@ -7506,23 +7511,23 @@ static bool defaultedSpecialMemberIsConstexpr( // constructor is constexpr to determine whether the type is a literal type. return ClassDecl->defaultedDefaultConstructorIsConstexpr(); - case Sema::CXXCopyConstructor: - case Sema::CXXMoveConstructor: + case CXXSpecialMemberKind::CopyConstructor: + case CXXSpecialMemberKind::MoveConstructor: // For copy or move constructors, we need to perform overload resolution. break; - case Sema::CXXCopyAssignment: - case Sema::CXXMoveAssignment: + case CXXSpecialMemberKind::CopyAssignment: + case CXXSpecialMemberKind::MoveAssignment: if (!S.getLangOpts().CPlusPlus14) return false; // In C++1y, we need to perform overload resolution. Ctor = false; break; - case Sema::CXXDestructor: + case CXXSpecialMemberKind::Destructor: return ClassDecl->defaultedDestructorIsConstexpr(); - case Sema::CXXInvalid: + case CXXSpecialMemberKind::Invalid: return false; } @@ -7534,7 +7539,7 @@ static bool defaultedSpecialMemberIsConstexpr( // will be initialized (if the constructor isn't deleted), we just don't know // which one. if (Ctor && ClassDecl->isUnion()) - return CSM == Sema::CXXDefaultConstructor + return CSM == CXXSpecialMemberKind::DefaultConstructor ? ClassDecl->hasInClassInitializer() || !ClassDecl->hasVariantMembers() : true; @@ -7575,7 +7580,8 @@ static bool defaultedSpecialMemberIsConstexpr( for (const auto *F : ClassDecl->fields()) { if (F->isInvalidDecl()) continue; - if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + F->hasInClassInitializer()) continue; QualType BaseType = S.Context.getBaseElementType(F->getType()); if (const RecordType *RecordTy = BaseType->getAs()) { @@ -7584,7 +7590,7 @@ static bool defaultedSpecialMemberIsConstexpr( BaseType.getCVRQualifiers(), ConstArg && !F->isMutable())) return false; - } else if (CSM == Sema::CXXDefaultConstructor) { + } else if (CSM == CXXSpecialMemberKind::DefaultConstructor) { return false; } } @@ -7615,9 +7621,10 @@ struct ComputingExceptionSpec { } static Sema::ImplicitExceptionSpecification -ComputeDefaultedSpecialMemberExceptionSpec( - Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, - Sema::InheritedConstructorInfo *ICI); +ComputeDefaultedSpecialMemberExceptionSpec(Sema &S, SourceLocation Loc, + CXXMethodDecl *MD, + CXXSpecialMemberKind CSM, + Sema::InheritedConstructorInfo *ICI); static Sema::ImplicitExceptionSpecification ComputeDefaultedComparisonExceptionSpec(Sema &S, SourceLocation Loc, @@ -7641,7 +7648,7 @@ computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, FunctionDecl *FD) { Sema::InheritedConstructorInfo ICI( S, Loc, CD->getInheritedConstructor().getShadowDecl()); return ComputeDefaultedSpecialMemberExceptionSpec( - S, Loc, CD, Sema::CXXDefaultConstructor, &ICI); + S, Loc, CD, CXXSpecialMemberKind::DefaultConstructor, &ICI); } static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S, @@ -7693,11 +7700,11 @@ void Sema::CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *FD) { } bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, - CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, SourceLocation DefaultLoc) { CXXRecordDecl *RD = MD->getParent(); - assert(MD->isExplicitlyDefaulted() && CSM != CXXInvalid && + assert(MD->isExplicitlyDefaulted() && CSM != CXXSpecialMemberKind::Invalid && "not an explicitly-defaulted special member"); // Defer all checking for special members of a dependent type. @@ -7723,21 +7730,22 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, bool DeleteOnTypeMismatch = getLangOpts().CPlusPlus20 && First; bool ShouldDeleteForTypeMismatch = false; unsigned ExpectedParams = 1; - if (CSM == CXXDefaultConstructor || CSM == CXXDestructor) + if (CSM == CXXSpecialMemberKind::DefaultConstructor || + CSM == CXXSpecialMemberKind::Destructor) ExpectedParams = 0; if (MD->getNumExplicitParams() != ExpectedParams) { // This checks for default arguments: a copy or move constructor with a // default argument is classified as a default constructor, and assignment // operations and destructors can't have default arguments. Diag(MD->getLocation(), diag::err_defaulted_special_member_params) - << CSM << MD->getSourceRange(); + << llvm::to_underlying(CSM) << MD->getSourceRange(); HadError = true; } else if (MD->isVariadic()) { if (DeleteOnTypeMismatch) ShouldDeleteForTypeMismatch = true; else { Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic) - << CSM << MD->getSourceRange(); + << llvm::to_underlying(CSM) << MD->getSourceRange(); HadError = true; } } @@ -7745,13 +7753,14 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, const FunctionProtoType *Type = MD->getType()->castAs(); bool CanHaveConstParam = false; - if (CSM == CXXCopyConstructor) + if (CSM == CXXSpecialMemberKind::CopyConstructor) CanHaveConstParam = RD->implicitCopyConstructorHasConstParam(); - else if (CSM == CXXCopyAssignment) + else if (CSM == CXXSpecialMemberKind::CopyAssignment) CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam(); QualType ReturnType = Context.VoidTy; - if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { + if (CSM == CXXSpecialMemberKind::CopyAssignment || + CSM == CXXSpecialMemberKind::MoveAssignment) { // Check for return type matching. ReturnType = Type->getReturnType(); QualType ThisType = MD->getFunctionObjectParameterType(); @@ -7765,7 +7774,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (!Context.hasSameType(ReturnType, ExpectedReturnType)) { Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type) - << (CSM == CXXMoveAssignment) << ExpectedReturnType; + << (CSM == CXXSpecialMemberKind::MoveAssignment) + << ExpectedReturnType; HadError = true; } @@ -7775,7 +7785,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, ShouldDeleteForTypeMismatch = true; else { Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) - << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14; + << (CSM == CXXSpecialMemberKind::MoveAssignment) + << getLangOpts().CPlusPlus14; HadError = true; } } @@ -7793,7 +7804,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, else { Diag(MD->getLocation(), diag::err_defaulted_special_member_explicit_object_mismatch) - << (CSM == CXXMoveAssignment) << RD << MD->getSourceRange(); + << (CSM == CXXSpecialMemberKind::MoveAssignment) << RD + << MD->getSourceRange(); HadError = true; } } @@ -7815,7 +7827,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, ShouldDeleteForTypeMismatch = true; else { Diag(MD->getLocation(), - diag::err_defaulted_special_member_volatile_param) << CSM; + diag::err_defaulted_special_member_volatile_param) + << llvm::to_underlying(CSM); HadError = true; } } @@ -7823,23 +7836,25 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (HasConstParam && !CanHaveConstParam) { if (DeleteOnTypeMismatch) ShouldDeleteForTypeMismatch = true; - else if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) { + else if (CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::CopyAssignment) { Diag(MD->getLocation(), diag::err_defaulted_special_member_copy_const_param) - << (CSM == CXXCopyAssignment); + << (CSM == CXXSpecialMemberKind::CopyAssignment); // FIXME: Explain why this special member can't be const. HadError = true; } else { Diag(MD->getLocation(), diag::err_defaulted_special_member_move_const_param) - << (CSM == CXXMoveAssignment); + << (CSM == CXXSpecialMemberKind::MoveAssignment); HadError = true; } } } else if (ExpectedParams) { // A copy assignment operator can take its argument by value, but a // defaulted one cannot. - assert(CSM == CXXCopyAssignment && "unexpected non-ref argument"); + assert(CSM == CXXSpecialMemberKind::CopyAssignment && + "unexpected non-ref argument"); Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); HadError = true; } @@ -7874,12 +7889,12 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (!MD->isConsteval() && RD->getNumVBases()) { Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb) - << CSM; + << llvm::to_underlying(CSM); for (const auto &I : RD->vbases()) Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here); } else { Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) - << CSM << MD->isConsteval(); + << llvm::to_underlying(CSM) << MD->isConsteval(); } HadError = true; // FIXME: Explain why the special member can't be constexpr. @@ -7912,9 +7927,11 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (First) { SetDeclDeleted(MD, MD->getLocation()); if (!inTemplateInstantiation() && !HadError) { - Diag(MD->getLocation(), diag::warn_defaulted_method_deleted) << CSM; + Diag(MD->getLocation(), diag::warn_defaulted_method_deleted) + << llvm::to_underlying(CSM); if (ShouldDeleteForTypeMismatch) { - Diag(MD->getLocation(), diag::note_deleted_type_mismatch) << CSM; + Diag(MD->getLocation(), diag::note_deleted_type_mismatch) + << llvm::to_underlying(CSM); } else if (ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/ true) && DefaultLoc.isValid()) { @@ -7924,13 +7941,15 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, } if (ShouldDeleteForTypeMismatch && !HadError) { Diag(MD->getLocation(), - diag::warn_cxx17_compat_defaulted_method_type_mismatch) << CSM; + diag::warn_cxx17_compat_defaulted_method_type_mismatch) + << llvm::to_underlying(CSM); } } else { // C++11 [dcl.fct.def.default]p4: // [For a] user-provided explicitly-defaulted function [...] if such a // function is implicitly defined as deleted, the program is ill-formed. - Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; + Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) + << llvm::to_underlying(CSM); assert(!ShouldDeleteForTypeMismatch && "deleted non-first decl"); ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true); HadError = true; @@ -9271,28 +9290,28 @@ template struct SpecialMemberVisitor { Sema &S; CXXMethodDecl *MD; - Sema::CXXSpecialMember CSM; + CXXSpecialMemberKind CSM; Sema::InheritedConstructorInfo *ICI; // Properties of the special member, computed for convenience. bool IsConstructor = false, IsAssignment = false, ConstArg = false; - SpecialMemberVisitor(Sema &S, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, + SpecialMemberVisitor(Sema &S, CXXMethodDecl *MD, CXXSpecialMemberKind CSM, Sema::InheritedConstructorInfo *ICI) : S(S), MD(MD), CSM(CSM), ICI(ICI) { switch (CSM) { - case Sema::CXXDefaultConstructor: - case Sema::CXXCopyConstructor: - case Sema::CXXMoveConstructor: + case CXXSpecialMemberKind::DefaultConstructor: + case CXXSpecialMemberKind::CopyConstructor: + case CXXSpecialMemberKind::MoveConstructor: IsConstructor = true; break; - case Sema::CXXCopyAssignment: - case Sema::CXXMoveAssignment: + case CXXSpecialMemberKind::CopyAssignment: + case CXXSpecialMemberKind::MoveAssignment: IsAssignment = true; break; - case Sema::CXXDestructor: + case CXXSpecialMemberKind::Destructor: break; - case Sema::CXXInvalid: + case CXXSpecialMemberKind::Invalid: llvm_unreachable("invalid special member kind"); } @@ -9307,7 +9326,8 @@ struct SpecialMemberVisitor { /// Is this a "move" special member? bool isMove() const { - return CSM == Sema::CXXMoveConstructor || CSM == Sema::CXXMoveAssignment; + return CSM == CXXSpecialMemberKind::MoveConstructor || + CSM == CXXSpecialMemberKind::MoveAssignment; } /// Look up the corresponding special member in the given class. @@ -9322,7 +9342,7 @@ struct SpecialMemberVisitor { Sema::SpecialMemberOverloadResult lookupInheritedCtor(CXXRecordDecl *Class) { if (!ICI) return {}; - assert(CSM == Sema::CXXDefaultConstructor); + assert(CSM == CXXSpecialMemberKind::DefaultConstructor); auto *BaseCtor = cast(MD)->getInheritedConstructor().getConstructor(); if (auto *MD = ICI->findConstructorForBase(Class, BaseCtor).first) @@ -9392,15 +9412,15 @@ struct SpecialMemberDeletionInfo bool AllFieldsAreConst; SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD, - Sema::CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, Sema::InheritedConstructorInfo *ICI, bool Diagnose) : SpecialMemberVisitor(S, MD, CSM, ICI), Diagnose(Diagnose), Loc(MD->getLocation()), AllFieldsAreConst(true) {} bool inUnion() const { return MD->getParent()->isUnion(); } - Sema::CXXSpecialMember getEffectiveCSM() { - return ICI ? Sema::CXXInvalid : CSM; + CXXSpecialMemberKind getEffectiveCSM() { + return ICI ? CXXSpecialMemberKind::Invalid : CSM; } bool shouldDeleteForVariantObjCPtrMember(FieldDecl *FD, QualType FieldType); @@ -9466,7 +9486,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( // must be accessible and non-deleted, but need not be trivial. Such a // destructor is never actually called, but is semantically checked as // if it were. - if (CSM == Sema::CXXDefaultConstructor) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor) { // [class.default.ctor]p2: // A defaulted default constructor for class X is defined as deleted if // - X is a union that has a variant member with a non-trivial default @@ -9487,15 +9507,16 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( if (Field) { S.Diag(Field->getLocation(), diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << MD->getParent() << /*IsField*/true - << Field << DiagKind << IsDtorCallInCtor << /*IsObjCPtr*/false; + << llvm::to_underlying(getEffectiveCSM()) << MD->getParent() + << /*IsField*/ true << Field << DiagKind << IsDtorCallInCtor + << /*IsObjCPtr*/ false; } else { CXXBaseSpecifier *Base = Subobj.get(); S.Diag(Base->getBeginLoc(), diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << MD->getParent() << /*IsField*/ false - << Base->getType() << DiagKind << IsDtorCallInCtor - << /*IsObjCPtr*/false; + << llvm::to_underlying(getEffectiveCSM()) << MD->getParent() + << /*IsField*/ false << Base->getType() << DiagKind + << IsDtorCallInCtor << /*IsObjCPtr*/ false; } if (DiagKind == 1) @@ -9527,8 +9548,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( // C++11 [class.dtor]p5: // -- any direct or virtual base class [...] has a type with a destructor // that is deleted or inaccessible - if (!(CSM == Sema::CXXDefaultConstructor && - Field && Field->hasInClassInitializer()) && + if (!(CSM == CXXSpecialMemberKind::DefaultConstructor && Field && + Field->hasInClassInitializer()) && shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable), false)) return true; @@ -9538,8 +9559,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( // type with a destructor that is deleted or inaccessible if (IsConstructor) { Sema::SpecialMemberOverloadResult SMOR = - S.LookupSpecialMember(Class, Sema::CXXDestructor, - false, false, false, false, false); + S.LookupSpecialMember(Class, CXXSpecialMemberKind::Destructor, false, + false, false, false, false); if (shouldDeleteForSubobjectCall(Subobj, SMOR, true)) return true; } @@ -9557,15 +9578,16 @@ bool SpecialMemberDeletionInfo::shouldDeleteForVariantObjCPtrMember( // Don't make the defaulted default constructor defined as deleted if the // member has an in-class initializer. - if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + FD->hasInClassInitializer()) return false; if (Diagnose) { auto *ParentClass = cast(FD->getParent()); - S.Diag(FD->getLocation(), - diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << ParentClass << /*IsField*/true - << FD << 4 << /*IsDtorCallInCtor*/false << /*IsObjCPtr*/true; + S.Diag(FD->getLocation(), diag::note_deleted_special_member_class_subobject) + << llvm::to_underlying(getEffectiveCSM()) << ParentClass + << /*IsField*/ true << FD << 4 << /*IsDtorCallInCtor*/ false + << /*IsObjCPtr*/ true; } return true; @@ -9590,9 +9612,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { if (BaseCtor->isDeleted() && Diagnose) { S.Diag(Base->getBeginLoc(), diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << MD->getParent() << /*IsField*/ false - << Base->getType() << /*Deleted*/ 1 << /*IsDtorCallInCtor*/ false - << /*IsObjCPtr*/false; + << llvm::to_underlying(getEffectiveCSM()) << MD->getParent() + << /*IsField*/ false << Base->getType() << /*Deleted*/ 1 + << /*IsDtorCallInCtor*/ false << /*IsObjCPtr*/ false; S.NoteDeletedFunction(BaseCtor); } return BaseCtor->isDeleted(); @@ -9609,7 +9631,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { if (inUnion() && shouldDeleteForVariantObjCPtrMember(FD, FieldType)) return true; - if (CSM == Sema::CXXDefaultConstructor) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor) { // For a default constructor, all references must be initialized in-class // and, if a union, it must have a non-const member. if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) { @@ -9632,7 +9654,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { if (inUnion() && !FieldType.isConstQualified()) AllFieldsAreConst = false; - } else if (CSM == Sema::CXXCopyConstructor) { + } else if (CSM == CXXSpecialMemberKind::CopyConstructor) { // For a copy constructor, data members must not be of rvalue reference // type. if (FieldType->isRValueReferenceType()) { @@ -9683,8 +9705,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { } // At least one member in each anonymous union must be non-const - if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst && - !FieldRecord->field_empty()) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + AllVariantFieldsAreConst && !FieldRecord->field_empty()) { if (Diagnose) S.Diag(FieldRecord->getLocation(), diag::note_deleted_default_ctor_all_const) @@ -9712,7 +9734,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { // This is a silly definition, because it gives an empty union a deleted // default constructor. Don't do that. - if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor && inUnion() && + AllFieldsAreConst) { bool AnyFields = false; for (auto *F : MD->getParent()->fields()) if ((AnyFields = !F->isUnnamedBitfield())) @@ -9731,7 +9754,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { /// Determine whether a defaulted special member function should be defined as /// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11, /// C++11 [class.copy]p23, and C++11 [class.dtor]p5. -bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, +bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, + CXXSpecialMemberKind CSM, InheritedConstructorInfo *ICI, bool Diagnose) { if (MD->isInvalidDecl()) @@ -9748,7 +9772,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, // assignment operator. // C++2a adds back these operators if the lambda has no lambda-capture. if (RD->isLambda() && !RD->lambdaIsDefaultConstructibleAndAssignable() && - (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) { + (CSM == CXXSpecialMemberKind::DefaultConstructor || + CSM == CXXSpecialMemberKind::CopyAssignment)) { if (Diagnose) Diag(RD->getLocation(), diag::note_lambda_decl); return true; @@ -9757,16 +9782,16 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, // For an anonymous struct or union, the copy and assignment special members // will never be used, so skip the check. For an anonymous union declared at // namespace scope, the constructor and destructor are used. - if (CSM != CXXDefaultConstructor && CSM != CXXDestructor && - RD->isAnonymousStructOrUnion()) + if (CSM != CXXSpecialMemberKind::DefaultConstructor && + CSM != CXXSpecialMemberKind::Destructor && RD->isAnonymousStructOrUnion()) return false; // C++11 [class.copy]p7, p18: // If the class definition declares a move constructor or move assignment // operator, an implicitly declared copy constructor or copy assignment // operator is defined as deleted. - if (MD->isImplicit() && - (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) { + if (MD->isImplicit() && (CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::CopyAssignment)) { CXXMethodDecl *UserDeclaredMove = nullptr; // In Microsoft mode up to MSVC 2013, a user-declared move only causes the @@ -9777,7 +9802,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015); if (RD->hasUserDeclaredMoveConstructor() && - (!DeletesOnlyMatchingCopy || CSM == CXXCopyConstructor)) { + (!DeletesOnlyMatchingCopy || + CSM == CXXSpecialMemberKind::CopyConstructor)) { if (!Diagnose) return true; // Find any user-declared move constructor. @@ -9789,7 +9815,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, } assert(UserDeclaredMove); } else if (RD->hasUserDeclaredMoveAssignment() && - (!DeletesOnlyMatchingCopy || CSM == CXXCopyAssignment)) { + (!DeletesOnlyMatchingCopy || + CSM == CXXSpecialMemberKind::CopyAssignment)) { if (!Diagnose) return true; // Find any user-declared move assignment operator. @@ -9805,8 +9832,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, if (UserDeclaredMove) { Diag(UserDeclaredMove->getLocation(), diag::note_deleted_copy_user_declared_move) - << (CSM == CXXCopyAssignment) << RD - << UserDeclaredMove->isMoveAssignmentOperator(); + << (CSM == CXXSpecialMemberKind::CopyAssignment) << RD + << UserDeclaredMove->isMoveAssignmentOperator(); return true; } } @@ -9817,7 +9844,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, // C++11 [class.dtor]p5: // -- for a virtual destructor, lookup of the non-array deallocation function // results in an ambiguity or in a function that is deleted or inaccessible - if (CSM == CXXDestructor && MD->isVirtual()) { + if (CSM == CXXSpecialMemberKind::Destructor && MD->isVirtual()) { FunctionDecl *OperatorDelete = nullptr; DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); @@ -9891,7 +9918,7 @@ void Sema::DiagnoseDeletedDefaultedFunction(FunctionDecl *FD) { /// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to /// determine whether the special member is trivial. static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, - Sema::CXXSpecialMember CSM, unsigned Quals, + CXXSpecialMemberKind CSM, unsigned Quals, bool ConstRHS, Sema::TrivialABIHandling TAH, CXXMethodDecl **Selected) { @@ -9899,10 +9926,10 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, *Selected = nullptr; switch (CSM) { - case Sema::CXXInvalid: + case CXXSpecialMemberKind::Invalid: llvm_unreachable("not a special member"); - case Sema::CXXDefaultConstructor: + case CXXSpecialMemberKind::DefaultConstructor: // C++11 [class.ctor]p5: // A default constructor is trivial if: // - all the [direct subobjects] have trivial default constructors @@ -9931,7 +9958,7 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, return false; - case Sema::CXXDestructor: + case CXXSpecialMemberKind::Destructor: // C++11 [class.dtor]p5: // A destructor is trivial if: // - all the direct [subobjects] have trivial destructors @@ -9948,7 +9975,7 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, return false; - case Sema::CXXCopyConstructor: + case CXXSpecialMemberKind::CopyConstructor: // C++11 [class.copy]p12: // A copy constructor is trivial if: // - the constructor selected to copy each direct [subobject] is trivial @@ -9969,7 +9996,7 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, // struct B { mutable A a; }; goto NeedOverloadResolution; - case Sema::CXXCopyAssignment: + case CXXSpecialMemberKind::CopyAssignment: // C++11 [class.copy]p25: // A copy assignment operator is trivial if: // - the assignment operator selected to copy each direct [subobject] is @@ -9984,8 +10011,8 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, // treat that as a language defect. goto NeedOverloadResolution; - case Sema::CXXMoveConstructor: - case Sema::CXXMoveAssignment: + case CXXSpecialMemberKind::MoveConstructor: + case CXXSpecialMemberKind::MoveAssignment: NeedOverloadResolution: Sema::SpecialMemberOverloadResult SMOR = lookupCallFromSpecialMember(S, RD, CSM, Quals, ConstRHS); @@ -10009,7 +10036,8 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, *Selected = SMOR.getMethod(); if (TAH == Sema::TAH_ConsiderTrivialABI && - (CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor)) + (CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::MoveConstructor)) return SMOR.getMethod()->isTrivialForCall(); return SMOR.getMethod()->isTrivial(); } @@ -10047,9 +10075,10 @@ enum TrivialSubobjectKind { /// Check whether the special member selected for a given type would be trivial. static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, QualType SubType, bool ConstRHS, - Sema::CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, TrivialSubobjectKind Kind, - Sema::TrivialABIHandling TAH, bool Diagnose) { + Sema::TrivialABIHandling TAH, + bool Diagnose) { CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl(); if (!SubRD) return true; @@ -10063,27 +10092,28 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, if (ConstRHS) SubType.addConst(); - if (!Selected && CSM == Sema::CXXDefaultConstructor) { + if (!Selected && CSM == CXXSpecialMemberKind::DefaultConstructor) { S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor) << Kind << SubType.getUnqualifiedType(); if (CXXConstructorDecl *CD = findUserDeclaredCtor(SubRD)) S.Diag(CD->getLocation(), diag::note_user_declared_ctor); } else if (!Selected) S.Diag(SubobjLoc, diag::note_nontrivial_no_copy) - << Kind << SubType.getUnqualifiedType() << CSM << SubType; + << Kind << SubType.getUnqualifiedType() << llvm::to_underlying(CSM) + << SubType; else if (Selected->isUserProvided()) { if (Kind == TSK_CompleteObject) S.Diag(Selected->getLocation(), diag::note_nontrivial_user_provided) - << Kind << SubType.getUnqualifiedType() << CSM; + << Kind << SubType.getUnqualifiedType() << llvm::to_underlying(CSM); else { S.Diag(SubobjLoc, diag::note_nontrivial_user_provided) - << Kind << SubType.getUnqualifiedType() << CSM; + << Kind << SubType.getUnqualifiedType() << llvm::to_underlying(CSM); S.Diag(Selected->getLocation(), diag::note_declared_at); } } else { if (Kind != TSK_CompleteObject) S.Diag(SubobjLoc, diag::note_nontrivial_subobject) - << Kind << SubType.getUnqualifiedType() << CSM; + << Kind << SubType.getUnqualifiedType() << llvm::to_underlying(CSM); // Explain why the defaulted or deleted special member isn't trivial. S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI, @@ -10097,8 +10127,7 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, /// Check whether the members of a class type allow a special member to be /// trivial. static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, - Sema::CXXSpecialMember CSM, - bool ConstArg, + CXXSpecialMemberKind CSM, bool ConstArg, Sema::TrivialABIHandling TAH, bool Diagnose) { for (const auto *FI : RD->fields()) { @@ -10119,7 +10148,8 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, // A default constructor is trivial if [...] // -- no non-static data member of its class has a // brace-or-equal-initializer - if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + FI->hasInClassInitializer()) { if (Diagnose) S.Diag(FI->getLocation(), diag::note_nontrivial_default_member_init) << FI; @@ -10148,10 +10178,12 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, /// Diagnose why the specified class does not have a trivial special member of /// the given kind. -void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) { +void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, + CXXSpecialMemberKind CSM) { QualType Ty = Context.getRecordType(RD); - bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment); + bool ConstArg = (CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::CopyAssignment); checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM, TSK_CompleteObject, TAH_IgnoreTrivialABI, /*Diagnose*/true); @@ -10160,9 +10192,10 @@ void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) { /// Determine whether a defaulted or deleted special member function is trivial, /// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12, /// C++11 [class.copy]p25, and C++11 [class.dtor]p5. -bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, +bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, TrivialABIHandling TAH, bool Diagnose) { - assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough"); + assert(!MD->isUserProvided() && CSM != CXXSpecialMemberKind::Invalid && + "not special enough"); CXXRecordDecl *RD = MD->getParent(); @@ -10172,13 +10205,13 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // A [special member] is trivial if [...] its parameter-type-list is // equivalent to the parameter-type-list of an implicit declaration [...] switch (CSM) { - case CXXDefaultConstructor: - case CXXDestructor: + case CXXSpecialMemberKind::DefaultConstructor: + case CXXSpecialMemberKind::Destructor: // Trivial default constructors and destructors cannot have parameters. break; - case CXXCopyConstructor: - case CXXCopyAssignment: { + case CXXSpecialMemberKind::CopyConstructor: + case CXXSpecialMemberKind::CopyAssignment: { const ParmVarDecl *Param0 = MD->getNonObjectParameter(0); const ReferenceType *RT = Param0->getType()->getAs(); @@ -10207,8 +10240,8 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, break; } - case CXXMoveConstructor: - case CXXMoveAssignment: { + case CXXSpecialMemberKind::MoveConstructor: + case CXXSpecialMemberKind::MoveAssignment: { // Trivial move operations always have non-cv-qualified parameters. const ParmVarDecl *Param0 = MD->getNonObjectParameter(0); const RValueReferenceType *RT = @@ -10223,7 +10256,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, break; } - case CXXInvalid: + case CXXSpecialMemberKind::Invalid: llvm_unreachable("not a special member"); } @@ -10272,7 +10305,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // C++11 [class.dtor]p5: // A destructor is trivial if [...] // -- the destructor is not virtual - if (CSM == CXXDestructor && MD->isVirtual()) { + if (CSM == CXXSpecialMemberKind::Destructor && MD->isVirtual()) { if (Diagnose) Diag(MD->getLocation(), diag::note_nontrivial_virtual_dtor) << RD; return false; @@ -10281,7 +10314,8 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: // A [special member] for class X is trivial if [...] // -- class X has no virtual functions and no virtual base classes - if (CSM != CXXDestructor && MD->getParent()->isDynamicClass()) { + if (CSM != CXXSpecialMemberKind::Destructor && + MD->getParent()->isDynamicClass()) { if (!Diagnose) return false; @@ -13760,7 +13794,7 @@ struct SpecialMemberExceptionSpecInfo Sema::ImplicitExceptionSpecification ExceptSpec; SpecialMemberExceptionSpecInfo(Sema &S, CXXMethodDecl *MD, - Sema::CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, Sema::InheritedConstructorInfo *ICI, SourceLocation Loc) : SpecialMemberVisitor(S, MD, CSM, ICI), Loc(Loc), ExceptSpec(S) {} @@ -13793,7 +13827,8 @@ bool SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) { } bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) { - if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + FD->hasInClassInitializer()) { Expr *E = FD->getInClassInitializer(); if (!E) // FIXME: It's a little wasteful to build and throw away a @@ -13852,7 +13887,7 @@ ExplicitSpecifier Sema::ActOnExplicitBoolSpecifier(Expr *ExplicitExpr) { static Sema::ImplicitExceptionSpecification ComputeDefaultedSpecialMemberExceptionSpec( - Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, + Sema &S, SourceLocation Loc, CXXMethodDecl *MD, CXXSpecialMemberKind CSM, Sema::InheritedConstructorInfo *ICI) { ComputingExceptionSpec CES(S, MD, Loc); @@ -13902,7 +13937,7 @@ struct DeclaringSpecialMember { Sema::ContextRAII SavedContext; bool WasAlreadyBeingDeclared; - DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM) + DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, CXXSpecialMemberKind CSM) : S(S), D(RD, CSM), SavedContext(S, RD) { WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D).second; if (WasAlreadyBeingDeclared) @@ -13992,13 +14027,13 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( assert(ClassDecl->needsImplicitDefaultConstructor() && "Should not build implicit default constructor!"); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::DefaultConstructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXDefaultConstructor, - false); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::DefaultConstructor, false); // Create the actual constructor declaration. CanQualType ClassType @@ -14020,10 +14055,10 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( setupImplicitSpecialMemberType(DefaultCon, Context.VoidTy, std::nullopt); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDefaultConstructor, - DefaultCon, - /* ConstRHS */ false, - /* Diagnose */ false); + inferCUDATargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::DefaultConstructor, DefaultCon, + /* ConstRHS */ false, + /* Diagnose */ false); // We don't need to use SpecialMemberIsTrivial here; triviality for default // constructors is easy to compute. @@ -14035,7 +14070,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, DefaultCon); - if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) + if (ShouldDeleteSpecialMember(DefaultCon, + CXXSpecialMemberKind::DefaultConstructor)) SetDeclDeleted(DefaultCon, ClassLoc); if (S) @@ -14127,10 +14163,10 @@ Sema::findInheritingConstructor(SourceLocation Loc, // from which it was inherited. InheritedConstructorInfo ICI(*this, Loc, Shadow); - bool Constexpr = - BaseCtor->isConstexpr() && - defaultedSpecialMemberIsConstexpr(*this, Derived, CXXDefaultConstructor, - false, BaseCtor, &ICI); + bool Constexpr = BaseCtor->isConstexpr() && + defaultedSpecialMemberIsConstexpr( + *this, Derived, CXXSpecialMemberKind::DefaultConstructor, + false, BaseCtor, &ICI); CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, @@ -14174,7 +14210,8 @@ Sema::findInheritingConstructor(SourceLocation Loc, DerivedCtor->setParams(ParamDecls); Derived->addDecl(DerivedCtor); - if (ShouldDeleteSpecialMember(DerivedCtor, CXXDefaultConstructor, &ICI)) + if (ShouldDeleteSpecialMember(DerivedCtor, + CXXSpecialMemberKind::DefaultConstructor, &ICI)) SetDeclDeleted(DerivedCtor, UsingLoc); return DerivedCtor; @@ -14183,8 +14220,9 @@ Sema::findInheritingConstructor(SourceLocation Loc, void Sema::NoteDeletedInheritingConstructor(CXXConstructorDecl *Ctor) { InheritedConstructorInfo ICI(*this, Ctor->getLocation(), Ctor->getInheritedConstructor().getShadowDecl()); - ShouldDeleteSpecialMember(Ctor, CXXDefaultConstructor, &ICI, - /*Diagnose*/true); + ShouldDeleteSpecialMember(Ctor, CXXSpecialMemberKind::DefaultConstructor, + &ICI, + /*Diagnose*/ true); } void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, @@ -14275,13 +14313,13 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // inline public member of its class. assert(ClassDecl->needsImplicitDestructor()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::Destructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXDestructor, - false); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::Destructor, false); // Create the actual destructor declaration. CanQualType ClassType @@ -14303,10 +14341,10 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { setupImplicitSpecialMemberType(Destructor, Context.VoidTy, std::nullopt); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDestructor, - Destructor, - /* ConstRHS */ false, - /* Diagnose */ false); + inferCUDATargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::Destructor, Destructor, + /* ConstRHS */ false, + /* Diagnose */ false); // We don't need to use SpecialMemberIsTrivial here; triviality for // destructors is easy to compute. @@ -14324,7 +14362,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // the definition of the class, because its validity depends on the alignment // of the class. We'll check this from ActOnFields once the class is complete. if (ClassDecl->isCompleteDefinition() && - ShouldDeleteSpecialMember(Destructor, CXXDestructor)) + ShouldDeleteSpecialMember(Destructor, CXXSpecialMemberKind::Destructor)) SetDeclDeleted(Destructor, ClassLoc); // Introduce this destructor into its scope. @@ -14905,7 +14943,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // operators taking an object instead of a reference are allowed. assert(ClassDecl->needsImplicitCopyAssignment()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::CopyAssignment); if (DSM.isAlreadyBeingDeclared()) return nullptr; @@ -14922,9 +14961,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { ArgType = Context.getLValueReferenceType(ArgType); - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXCopyAssignment, - Const); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::CopyAssignment, Const); // An implicitly-declared copy assignment operator is an inline public // member of its class. @@ -14945,10 +14983,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { setupImplicitSpecialMemberType(CopyAssignment, RetType, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyAssignment, - CopyAssignment, - /* ConstRHS */ Const, - /* Diagnose */ false); + inferCUDATargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::CopyAssignment, CopyAssignment, + /* ConstRHS */ Const, + /* Diagnose */ false); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, @@ -14959,9 +14997,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { CopyAssignment->setParams(FromParam); CopyAssignment->setTrivial( - ClassDecl->needsOverloadResolutionForCopyAssignment() - ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment) - : ClassDecl->hasTrivialCopyAssignment()); + ClassDecl->needsOverloadResolutionForCopyAssignment() + ? SpecialMemberIsTrivial(CopyAssignment, + CXXSpecialMemberKind::CopyAssignment) + : ClassDecl->hasTrivialCopyAssignment()); // Note that we have added this copy-assignment operator. ++getASTContext().NumImplicitCopyAssignmentOperatorsDeclared; @@ -14969,7 +15008,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, CopyAssignment); - if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) { + if (ShouldDeleteSpecialMember(CopyAssignment, + CXXSpecialMemberKind::CopyAssignment)) { ClassDecl->setImplicitCopyAssignmentIsDeleted(); SetDeclDeleted(CopyAssignment, ClassLoc); } @@ -15256,7 +15296,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { assert(ClassDecl->needsImplicitMoveAssignment()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::MoveAssignment); if (DSM.isAlreadyBeingDeclared()) return nullptr; @@ -15272,9 +15313,8 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { QualType RetType = Context.getLValueReferenceType(ArgType); ArgType = Context.getRValueReferenceType(ArgType); - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXMoveAssignment, - false); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::MoveAssignment, false); // An implicitly-declared move assignment operator is an inline public // member of its class. @@ -15295,10 +15335,10 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveAssignment, - MoveAssignment, - /* ConstRHS */ false, - /* Diagnose */ false); + inferCUDATargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::MoveAssignment, MoveAssignment, + /* ConstRHS */ false, + /* Diagnose */ false); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment, @@ -15309,9 +15349,10 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { MoveAssignment->setParams(FromParam); MoveAssignment->setTrivial( - ClassDecl->needsOverloadResolutionForMoveAssignment() - ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment) - : ClassDecl->hasTrivialMoveAssignment()); + ClassDecl->needsOverloadResolutionForMoveAssignment() + ? SpecialMemberIsTrivial(MoveAssignment, + CXXSpecialMemberKind::MoveAssignment) + : ClassDecl->hasTrivialMoveAssignment()); // Note that we have added this copy-assignment operator. ++getASTContext().NumImplicitMoveAssignmentOperatorsDeclared; @@ -15319,7 +15360,8 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, MoveAssignment); - if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) { + if (ShouldDeleteSpecialMember(MoveAssignment, + CXXSpecialMemberKind::MoveAssignment)) { ClassDecl->setImplicitMoveAssignmentIsDeleted(); SetDeclDeleted(MoveAssignment, ClassLoc); } @@ -15368,10 +15410,10 @@ static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class, // If we're not actually going to call a move assignment for this base, // or the selected move assignment is trivial, skip it. Sema::SpecialMemberOverloadResult SMOR = - S.LookupSpecialMember(Base, Sema::CXXMoveAssignment, - /*ConstArg*/false, /*VolatileArg*/false, - /*RValueThis*/true, /*ConstThis*/false, - /*VolatileThis*/false); + S.LookupSpecialMember(Base, CXXSpecialMemberKind::MoveAssignment, + /*ConstArg*/ false, /*VolatileArg*/ false, + /*RValueThis*/ true, /*ConstThis*/ false, + /*VolatileThis*/ false); if (!SMOR.getMethod() || SMOR.getMethod()->isTrivial() || !SMOR.getMethod()->isMoveAssignmentOperator()) continue; @@ -15648,7 +15690,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // constructor, one is declared implicitly. assert(ClassDecl->needsImplicitCopyConstructor()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::CopyConstructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; @@ -15666,9 +15709,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( ArgType = Context.getLValueReferenceType(ArgType); - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXCopyConstructor, - Const); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::CopyConstructor, Const); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( @@ -15691,10 +15733,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( setupImplicitSpecialMemberType(CopyConstructor, Context.VoidTy, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyConstructor, - CopyConstructor, - /* ConstRHS */ Const, - /* Diagnose */ false); + inferCUDATargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::CopyConstructor, CopyConstructor, + /* ConstRHS */ Const, + /* Diagnose */ false); // During template instantiation of special member functions we need a // reliable TypeSourceInfo for the parameter types in order to allow functions @@ -15712,14 +15754,16 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( CopyConstructor->setTrivial( ClassDecl->needsOverloadResolutionForCopyConstructor() - ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) + ? SpecialMemberIsTrivial(CopyConstructor, + CXXSpecialMemberKind::CopyConstructor) : ClassDecl->hasTrivialCopyConstructor()); CopyConstructor->setTrivialForCall( ClassDecl->hasAttr() || (ClassDecl->needsOverloadResolutionForCopyConstructor() - ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor, - TAH_ConsiderTrivialABI) + ? SpecialMemberIsTrivial(CopyConstructor, + CXXSpecialMemberKind::CopyConstructor, + TAH_ConsiderTrivialABI) : ClassDecl->hasTrivialCopyConstructorForCall())); // Note that we have declared this constructor. @@ -15728,7 +15772,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, CopyConstructor); - if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) { + if (ShouldDeleteSpecialMember(CopyConstructor, + CXXSpecialMemberKind::CopyConstructor)) { ClassDecl->setImplicitCopyConstructorIsDeleted(); SetDeclDeleted(CopyConstructor, ClassLoc); } @@ -15793,7 +15838,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( CXXRecordDecl *ClassDecl) { assert(ClassDecl->needsImplicitMoveConstructor()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::MoveConstructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; @@ -15807,9 +15853,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( ArgType = Context.getAddrSpaceQualType(ClassType, AS); ArgType = Context.getRValueReferenceType(ArgType); - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXMoveConstructor, - false); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::MoveConstructor, false); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( @@ -15833,10 +15878,10 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( setupImplicitSpecialMemberType(MoveConstructor, Context.VoidTy, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveConstructor, - MoveConstructor, - /* ConstRHS */ false, - /* Diagnose */ false); + inferCUDATargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::MoveConstructor, MoveConstructor, + /* ConstRHS */ false, + /* Diagnose */ false); // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, @@ -15848,13 +15893,15 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( MoveConstructor->setTrivial( ClassDecl->needsOverloadResolutionForMoveConstructor() - ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) + ? SpecialMemberIsTrivial(MoveConstructor, + CXXSpecialMemberKind::MoveConstructor) : ClassDecl->hasTrivialMoveConstructor()); MoveConstructor->setTrivialForCall( ClassDecl->hasAttr() || (ClassDecl->needsOverloadResolutionForMoveConstructor() - ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor, + ? SpecialMemberIsTrivial(MoveConstructor, + CXXSpecialMemberKind::MoveConstructor, TAH_ConsiderTrivialABI) : ClassDecl->hasTrivialMoveConstructorForCall())); @@ -15864,7 +15911,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, MoveConstructor); - if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) { + if (ShouldDeleteSpecialMember(MoveConstructor, + CXXSpecialMemberKind::MoveConstructor)) { ClassDecl->setImplicitMoveConstructorIsDeleted(); SetDeclDeleted(MoveConstructor, ClassLoc); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a75e9925a431..6b8ce0f633a3 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -31,6 +31,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -10023,8 +10024,9 @@ bool InitializationSequence::Diagnose(Sema &S, // implicit. if (S.isImplicitlyDeleted(Best->Function)) S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init) - << S.getSpecialMember(cast(Best->Function)) - << DestType << ArgsRange; + << llvm::to_underlying( + S.getSpecialMember(cast(Best->Function))) + << DestType << ArgsRange; else S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) << DestType << ArgsRange; diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 38237ee57807..d65f52b8efe8 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -37,6 +37,7 @@ #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/edit_distance.h" @@ -3341,21 +3342,20 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, Functions.append(Operators.begin(), Operators.end()); } -Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, - CXXSpecialMember SM, - bool ConstArg, - bool VolatileArg, - bool RValueThis, - bool ConstThis, - bool VolatileThis) { +Sema::SpecialMemberOverloadResult +Sema::LookupSpecialMember(CXXRecordDecl *RD, CXXSpecialMemberKind SM, + bool ConstArg, bool VolatileArg, bool RValueThis, + bool ConstThis, bool VolatileThis) { assert(CanDeclareSpecialMemberFunction(RD) && "doing special member lookup into record that isn't fully complete"); RD = RD->getDefinition(); if (RValueThis || ConstThis || VolatileThis) - assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) && + assert((SM == CXXSpecialMemberKind::CopyAssignment || + SM == CXXSpecialMemberKind::MoveAssignment) && "constructors and destructors always have unqualified lvalue this"); if (ConstArg || VolatileArg) - assert((SM != CXXDefaultConstructor && SM != CXXDestructor) && + assert((SM != CXXSpecialMemberKind::DefaultConstructor && + SM != CXXSpecialMemberKind::Destructor) && "parameter-less special members can't have qualified arguments"); // FIXME: Get the caller to pass in a location for the lookup. @@ -3363,7 +3363,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, llvm::FoldingSetNodeID ID; ID.AddPointer(RD); - ID.AddInteger(SM); + ID.AddInteger(llvm::to_underlying(SM)); ID.AddInteger(ConstArg); ID.AddInteger(VolatileArg); ID.AddInteger(RValueThis); @@ -3382,7 +3382,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, Result = new (Result) SpecialMemberOverloadResultEntry(ID); SpecialMemberCache.InsertNode(Result, InsertPoint); - if (SM == CXXDestructor) { + if (SM == CXXSpecialMemberKind::Destructor) { if (RD->needsImplicitDestructor()) { runWithSufficientStackSpace(RD->getLocation(), [&] { DeclareImplicitDestructor(RD); @@ -3406,7 +3406,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, QualType ArgType = CanTy; ExprValueKind VK = VK_LValue; - if (SM == CXXDefaultConstructor) { + if (SM == CXXSpecialMemberKind::DefaultConstructor) { Name = Context.DeclarationNames.getCXXConstructorName(CanTy); NumArgs = 0; if (RD->needsImplicitDefaultConstructor()) { @@ -3415,7 +3415,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, }); } } else { - if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) { + if (SM == CXXSpecialMemberKind::CopyConstructor || + SM == CXXSpecialMemberKind::MoveConstructor) { Name = Context.DeclarationNames.getCXXConstructorName(CanTy); if (RD->needsImplicitCopyConstructor()) { runWithSufficientStackSpace(RD->getLocation(), [&] { @@ -3453,7 +3454,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, // Possibly an XValue is actually correct in the case of move, but // there is no semantic difference for class types in this restricted // case. - if (SM == CXXCopyConstructor || SM == CXXCopyAssignment) + if (SM == CXXSpecialMemberKind::CopyConstructor || + SM == CXXSpecialMemberKind::CopyAssignment) VK = VK_LValue; else VK = VK_PRValue; @@ -3461,7 +3463,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, OpaqueValueExpr FakeArg(LookupLoc, ArgType, VK); - if (SM != CXXDefaultConstructor) { + if (SM != CXXSpecialMemberKind::DefaultConstructor) { NumArgs = 1; Arg = &FakeArg; } @@ -3487,7 +3489,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, // type, rather than because there's some other declared constructor. // Every class has a copy/move constructor, copy/move assignment, and // destructor. - assert(SM == CXXDefaultConstructor && + assert(SM == CXXSpecialMemberKind::DefaultConstructor && "lookup for a constructor or assignment operator was empty"); Result->setMethod(nullptr); Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted); @@ -3505,7 +3507,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, DeclAccessPair Cand = DeclAccessPair::make(CandDecl, AS_public); auto CtorInfo = getConstructorInfo(Cand); if (CXXMethodDecl *M = dyn_cast(Cand->getUnderlyingDecl())) { - if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) + if (SM == CXXSpecialMemberKind::CopyAssignment || + SM == CXXSpecialMemberKind::MoveAssignment) AddMethodCandidate(M, Cand, RD, ThisTy, Classification, llvm::ArrayRef(&Arg, NumArgs), OCS, true); else if (CtorInfo) @@ -3517,7 +3520,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, /*SuppressUserConversions*/ true); } else if (FunctionTemplateDecl *Tmpl = dyn_cast(Cand->getUnderlyingDecl())) { - if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) + if (SM == CXXSpecialMemberKind::CopyAssignment || + SM == CXXSpecialMemberKind::MoveAssignment) AddMethodTemplateCandidate(Tmpl, Cand, RD, nullptr, ThisTy, Classification, llvm::ArrayRef(&Arg, NumArgs), OCS, true); @@ -3563,8 +3567,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, /// Look up the default constructor for the given class. CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) { SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false, - false, false); + LookupSpecialMember(Class, CXXSpecialMemberKind::DefaultConstructor, + false, false, false, false, false); return cast_or_null(Result.getMethod()); } @@ -3574,9 +3578,9 @@ CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class, unsigned Quals) { assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy ctor arg"); - SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXCopyConstructor, Quals & Qualifiers::Const, - Quals & Qualifiers::Volatile, false, false, false); + SpecialMemberOverloadResult Result = LookupSpecialMember( + Class, CXXSpecialMemberKind::CopyConstructor, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, false, false, false); return cast_or_null(Result.getMethod()); } @@ -3584,9 +3588,9 @@ CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class, /// Look up the moving constructor for the given class. CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class, unsigned Quals) { - SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXMoveConstructor, Quals & Qualifiers::Const, - Quals & Qualifiers::Volatile, false, false, false); + SpecialMemberOverloadResult Result = LookupSpecialMember( + Class, CXXSpecialMemberKind::MoveConstructor, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, false, false, false); return cast_or_null(Result.getMethod()); } @@ -3618,11 +3622,10 @@ CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class, "non-const, non-volatile qualifiers for copy assignment arg"); assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy assignment this"); - SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXCopyAssignment, Quals & Qualifiers::Const, - Quals & Qualifiers::Volatile, RValueThis, - ThisQuals & Qualifiers::Const, - ThisQuals & Qualifiers::Volatile); + SpecialMemberOverloadResult Result = LookupSpecialMember( + Class, CXXSpecialMemberKind::CopyAssignment, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, RValueThis, ThisQuals & Qualifiers::Const, + ThisQuals & Qualifiers::Volatile); return Result.getMethod(); } @@ -3634,11 +3637,10 @@ CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class, unsigned ThisQuals) { assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy assignment this"); - SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXMoveAssignment, Quals & Qualifiers::Const, - Quals & Qualifiers::Volatile, RValueThis, - ThisQuals & Qualifiers::Const, - ThisQuals & Qualifiers::Volatile); + SpecialMemberOverloadResult Result = LookupSpecialMember( + Class, CXXSpecialMemberKind::MoveAssignment, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, RValueThis, ThisQuals & Qualifiers::Const, + ThisQuals & Qualifiers::Volatile); return Result.getMethod(); } @@ -3651,8 +3653,8 @@ CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class, /// \returns The destructor for this class. CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { return cast_or_null( - LookupSpecialMember(Class, CXXDestructor, false, false, false, false, - false) + LookupSpecialMember(Class, CXXSpecialMemberKind::Destructor, false, false, + false, false, false) .getMethod()); } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 3808af37ff54..1f674dd4bb0f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -36,6 +36,7 @@ #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -11955,25 +11956,25 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { CXXMethodDecl *Meth = dyn_cast(Callee); if (Meth != nullptr && Meth->isImplicit()) { CXXRecordDecl *ParentClass = Meth->getParent(); - Sema::CXXSpecialMember CSM; + CXXSpecialMemberKind CSM; switch (FnKindPair.first) { default: return; case oc_implicit_default_constructor: - CSM = Sema::CXXDefaultConstructor; + CSM = CXXSpecialMemberKind::DefaultConstructor; break; case oc_implicit_copy_constructor: - CSM = Sema::CXXCopyConstructor; + CSM = CXXSpecialMemberKind::CopyConstructor; break; case oc_implicit_move_constructor: - CSM = Sema::CXXMoveConstructor; + CSM = CXXSpecialMemberKind::MoveConstructor; break; case oc_implicit_copy_assignment: - CSM = Sema::CXXCopyAssignment; + CSM = CXXSpecialMemberKind::CopyAssignment; break; case oc_implicit_move_assignment: - CSM = Sema::CXXMoveAssignment; + CSM = CXXSpecialMemberKind::MoveAssignment; break; }; @@ -15064,7 +15065,8 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, DefaultedFunctionKind DFK = getDefaultedFunctionKind(DeletedFD); if (DFK.isSpecialMember()) { Diag(OpLoc, diag::err_ovl_deleted_special_oper) - << Args[0]->getType() << DFK.asSpecialMember(); + << Args[0]->getType() + << llvm::to_underlying(DFK.asSpecialMember()); } else { assert(DFK.isComparison()); Diag(OpLoc, diag::err_ovl_deleted_comparison) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index a265fd1c46a6..7cd428de0bb3 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -36,6 +36,7 @@ #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TemplateInstCallback.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeProfiler.h" @@ -1142,7 +1143,8 @@ void Sema::PrintInstantiationStack() { case CodeSynthesisContext::DeclaringSpecialMember: Diags.Report(Active->PointOfInstantiation, diag::note_in_declaration_of_implicit_special_member) - << cast(Active->Entity) << Active->SpecialMember; + << cast(Active->Entity) + << llvm::to_underlying(Active->SpecialMember); break; case CodeSynthesisContext::DeclaringImplicitEqualityComparison: @@ -1160,7 +1162,8 @@ void Sema::PrintInstantiationStack() { auto *MD = cast(FD); Diags.Report(Active->PointOfInstantiation, diag::note_member_synthesized_at) - << MD->isExplicitlyDefaulted() << DFK.asSpecialMember() + << MD->isExplicitlyDefaulted() + << llvm::to_underlying(DFK.asSpecialMember()) << Context.getTagDeclType(MD->getParent()); } else if (DFK.isComparison()) { QualType RecordType = FD->getParamDecl(0) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 707446e13209..7f510d34d671 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5123,10 +5123,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, assert(PatternDecl->isDefaulted() && "Special member needs to be defaulted"); auto PatternSM = getDefaultedFunctionKind(PatternDecl).asSpecialMember(); - if (!(PatternSM == Sema::CXXCopyConstructor || - PatternSM == Sema::CXXCopyAssignment || - PatternSM == Sema::CXXMoveConstructor || - PatternSM == Sema::CXXMoveAssignment)) + if (!(PatternSM == CXXSpecialMemberKind::CopyConstructor || + PatternSM == CXXSpecialMemberKind::CopyAssignment || + PatternSM == CXXSpecialMemberKind::MoveConstructor || + PatternSM == CXXSpecialMemberKind::MoveAssignment)) return; auto *NewRec = dyn_cast(Function->getDeclContext()); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 8762744396f4..b8a1518fbe00 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -9738,7 +9738,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, : diag::note_non_literal_nontrivial_dtor) << RD; if (!Dtor->isUserProvided()) - SpecialMemberIsTrivial(Dtor, CXXDestructor, TAH_IgnoreTrivialABI, + SpecialMemberIsTrivial(Dtor, CXXSpecialMemberKind::Destructor, + TAH_IgnoreTrivialABI, /*Diagnose*/ true); } } -- GitLab From 9250aedb5cabf0e44c694f0c8e68ae03e937be89 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Fri, 12 Apr 2024 11:21:48 +0200 Subject: [PATCH 042/464] [SCEV] Add range attribute handling (#88449) --- llvm/lib/Analysis/ScalarEvolution.cpp | 9 ++- .../ScalarEvolution/range-attribute.ll | 74 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Analysis/ScalarEvolution/range-attribute.ll diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 9fcce797f559..95440dda3b4c 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -6382,9 +6382,16 @@ uint32_t ScalarEvolution::getMinTrailingZeros(const SCEV *S) { /// Helper method to assign a range to V from metadata present in the IR. static std::optional GetRangeFromMetadata(Value *V) { - if (Instruction *I = dyn_cast(V)) + if (Instruction *I = dyn_cast(V)) { if (MDNode *MD = I->getMetadata(LLVMContext::MD_range)) return getConstantRangeFromMetadata(*MD); + if (const auto *CB = dyn_cast(V)) + if (std::optional Range = CB->getRange()) + return Range; + } + if (auto *A = dyn_cast(V)) + if (std::optional Range = A->getRange()) + return Range; return std::nullopt; } diff --git a/llvm/test/Analysis/ScalarEvolution/range-attribute.ll b/llvm/test/Analysis/ScalarEvolution/range-attribute.ll new file mode 100644 index 000000000000..ea22695e58d1 --- /dev/null +++ b/llvm/test/Analysis/ScalarEvolution/range-attribute.ll @@ -0,0 +1,74 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -disable-output "-passes=print" -scalar-evolution-classify-expressions=0 < %s 2>&1 | FileCheck %s + +define i32 @slt_trip_count_with_range_attr(i32 range(i32 1, 100) %limit) { +; +; CHECK-LABEL: 'slt_trip_count_with_range_attr' +; CHECK-NEXT: Determining loop execution counts for: @slt_trip_count_with_range_attr +; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %limit) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 98 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is (-1 + %limit) +; CHECK-NEXT: Loop %loop: Trip multiple is 1 +; + entry: + br label %loop + + loop: + %index = phi i32 [ 0, %entry ], [ %index.inc, %loop ] + %index.inc = add i32 %index, 1 + %continue = icmp slt i32 %index.inc, %limit + br i1 %continue, label %loop, label %loop.exit + + loop.exit: + ret i32 0 +} + +declare i32 @get_i32() + +define i32 @slt_trip_count_with_range_call() { +; +; CHECK-LABEL: 'slt_trip_count_with_range_call' +; CHECK-NEXT: Determining loop execution counts for: @slt_trip_count_with_range_call +; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %limit) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 98 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is (-1 + %limit) +; CHECK-NEXT: Loop %loop: Trip multiple is 1 +; + entry: + %limit = call range(i32 1, 100) i32 @get_i32() + br label %loop + + loop: + %index = phi i32 [ 0, %entry ], [ %index.inc, %loop ] + %index.inc = add i32 %index, 1 + %continue = icmp slt i32 %index.inc, %limit + br i1 %continue, label %loop, label %loop.exit + + loop.exit: + ret i32 0 +} + +declare range(i32 1, 100) i32 @get_i32_in_range() + +define i32 @slt_trip_count_with_range_result() { +; +; CHECK-LABEL: 'slt_trip_count_with_range_result' +; CHECK-NEXT: Determining loop execution counts for: @slt_trip_count_with_range_result +; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %limit) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i32 98 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is (-1 + %limit) +; CHECK-NEXT: Loop %loop: Trip multiple is 1 +; + entry: + %limit = call i32 @get_i32_in_range() + br label %loop + + loop: + %index = phi i32 [ 0, %entry ], [ %index.inc, %loop ] + %index.inc = add i32 %index, 1 + %continue = icmp slt i32 %index.inc, %limit + br i1 %continue, label %loop, label %loop.exit + + loop.exit: + ret i32 0 +} -- GitLab From 5d6b00929bd026d1448a5dd3a8341ea99b3befe1 Mon Sep 17 00:00:00 2001 From: AtariDreams Date: Fri, 12 Apr 2024 05:24:03 -0400 Subject: [PATCH 043/464] [NFC] Replace m_Sub(m_Zero(), X) with m_Neg(X) (#88461) --- llvm/lib/Analysis/InstructionSimplify.cpp | 2 +- llvm/lib/Analysis/ValueTracking.cpp | 4 ++-- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 2 +- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 7 +++---- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 3c943a09a9c2..1aaa4d658803 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -5052,7 +5052,7 @@ static Value *simplifyGEPInst(Type *SrcTy, Value *Ptr, // gep (gep V, C), (sub 0, V) -> C if (match(Indices.back(), - m_Sub(m_Zero(), m_PtrToInt(m_Specific(StrippedBasePtr)))) && + m_Neg(m_PtrToInt(m_Specific(StrippedBasePtr)))) && !BasePtrOffset.isZero()) { auto *CI = ConstantInt::get(GEPTy->getContext(), BasePtrOffset); return ConstantExpr::getIntToPtr(CI, GEPTy); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index eb8925c53475..ca257cc6aefd 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -8016,12 +8016,12 @@ bool llvm::isKnownNegation(const Value *X, const Value *Y, bool NeedNSW) { // X = sub (0, Y) || X = sub nsw (0, Y) if ((!NeedNSW && match(X, m_Sub(m_ZeroInt(), m_Specific(Y)))) || - (NeedNSW && match(X, m_NSWSub(m_ZeroInt(), m_Specific(Y))))) + (NeedNSW && match(X, m_NSWNeg(m_Specific(Y))))) return true; // Y = sub (0, X) || Y = sub nsw (0, X) if ((!NeedNSW && match(Y, m_Sub(m_ZeroInt(), m_Specific(X)))) || - (NeedNSW && match(Y, m_NSWSub(m_ZeroInt(), m_Specific(X))))) + (NeedNSW && match(Y, m_NSWNeg(m_Specific(X))))) return true; // X = sub (A, B), Y = sub (B, A) || X = sub nsw (A, B), Y = sub nsw (B, A) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 1dd0fa49a460..e002cf1d1de3 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4308,7 +4308,7 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth) const { // x & -x -> non-zero pow2 // so if we find the pattern return whether we know `x` is non-zero. SDValue X; - if (sd_match(Val, m_And(m_Value(X), m_Sub(m_Zero(), m_Deferred(X))))) + if (sd_match(Val, m_And(m_Value(X), m_Neg(m_Deferred(X))))) return isKnownNeverZero(X, Depth); if (Val.getOpcode() == ISD::ZERO_EXTEND) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 8c698e52b5a0..4dc1319f1c43 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1572,8 +1572,7 @@ Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) { // -X / C --> X / -C (if the negation doesn't overflow). // TODO: This could be enhanced to handle arbitrary vector constants by // checking if all elements are not the min-signed-val. - if (!Op1C->isMinSignedValue() && - match(Op0, m_NSWSub(m_Zero(), m_Value(X)))) { + if (!Op1C->isMinSignedValue() && match(Op0, m_NSWNeg(m_Value(X)))) { Constant *NegC = ConstantInt::get(Ty, -(*Op1C)); Instruction *BO = BinaryOperator::CreateSDiv(X, NegC); BO->setIsExact(I.isExact()); @@ -1583,7 +1582,7 @@ Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) { // -X / Y --> -(X / Y) Value *Y; - if (match(&I, m_SDiv(m_OneUse(m_NSWSub(m_Zero(), m_Value(X))), m_Value(Y)))) + if (match(&I, m_SDiv(m_OneUse(m_NSWNeg(m_Value(X))), m_Value(Y)))) return BinaryOperator::CreateNSWNeg( Builder.CreateSDiv(X, Y, I.getName(), I.isExact())); @@ -2173,7 +2172,7 @@ Instruction *InstCombinerImpl::visitSRem(BinaryOperator &I) { // -X srem Y --> -(X srem Y) Value *X, *Y; - if (match(&I, m_SRem(m_OneUse(m_NSWSub(m_Zero(), m_Value(X))), m_Value(Y)))) + if (match(&I, m_SRem(m_OneUse(m_NSWNeg(m_Value(X))), m_Value(Y)))) return BinaryOperator::CreateNSWNeg(Builder.CreateSRem(X, Y)); // If the sign bits of both operands are zero (i.e. we can prove they are -- GitLab From 0e6367236413e50599b49aff15b086088f152769 Mon Sep 17 00:00:00 2001 From: Sergio Afonso Date: Fri, 12 Apr 2024 10:35:48 +0100 Subject: [PATCH 044/464] [MLIR][OpenMP] Add omp.loop_nest operation (#87083) This patch introduces an operation intended to hold loop information associated to the `omp.distribute`, `omp.simdloop`, `omp.taskloop` and `omp.wsloop` operations. This is a stopgap solution to unblock work on transitioning these operations to becoming wrappers, as discussed in [this RFC](https://discourse.llvm.org/t/rfc-representing-combined-composite-constructs-in-the-openmp-dialect/76986). Long-term, this operation will likely be replaced by `omp.canonical_loop`, which is being designed to address missing support for loop transformations, etc. --- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 66 +++++++++++++++- mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 71 +++++++++++++++++ mlir/test/Dialect/OpenMP/invalid.mlir | 37 +++++++++ mlir/test/Dialect/OpenMP/ops.mlir | 79 +++++++++++++++++++ 4 files changed, 252 insertions(+), 1 deletion(-) diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index 2a8582be3833..a2eb39a8e607 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -524,6 +524,70 @@ def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> { let hasVerifier = 1; } +//===----------------------------------------------------------------------===// +// Loop Nest +//===----------------------------------------------------------------------===// + +def LoopNestOp : OpenMP_Op<"loop_nest", [SameVariadicOperandSize, + AllTypesMatch<["lowerBound", "upperBound", "step"]>, + ParentOneOf<["DistributeOp", "SimdLoopOp", "TaskloopOp", + "WsloopOp"]>, + RecursiveMemoryEffects]> { + let summary = "rectangular loop nest"; + let description = [{ + This operation represents a collapsed rectangular loop nest. For each + rectangular loop of the nest represented by an instance of this operation, + lower and upper bounds, as well as a step variable, must be defined. + + The lower and upper bounds specify a half-open range: the range includes the + lower bound but does not include the upper bound. If the `inclusive` + attribute is specified then the upper bound is also included. + + The body region can contain any number of blocks. The region is terminated + by an `omp.yield` instruction without operands. The induction variables, + represented as entry block arguments to the loop nest operation's single + region, match the types of the `lowerBound`, `upperBound` and `step` + arguments. + + ```mlir + omp.loop_nest (%i1, %i2) : i32 = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) { + %a = load %arrA[%i1, %i2] : memref + %b = load %arrB[%i1, %i2] : memref + %sum = arith.addf %a, %b : f32 + store %sum, %arrC[%i1, %i2] : memref + omp.yield + } + ``` + + This is a temporary simplified definition of a loop based on existing OpenMP + loop operations intended to serve as a stopgap solution until the long-term + representation of canonical loops is defined. Specifically, this operation + is intended to serve as a unique source for loop information during the + transition to making `omp.distribute`, `omp.simdloop`, `omp.taskloop` and + `omp.wsloop` wrapper operations. It is not intended to help with the + addition of support for loop transformations, non-rectangular loops and + non-perfectly nested loops. + }]; + + let arguments = (ins Variadic:$lowerBound, + Variadic:$upperBound, + Variadic:$step, + UnitAttr:$inclusive); + + let regions = (region AnyRegion:$region); + + let extraClassDeclaration = [{ + /// Returns the number of loops in the loop nest. + unsigned getNumLoops() { return getLowerBound().size(); } + + /// Returns the induction variables of the loop nest. + ArrayRef getIVs() { return getRegion().getArguments(); } + }]; + + let hasCustomAssemblyFormat = 1; + let hasVerifier = 1; +} + //===----------------------------------------------------------------------===// // 2.9.2 Workshare Loop Construct //===----------------------------------------------------------------------===// @@ -743,7 +807,7 @@ def SimdLoopOp : OpenMP_Op<"simdloop", [AttrSizedOperandSegments, def YieldOp : OpenMP_Op<"yield", [Pure, ReturnLike, Terminator, - ParentOneOf<["WsloopOp", "DeclareReductionOp", + ParentOneOf<["LoopNestOp", "WsloopOp", "DeclareReductionOp", "AtomicUpdateOp", "SimdLoopOp", "PrivateClauseOp"]>]> { let summary = "loop yield and termination operation"; let description = [{ diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index 2d5b2231d2dd..4ab78bf331f8 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -1862,6 +1862,77 @@ LogicalResult TaskloopOp::verify() { return success(); } +//===----------------------------------------------------------------------===// +// LoopNestOp +//===----------------------------------------------------------------------===// + +ParseResult LoopNestOp::parse(OpAsmParser &parser, OperationState &result) { + // Parse an opening `(` followed by induction variables followed by `)` + SmallVector ivs; + SmallVector lbs, ubs; + Type loopVarType; + if (parser.parseArgumentList(ivs, OpAsmParser::Delimiter::Paren) || + parser.parseColonType(loopVarType) || + // Parse loop bounds. + parser.parseEqual() || + parser.parseOperandList(lbs, ivs.size(), OpAsmParser::Delimiter::Paren) || + parser.parseKeyword("to") || + parser.parseOperandList(ubs, ivs.size(), OpAsmParser::Delimiter::Paren)) + return failure(); + + for (auto &iv : ivs) + iv.type = loopVarType; + + // Parse "inclusive" flag. + if (succeeded(parser.parseOptionalKeyword("inclusive"))) + result.addAttribute("inclusive", + UnitAttr::get(parser.getBuilder().getContext())); + + // Parse step values. + SmallVector steps; + if (parser.parseKeyword("step") || + parser.parseOperandList(steps, ivs.size(), OpAsmParser::Delimiter::Paren)) + return failure(); + + // Parse the body. + Region *region = result.addRegion(); + if (parser.parseRegion(*region, ivs)) + return failure(); + + // Resolve operands. + if (parser.resolveOperands(lbs, loopVarType, result.operands) || + parser.resolveOperands(ubs, loopVarType, result.operands) || + parser.resolveOperands(steps, loopVarType, result.operands)) + return failure(); + + // Parse the optional attribute list. + return parser.parseOptionalAttrDict(result.attributes); +} + +void LoopNestOp::print(OpAsmPrinter &p) { + Region ®ion = getRegion(); + auto args = region.getArguments(); + p << " (" << args << ") : " << args[0].getType() << " = (" << getLowerBound() + << ") to (" << getUpperBound() << ") "; + if (getInclusive()) + p << "inclusive "; + p << "step (" << getStep() << ") "; + p.printRegion(region, /*printEntryBlockArgs=*/false); +} + +LogicalResult LoopNestOp::verify() { + if (getLowerBound().size() != getIVs().size()) + return emitOpError() << "number of range arguments and IVs do not match"; + + for (auto [lb, iv] : llvm::zip_equal(getLowerBound(), getIVs())) { + if (lb.getType() != iv.getType()) + return emitOpError() + << "range argument type does not match corresponding IV type"; + } + + return success(); +} + //===----------------------------------------------------------------------===// // WsloopOp //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir index 27a440b3f97c..3802fbde534d 100644 --- a/mlir/test/Dialect/OpenMP/invalid.mlir +++ b/mlir/test/Dialect/OpenMP/invalid.mlir @@ -87,6 +87,43 @@ func.func @proc_bind_once() { // ----- +func.func @invalid_parent(%lb : index, %ub : index, %step : index) { + // expected-error@+1 {{op expects parent op to be one of 'omp.distribute, omp.simdloop, omp.taskloop, omp.wsloop'}} + omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) { + omp.yield + } +} + +// ----- + +func.func @type_mismatch(%lb : index, %ub : index, %step : index) { + // TODO Remove induction variables from omp.wsloop. + omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { + // expected-error@+1 {{range argument type does not match corresponding IV type}} + "omp.loop_nest" (%lb, %ub, %step) ({ + ^bb0(%iv2: i32): + omp.yield + }) : (index, index, index) -> () + omp.yield + } +} + +// ----- + +func.func @iv_number_mismatch(%lb : index, %ub : index, %step : index) { + // TODO Remove induction variables from omp.wsloop. + omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { + // expected-error@+1 {{number of range arguments and IVs do not match}} + "omp.loop_nest" (%lb, %ub, %step) ({ + ^bb0(%iv1 : index, %iv2 : index): + omp.yield + }) : (index, index, index) -> () + omp.yield + } +} + +// ----- + func.func @inclusive_not_a_clause(%lb : index, %ub : index, %step : index) { // expected-error @below {{expected 'for'}} omp.wsloop nowait inclusive diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir index ad5b74b84ac7..851d44ad984e 100644 --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -133,6 +133,85 @@ func.func @omp_parallel_pretty(%data_var : memref, %if_cond : i1, %num_thre return } +// CHECK-LABEL: omp_loop_nest +func.func @omp_loop_nest(%lb : index, %ub : index, %step : index) -> () { + // TODO Remove induction variables from omp.wsloop. + omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { + // CHECK: omp.loop_nest + // CHECK-SAME: (%{{.*}}) : index = + // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}}) + "omp.loop_nest" (%lb, %ub, %step) ({ + ^bb0(%iv2: index): + omp.yield + }) : (index, index, index) -> () + omp.yield + } + + // TODO Remove induction variables from omp.wsloop. + omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { + // CHECK: omp.loop_nest + // CHECK-SAME: (%{{.*}}) : index = + // CHECK-SAME: (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}}) + "omp.loop_nest" (%lb, %ub, %step) ({ + ^bb0(%iv2: index): + omp.yield + }) {inclusive} : (index, index, index) -> () + omp.yield + } + + // TODO Remove induction variables from omp.wsloop. + omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { + // CHECK: omp.loop_nest + // CHECK-SAME: (%{{.*}}, %{{.*}}) : index = + // CHECK-SAME: (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}}) + "omp.loop_nest" (%lb, %lb, %ub, %ub, %step, %step) ({ + ^bb0(%iv2: index, %iv3: index): + omp.yield + }) : (index, index, index, index, index, index) -> () + omp.yield + } + + return +} + +// CHECK-LABEL: omp_loop_nest_pretty +func.func @omp_loop_nest_pretty(%lb : index, %ub : index, %step : index) -> () { + // TODO Remove induction variables from omp.wsloop. + omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { + // CHECK: omp.loop_nest + // CHECK-SAME: (%{{.*}}) : index = + // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}}) + omp.loop_nest (%iv2) : index = (%lb) to (%ub) step (%step) { + omp.yield + } + omp.yield + } + + // TODO Remove induction variables from omp.wsloop. + omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { + // CHECK: omp.loop_nest + // CHECK-SAME: (%{{.*}}) : index = + // CHECK-SAME: (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}}) + omp.loop_nest (%iv2) : index = (%lb) to (%ub) inclusive step (%step) { + omp.yield + } + omp.yield + } + + // TODO Remove induction variables from omp.wsloop. + omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { + // CHECK: omp.loop_nest + // CHECK-SAME: (%{{.*}}) : index = + // CHECK-SAME: (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}}) + omp.loop_nest (%iv2, %iv3) : index = (%lb, %lb) to (%ub, %ub) step (%step, %step) { + omp.yield + } + omp.yield + } + + return +} + // CHECK-LABEL: omp_wsloop func.func @omp_wsloop(%lb : index, %ub : index, %step : index, %data_var : memref, %linear_var : i32, %chunk_var : i32) -> () { -- GitLab From f5b2d24b59f168eaeed08b5f45bf0c8dfcc1c292 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Fri, 12 Apr 2024 11:47:53 +0200 Subject: [PATCH 045/464] [NVPTX] Move roundeven on bf16 into the sm_90 has it but sm_80 doesn't bucket --- llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp | 1 + llvm/test/CodeGen/NVPTX/bf16-instructions.ll | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp index e1cdbd6a4b4d..44b61a937d64 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp @@ -447,6 +447,7 @@ NVPTXTargetLowering::NVPTXTargetLowering(const NVPTXTargetMachine &TM, case ISD::FFLOOR: case ISD::FNEARBYINT: case ISD::FRINT: + case ISD::FROUNDEVEN: case ISD::FTRUNC: IsOpSupported = STI.getSmVersion() >= 90 && STI.getPTXVersion() >= 78; break; diff --git a/llvm/test/CodeGen/NVPTX/bf16-instructions.ll b/llvm/test/CodeGen/NVPTX/bf16-instructions.ll index 884860712632..4cbab8bf2416 100644 --- a/llvm/test/CodeGen/NVPTX/bf16-instructions.ll +++ b/llvm/test/CodeGen/NVPTX/bf16-instructions.ll @@ -330,3 +330,15 @@ define bfloat @test_uitofp_i64(i64 %a) { %r = uitofp i64 %a to bfloat ret bfloat %r } + +; CHECK-LABEL: test_roundeven( +; CHECK: ld.param.b16 [[A:%rs[0-9]+]], [test_roundeven_param_0]; +; SM80: cvt.rni.f32.f32 [[F:%f[0-9]+]] +; SM80: cvt.rn.bf16.f32 [[R:%rs[0-9]+]], [[F]]; +; SM90: cvt.rni.bf16.bf16 [[R:%rs[0-9]+]], [[A]]; +; CHECK: st.param.b16 [func_retval0+0], [[R]]; +; CHECK: ret; +define bfloat @test_roundeven(bfloat %a) { + %r = call bfloat @llvm.roundeven.bf16(bfloat %a) + ret bfloat %r +} -- GitLab From b24af43fdfa1b1242b7cb77540462212227c57c4 Mon Sep 17 00:00:00 2001 From: David Green Date: Fri, 12 Apr 2024 10:57:01 +0100 Subject: [PATCH 046/464] [AArch64] Improve scheduling latency into Bundles (#86310) By default the scheduling info of instructions into a BUNDLE are given a latency of 0 as they operate on the implicit register of the bundle. This modifies that for AArch64 so that the latency is adjusted to use the latency from the instruction in the bundle instead. This essentially assumes that the bundled instructions are executed in a single cycle, which for AArch64 is probably OK considering they are mostly used for MOVPFX bundles, where this can help create slightly better scheduling especially for in-order cores. --- .../llvm/CodeGen/TargetSubtargetInfo.h | 4 +- llvm/lib/CodeGen/MachinePipeliner.cpp | 3 +- llvm/lib/CodeGen/ScheduleDAGInstrs.cpp | 8 +- .../SelectionDAG/ScheduleDAGSDNodes.cpp | 2 +- llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 39 ++++++ llvm/lib/Target/AArch64/AArch64Subtarget.h | 3 + llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp | 5 +- llvm/lib/Target/AMDGPU/GCNSubtarget.h | 3 +- llvm/lib/Target/Hexagon/HexagonSubtarget.cpp | 6 +- llvm/lib/Target/Hexagon/HexagonSubtarget.h | 3 +- ...x-deinterleaving-add-mull-scalable-fast.ll | 6 +- .../CodeGen/AArch64/llvm-ir-to-intrinsic.ll | 2 +- llvm/test/CodeGen/AArch64/misched-bundle.mir | 36 +++--- .../AArch64/sve-fixed-length-build-vector.ll | 2 +- .../AArch64/sve-fixed-length-fp-arith.ll | 24 ++-- .../AArch64/sve-fixed-length-fp-fma.ll | 6 +- .../AArch64/sve-fixed-length-fp-minmax.ll | 24 ++-- .../AArch64/sve-fixed-length-int-arith.ll | 8 +- .../AArch64/sve-fixed-length-int-minmax.ll | 32 ++--- .../AArch64/sve-fixed-length-int-mulh.ll | 16 +-- .../AArch64/sve-fixed-length-int-rem.ll | 96 +++++++------- .../AArch64/sve-fixed-length-int-shifts.ll | 24 ++-- llvm/test/CodeGen/AArch64/sve-fpext-load.ll | 2 +- llvm/test/CodeGen/AArch64/sve-fptosi-sat.ll | 70 +++++----- llvm/test/CodeGen/AArch64/sve-fptoui-sat.ll | 122 +++++++++--------- .../AArch64/sve-gather-scatter-addr-opts.ll | 10 +- .../AArch64/sve-masked-gather-legalize.ll | 4 +- llvm/test/CodeGen/AArch64/sve-smulo-sdnode.ll | 24 ++-- llvm/test/CodeGen/AArch64/sve-split-fcvt.ll | 34 ++--- ...aming-mode-fixed-length-fp-extend-trunc.ll | 6 +- ...sve-streaming-mode-fixed-length-int-div.ll | 8 +- ...sve-streaming-mode-fixed-length-int-rem.ll | 32 ++--- ...e-streaming-mode-fixed-length-int-to-fp.ll | 20 +-- llvm/test/CodeGen/AArch64/sve-umulo-sdnode.ll | 16 +-- .../test/CodeGen/AArch64/sve-vecreduce-dot.ll | 2 +- llvm/test/CodeGen/AArch64/sve2-xar.ll | 2 +- 36 files changed, 377 insertions(+), 327 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h index 7f8ed5c50198..5023e29ce145 100644 --- a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h +++ b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h @@ -235,7 +235,9 @@ public: // and UseOpIdx are the indices of the operands in Def and Use, respectively. // Otherwise, either may be -1. virtual void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, - int UseOpIdx, SDep &Dep) const {} + int UseOpIdx, SDep &Dep, + const TargetSchedModel *SchedModel) const { + } // For use with PostRAScheduling: get the anti-dependence breaking that should // be performed before post-RA scheduling. diff --git a/llvm/lib/CodeGen/MachinePipeliner.cpp b/llvm/lib/CodeGen/MachinePipeliner.cpp index 930504067832..4f7d9d070cee 100644 --- a/llvm/lib/CodeGen/MachinePipeliner.cpp +++ b/llvm/lib/CodeGen/MachinePipeliner.cpp @@ -919,7 +919,8 @@ void SwingSchedulerDAG::updatePhiDependences() { if (!MI->isPHI()) { SDep Dep(SU, SDep::Data, Reg); Dep.setLatency(0); - ST.adjustSchedDependency(SU, 0, &I, MO.getOperandNo(), Dep); + ST.adjustSchedDependency(SU, 0, &I, MO.getOperandNo(), Dep, + &SchedModel); I.addPred(Dep); } else { HasPhiUse = Reg; diff --git a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp index 51ede7992af5..c848ce4af86c 100644 --- a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -282,7 +282,7 @@ void ScheduleDAGInstrs::addPhysRegDataDeps(SUnit *SU, unsigned OperIdx) { } else { Dep.setLatency(0); } - ST.adjustSchedDependency(SU, OperIdx, UseSU, UseOpIdx, Dep); + ST.adjustSchedDependency(SU, OperIdx, UseSU, UseOpIdx, Dep, &SchedModel); UseSU->addPred(Dep); } } @@ -323,7 +323,8 @@ void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) { Dep.setLatency( SchedModel.computeOutputLatency(MI, OperIdx, DefInstr)); } - ST.adjustSchedDependency(SU, OperIdx, DefSU, I->OpIdx, Dep); + ST.adjustSchedDependency(SU, OperIdx, DefSU, I->OpIdx, Dep, + &SchedModel); DefSU->addPred(Dep); } } @@ -453,7 +454,8 @@ void ScheduleDAGInstrs::addVRegDefDeps(SUnit *SU, unsigned OperIdx) { SDep Dep(SU, SDep::Data, Reg); Dep.setLatency(SchedModel.computeOperandLatency(MI, OperIdx, Use, I->OperandIndex)); - ST.adjustSchedDependency(SU, OperIdx, UseSU, I->OperandIndex, Dep); + ST.adjustSchedDependency(SU, OperIdx, UseSU, I->OperandIndex, Dep, + &SchedModel); UseSU->addPred(Dep); } diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index 862fce6959f1..379456e3a9b6 100644 --- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -512,7 +512,7 @@ void ScheduleDAGSDNodes::AddSchedEdges() { Dep.setLatency(OpLatency); if (!isChain && !UnitLatencies) { computeOperandLatency(OpN, N, i, Dep); - ST.adjustSchedDependency(OpSU, DefIdx, &SU, i, Dep); + ST.adjustSchedDependency(OpSU, DefIdx, &SU, i, Dep, nullptr); } if (!SU.addPred(Dep) && !Dep.isCtrl() && OpSU->NumRegDefsLeft > 1) { diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp index bb268b2ba926..9eb1ecbb0315 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -472,6 +472,45 @@ void AArch64Subtarget::overrideSchedPolicy(MachineSchedPolicy &Policy, Policy.DisableLatencyHeuristic = DisableLatencySchedHeuristic; } +void AArch64Subtarget::adjustSchedDependency( + SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, SDep &Dep, + const TargetSchedModel *SchedModel) const { + if (!SchedModel || Dep.getKind() != SDep::Kind::Data || !Dep.getReg() || + !Def->isInstr() || !Use->isInstr() || + (Def->getInstr()->getOpcode() != TargetOpcode::BUNDLE && + Use->getInstr()->getOpcode() != TargetOpcode::BUNDLE)) + return; + + // If the Def is a BUNDLE, find the last instruction in the bundle that defs + // the register. + const MachineInstr *DefMI = Def->getInstr(); + if (DefMI->getOpcode() == TargetOpcode::BUNDLE) { + Register Reg = DefMI->getOperand(DefOpIdx).getReg(); + for (const auto &Op : const_mi_bundle_ops(*DefMI)) { + if (Op.isReg() && Op.isDef() && Op.getReg() == Reg) { + DefMI = Op.getParent(); + DefOpIdx = Op.getOperandNo(); + } + } + } + + // If the Use is a BUNDLE, find the first instruction that uses the Reg. + const MachineInstr *UseMI = Use->getInstr(); + if (UseMI->getOpcode() == TargetOpcode::BUNDLE) { + Register Reg = UseMI->getOperand(UseOpIdx).getReg(); + for (const auto &Op : const_mi_bundle_ops(*UseMI)) { + if (Op.isReg() && Op.isUse() && Op.getReg() == Reg) { + UseMI = Op.getParent(); + UseOpIdx = Op.getOperandNo(); + break; + } + } + } + + Dep.setLatency( + SchedModel->computeOperandLatency(DefMI, DefOpIdx, UseMI, UseOpIdx)); +} + bool AArch64Subtarget::enableEarlyIfConversion() const { return EnableEarlyIfConvert; } diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index 95bef7a76bca..c5ebd4c6cc61 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -354,6 +354,9 @@ public: void overrideSchedPolicy(MachineSchedPolicy &Policy, unsigned NumRegionInstrs) const override; + void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, + SDep &Dep, + const TargetSchedModel *SchedModel) const override; bool enableEarlyIfConversion() const override; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp index 8f0eae362eca..36e453f04426 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp @@ -860,8 +860,9 @@ unsigned GCNSubtarget::getMaxNumVGPRs(const MachineFunction &MF) const { return getBaseMaxNumVGPRs(F, MFI.getWavesPerEU()); } -void GCNSubtarget::adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, - int UseOpIdx, SDep &Dep) const { +void GCNSubtarget::adjustSchedDependency( + SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, SDep &Dep, + const TargetSchedModel *SchedModel) const { if (Dep.getKind() != SDep::Kind::Data || !Dep.getReg() || !Def->isInstr() || !Use->isInstr()) return; diff --git a/llvm/lib/Target/AMDGPU/GCNSubtarget.h b/llvm/lib/Target/AMDGPU/GCNSubtarget.h index 04ff53a6647b..8a4a46ce50d1 100644 --- a/llvm/lib/Target/AMDGPU/GCNSubtarget.h +++ b/llvm/lib/Target/AMDGPU/GCNSubtarget.h @@ -1500,7 +1500,8 @@ public: } void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, - SDep &Dep) const override; + SDep &Dep, + const TargetSchedModel *SchedModel) const override; // \returns true if it's beneficial on this subtarget for the scheduler to // cluster stores as well as loads. diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp b/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp index 2d320e6b0cad..da8ab5c4b21b 100644 --- a/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp +++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp @@ -437,9 +437,9 @@ bool HexagonSubtarget::useAA() const { /// Perform target specific adjustments to the latency of a schedule /// dependency. -void HexagonSubtarget::adjustSchedDependency(SUnit *Src, int SrcOpIdx, - SUnit *Dst, int DstOpIdx, - SDep &Dep) const { +void HexagonSubtarget::adjustSchedDependency( + SUnit *Src, int SrcOpIdx, SUnit *Dst, int DstOpIdx, SDep &Dep, + const TargetSchedModel *SchedModel) const { if (!Src->isInstr() || !Dst->isInstr()) return; diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.h b/llvm/lib/Target/Hexagon/HexagonSubtarget.h index e56007ee21e7..da3f8f56ccc4 100644 --- a/llvm/lib/Target/Hexagon/HexagonSubtarget.h +++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.h @@ -308,7 +308,8 @@ public: /// Perform target specific adjustments to the latency of a schedule /// dependency. void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, - SDep &Dep) const override; + SDep &Dep, + const TargetSchedModel *SchedModel) const override; unsigned getVectorLength() const { assert(useHVXOps()); diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-scalable-fast.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-scalable-fast.ll index aac43f7b960f..1751f99b3e92 100644 --- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-scalable-fast.ll +++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-scalable-fast.ll @@ -190,8 +190,8 @@ define @mul_add_rot_mull( %a, @mul_add_rot_mull( %a, @fshl_rot_illegal_i64( %a, @srem_v2i32(<2 x i32> %op1, <2 x i32> %op2) vscale_range(1,0) #0 { ; CHECK-LABEL: srem_v2i32: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 -; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 ; CHECK-NEXT: ptrue p0.s, vl2 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: sdiv z2.s, p0/m, z2.s, z1.s ; CHECK-NEXT: mls v0.2s, v2.2s, v1.2s @@ -549,9 +549,9 @@ define <2 x i32> @srem_v2i32(<2 x i32> %op1, <2 x i32> %op2) vscale_range(1,0) # define <4 x i32> @srem_v4i32(<4 x i32> %op1, <4 x i32> %op2) vscale_range(1,0) #0 { ; CHECK-LABEL: srem_v4i32: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 -; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 ; CHECK-NEXT: ptrue p0.s, vl4 +; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 +; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: sdiv z2.s, p0/m, z2.s, z1.s ; CHECK-NEXT: mls v0.4s, v2.4s, v1.4s @@ -582,25 +582,25 @@ define void @srem_v8i32(ptr %a, ptr %b) vscale_range(2,0) #0 { define void @srem_v16i32(ptr %a, ptr %b) #0 { ; VBITS_GE_128-LABEL: srem_v16i32: ; VBITS_GE_128: // %bb.0: -; VBITS_GE_128-NEXT: ldp q0, q3, [x1] ; VBITS_GE_128-NEXT: ptrue p0.s, vl4 +; VBITS_GE_128-NEXT: ldp q0, q3, [x1] ; VBITS_GE_128-NEXT: ldp q1, q2, [x0] -; VBITS_GE_128-NEXT: movprfx z4, z1 -; VBITS_GE_128-NEXT: sdiv z4.s, p0/m, z4.s, z0.s ; VBITS_GE_128-NEXT: ldp q16, q5, [x0, #32] -; VBITS_GE_128-NEXT: movprfx z19, z2 -; VBITS_GE_128-NEXT: sdiv z19.s, p0/m, z19.s, z3.s ; VBITS_GE_128-NEXT: ldp q17, q6, [x1, #32] +; VBITS_GE_128-NEXT: movprfx z4, z1 +; VBITS_GE_128-NEXT: sdiv z4.s, p0/m, z4.s, z0.s ; VBITS_GE_128-NEXT: movprfx z7, z5 ; VBITS_GE_128-NEXT: sdiv z7.s, p0/m, z7.s, z6.s ; VBITS_GE_128-NEXT: movprfx z18, z16 ; VBITS_GE_128-NEXT: sdiv z18.s, p0/m, z18.s, z17.s -; VBITS_GE_128-NEXT: mls v1.4s, v4.4s, v0.4s -; VBITS_GE_128-NEXT: mls v2.4s, v19.4s, v3.4s +; VBITS_GE_128-NEXT: movprfx z19, z2 +; VBITS_GE_128-NEXT: sdiv z19.s, p0/m, z19.s, z3.s ; VBITS_GE_128-NEXT: mls v16.4s, v18.4s, v17.4s ; VBITS_GE_128-NEXT: mls v5.4s, v7.4s, v6.4s -; VBITS_GE_128-NEXT: stp q1, q2, [x0] +; VBITS_GE_128-NEXT: mls v1.4s, v4.4s, v0.4s +; VBITS_GE_128-NEXT: mls v2.4s, v19.4s, v3.4s ; VBITS_GE_128-NEXT: stp q16, q5, [x0, #32] +; VBITS_GE_128-NEXT: stp q1, q2, [x0] ; VBITS_GE_128-NEXT: ret ; ; VBITS_GE_256-LABEL: srem_v16i32: @@ -609,17 +609,17 @@ define void @srem_v16i32(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: mov x8, #8 // =0x8 ; VBITS_GE_256-NEXT: ld1w { z0.s }, p0/z, [x0, x8, lsl #2] ; VBITS_GE_256-NEXT: ld1w { z1.s }, p0/z, [x1, x8, lsl #2] -; VBITS_GE_256-NEXT: movprfx z2, z0 -; VBITS_GE_256-NEXT: sdiv z2.s, p0/m, z2.s, z1.s ; VBITS_GE_256-NEXT: ld1w { z3.s }, p0/z, [x0] ; VBITS_GE_256-NEXT: ld1w { z4.s }, p0/z, [x1] +; VBITS_GE_256-NEXT: movprfx z2, z0 +; VBITS_GE_256-NEXT: sdiv z2.s, p0/m, z2.s, z1.s ; VBITS_GE_256-NEXT: movprfx z5, z3 ; VBITS_GE_256-NEXT: sdiv z5.s, p0/m, z5.s, z4.s ; VBITS_GE_256-NEXT: mls z0.s, p0/m, z2.s, z1.s ; VBITS_GE_256-NEXT: movprfx z1, z3 ; VBITS_GE_256-NEXT: mls z1.s, p0/m, z5.s, z4.s -; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: st1w { z0.s }, p0, [x0, x8, lsl #2] +; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: srem_v16i32: @@ -681,8 +681,8 @@ define <1 x i64> @srem_v1i64(<1 x i64> %op1, <1 x i64> %op2) vscale_range(1,0) # ; CHECK-LABEL: srem_v1i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d, vl1 -; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: sdiv z2.d, p0/m, z2.d, z1.d ; CHECK-NEXT: mls z0.d, p0/m, z2.d, z1.d @@ -698,8 +698,8 @@ define <2 x i64> @srem_v2i64(<2 x i64> %op1, <2 x i64> %op2) vscale_range(1,0) # ; CHECK-LABEL: srem_v2i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d, vl2 -; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 +; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: sdiv z2.d, p0/m, z2.d, z1.d ; CHECK-NEXT: mls z0.d, p0/m, z2.d, z1.d @@ -733,16 +733,16 @@ define void @srem_v8i64(ptr %a, ptr %b) #0 { ; VBITS_GE_128-NEXT: ptrue p0.d, vl2 ; VBITS_GE_128-NEXT: ldp q0, q3, [x1] ; VBITS_GE_128-NEXT: ldp q1, q2, [x0] -; VBITS_GE_128-NEXT: movprfx z4, z1 -; VBITS_GE_128-NEXT: sdiv z4.d, p0/m, z4.d, z0.d ; VBITS_GE_128-NEXT: ldp q16, q5, [x0, #32] -; VBITS_GE_128-NEXT: movprfx z19, z2 -; VBITS_GE_128-NEXT: sdiv z19.d, p0/m, z19.d, z3.d ; VBITS_GE_128-NEXT: ldp q17, q6, [x1, #32] +; VBITS_GE_128-NEXT: movprfx z4, z1 +; VBITS_GE_128-NEXT: sdiv z4.d, p0/m, z4.d, z0.d ; VBITS_GE_128-NEXT: movprfx z7, z5 ; VBITS_GE_128-NEXT: sdiv z7.d, p0/m, z7.d, z6.d ; VBITS_GE_128-NEXT: movprfx z18, z16 ; VBITS_GE_128-NEXT: sdiv z18.d, p0/m, z18.d, z17.d +; VBITS_GE_128-NEXT: movprfx z19, z2 +; VBITS_GE_128-NEXT: sdiv z19.d, p0/m, z19.d, z3.d ; VBITS_GE_128-NEXT: mls z16.d, p0/m, z18.d, z17.d ; VBITS_GE_128-NEXT: mls z5.d, p0/m, z7.d, z6.d ; VBITS_GE_128-NEXT: msb z0.d, p0/m, z4.d, z1.d @@ -758,17 +758,17 @@ define void @srem_v8i64(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: mov x8, #4 // =0x4 ; VBITS_GE_256-NEXT: ld1d { z0.d }, p0/z, [x0, x8, lsl #3] ; VBITS_GE_256-NEXT: ld1d { z1.d }, p0/z, [x1, x8, lsl #3] -; VBITS_GE_256-NEXT: movprfx z2, z0 -; VBITS_GE_256-NEXT: sdiv z2.d, p0/m, z2.d, z1.d ; VBITS_GE_256-NEXT: ld1d { z3.d }, p0/z, [x0] ; VBITS_GE_256-NEXT: ld1d { z4.d }, p0/z, [x1] +; VBITS_GE_256-NEXT: movprfx z2, z0 +; VBITS_GE_256-NEXT: sdiv z2.d, p0/m, z2.d, z1.d ; VBITS_GE_256-NEXT: movprfx z5, z3 ; VBITS_GE_256-NEXT: sdiv z5.d, p0/m, z5.d, z4.d ; VBITS_GE_256-NEXT: mls z0.d, p0/m, z2.d, z1.d ; VBITS_GE_256-NEXT: movprfx z1, z3 ; VBITS_GE_256-NEXT: mls z1.d, p0/m, z5.d, z4.d -; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: st1d { z0.d }, p0, [x0, x8, lsl #3] +; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: srem_v8i64: @@ -1351,9 +1351,9 @@ define void @urem_v128i16(ptr %a, ptr %b) vscale_range(16,0) #0 { define <2 x i32> @urem_v2i32(<2 x i32> %op1, <2 x i32> %op2) vscale_range(1,0) #0 { ; CHECK-LABEL: urem_v2i32: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 -; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 ; CHECK-NEXT: ptrue p0.s, vl2 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: udiv z2.s, p0/m, z2.s, z1.s ; CHECK-NEXT: mls v0.2s, v2.2s, v1.2s @@ -1367,9 +1367,9 @@ define <2 x i32> @urem_v2i32(<2 x i32> %op1, <2 x i32> %op2) vscale_range(1,0) # define <4 x i32> @urem_v4i32(<4 x i32> %op1, <4 x i32> %op2) vscale_range(1,0) #0 { ; CHECK-LABEL: urem_v4i32: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 -; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 ; CHECK-NEXT: ptrue p0.s, vl4 +; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 +; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: udiv z2.s, p0/m, z2.s, z1.s ; CHECK-NEXT: mls v0.4s, v2.4s, v1.4s @@ -1400,25 +1400,25 @@ define void @urem_v8i32(ptr %a, ptr %b) vscale_range(2,0) #0 { define void @urem_v16i32(ptr %a, ptr %b) #0 { ; VBITS_GE_128-LABEL: urem_v16i32: ; VBITS_GE_128: // %bb.0: -; VBITS_GE_128-NEXT: ldp q0, q3, [x1] ; VBITS_GE_128-NEXT: ptrue p0.s, vl4 +; VBITS_GE_128-NEXT: ldp q0, q3, [x1] ; VBITS_GE_128-NEXT: ldp q1, q2, [x0] -; VBITS_GE_128-NEXT: movprfx z4, z1 -; VBITS_GE_128-NEXT: udiv z4.s, p0/m, z4.s, z0.s ; VBITS_GE_128-NEXT: ldp q16, q5, [x0, #32] -; VBITS_GE_128-NEXT: movprfx z19, z2 -; VBITS_GE_128-NEXT: udiv z19.s, p0/m, z19.s, z3.s ; VBITS_GE_128-NEXT: ldp q17, q6, [x1, #32] +; VBITS_GE_128-NEXT: movprfx z4, z1 +; VBITS_GE_128-NEXT: udiv z4.s, p0/m, z4.s, z0.s ; VBITS_GE_128-NEXT: movprfx z7, z5 ; VBITS_GE_128-NEXT: udiv z7.s, p0/m, z7.s, z6.s ; VBITS_GE_128-NEXT: movprfx z18, z16 ; VBITS_GE_128-NEXT: udiv z18.s, p0/m, z18.s, z17.s -; VBITS_GE_128-NEXT: mls v1.4s, v4.4s, v0.4s -; VBITS_GE_128-NEXT: mls v2.4s, v19.4s, v3.4s +; VBITS_GE_128-NEXT: movprfx z19, z2 +; VBITS_GE_128-NEXT: udiv z19.s, p0/m, z19.s, z3.s ; VBITS_GE_128-NEXT: mls v16.4s, v18.4s, v17.4s ; VBITS_GE_128-NEXT: mls v5.4s, v7.4s, v6.4s -; VBITS_GE_128-NEXT: stp q1, q2, [x0] +; VBITS_GE_128-NEXT: mls v1.4s, v4.4s, v0.4s +; VBITS_GE_128-NEXT: mls v2.4s, v19.4s, v3.4s ; VBITS_GE_128-NEXT: stp q16, q5, [x0, #32] +; VBITS_GE_128-NEXT: stp q1, q2, [x0] ; VBITS_GE_128-NEXT: ret ; ; VBITS_GE_256-LABEL: urem_v16i32: @@ -1427,17 +1427,17 @@ define void @urem_v16i32(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: mov x8, #8 // =0x8 ; VBITS_GE_256-NEXT: ld1w { z0.s }, p0/z, [x0, x8, lsl #2] ; VBITS_GE_256-NEXT: ld1w { z1.s }, p0/z, [x1, x8, lsl #2] -; VBITS_GE_256-NEXT: movprfx z2, z0 -; VBITS_GE_256-NEXT: udiv z2.s, p0/m, z2.s, z1.s ; VBITS_GE_256-NEXT: ld1w { z3.s }, p0/z, [x0] ; VBITS_GE_256-NEXT: ld1w { z4.s }, p0/z, [x1] +; VBITS_GE_256-NEXT: movprfx z2, z0 +; VBITS_GE_256-NEXT: udiv z2.s, p0/m, z2.s, z1.s ; VBITS_GE_256-NEXT: movprfx z5, z3 ; VBITS_GE_256-NEXT: udiv z5.s, p0/m, z5.s, z4.s ; VBITS_GE_256-NEXT: mls z0.s, p0/m, z2.s, z1.s ; VBITS_GE_256-NEXT: movprfx z1, z3 ; VBITS_GE_256-NEXT: mls z1.s, p0/m, z5.s, z4.s -; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: st1w { z0.s }, p0, [x0, x8, lsl #2] +; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: urem_v16i32: @@ -1499,8 +1499,8 @@ define <1 x i64> @urem_v1i64(<1 x i64> %op1, <1 x i64> %op2) vscale_range(1,0) # ; CHECK-LABEL: urem_v1i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d, vl1 -; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: udiv z2.d, p0/m, z2.d, z1.d ; CHECK-NEXT: mls z0.d, p0/m, z2.d, z1.d @@ -1516,8 +1516,8 @@ define <2 x i64> @urem_v2i64(<2 x i64> %op1, <2 x i64> %op2) vscale_range(1,0) # ; CHECK-LABEL: urem_v2i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d, vl2 -; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 +; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: udiv z2.d, p0/m, z2.d, z1.d ; CHECK-NEXT: mls z0.d, p0/m, z2.d, z1.d @@ -1551,16 +1551,16 @@ define void @urem_v8i64(ptr %a, ptr %b) #0 { ; VBITS_GE_128-NEXT: ptrue p0.d, vl2 ; VBITS_GE_128-NEXT: ldp q0, q3, [x1] ; VBITS_GE_128-NEXT: ldp q1, q2, [x0] -; VBITS_GE_128-NEXT: movprfx z4, z1 -; VBITS_GE_128-NEXT: udiv z4.d, p0/m, z4.d, z0.d ; VBITS_GE_128-NEXT: ldp q16, q5, [x0, #32] -; VBITS_GE_128-NEXT: movprfx z19, z2 -; VBITS_GE_128-NEXT: udiv z19.d, p0/m, z19.d, z3.d ; VBITS_GE_128-NEXT: ldp q17, q6, [x1, #32] +; VBITS_GE_128-NEXT: movprfx z4, z1 +; VBITS_GE_128-NEXT: udiv z4.d, p0/m, z4.d, z0.d ; VBITS_GE_128-NEXT: movprfx z7, z5 ; VBITS_GE_128-NEXT: udiv z7.d, p0/m, z7.d, z6.d ; VBITS_GE_128-NEXT: movprfx z18, z16 ; VBITS_GE_128-NEXT: udiv z18.d, p0/m, z18.d, z17.d +; VBITS_GE_128-NEXT: movprfx z19, z2 +; VBITS_GE_128-NEXT: udiv z19.d, p0/m, z19.d, z3.d ; VBITS_GE_128-NEXT: mls z16.d, p0/m, z18.d, z17.d ; VBITS_GE_128-NEXT: mls z5.d, p0/m, z7.d, z6.d ; VBITS_GE_128-NEXT: msb z0.d, p0/m, z4.d, z1.d @@ -1576,17 +1576,17 @@ define void @urem_v8i64(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: mov x8, #4 // =0x4 ; VBITS_GE_256-NEXT: ld1d { z0.d }, p0/z, [x0, x8, lsl #3] ; VBITS_GE_256-NEXT: ld1d { z1.d }, p0/z, [x1, x8, lsl #3] -; VBITS_GE_256-NEXT: movprfx z2, z0 -; VBITS_GE_256-NEXT: udiv z2.d, p0/m, z2.d, z1.d ; VBITS_GE_256-NEXT: ld1d { z3.d }, p0/z, [x0] ; VBITS_GE_256-NEXT: ld1d { z4.d }, p0/z, [x1] +; VBITS_GE_256-NEXT: movprfx z2, z0 +; VBITS_GE_256-NEXT: udiv z2.d, p0/m, z2.d, z1.d ; VBITS_GE_256-NEXT: movprfx z5, z3 ; VBITS_GE_256-NEXT: udiv z5.d, p0/m, z5.d, z4.d ; VBITS_GE_256-NEXT: mls z0.d, p0/m, z2.d, z1.d ; VBITS_GE_256-NEXT: movprfx z1, z3 ; VBITS_GE_256-NEXT: mls z1.d, p0/m, z5.d, z4.d -; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: st1d { z0.d }, p0, [x0, x8, lsl #3] +; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: urem_v8i64: diff --git a/llvm/test/CodeGen/AArch64/sve-fixed-length-int-shifts.ll b/llvm/test/CodeGen/AArch64/sve-fixed-length-int-shifts.ll index 7184cc970597..0fa8c8f50e29 100644 --- a/llvm/test/CodeGen/AArch64/sve-fixed-length-int-shifts.ll +++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-int-shifts.ll @@ -59,8 +59,8 @@ define void @ashr_v64i8(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: asr z0.b, p0/m, z0.b, z1.b ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: asr z1.b, p0/m, z1.b, z3.b -; VBITS_GE_256-NEXT: st1b { z1.b }, p0, [x0] ; VBITS_GE_256-NEXT: st1b { z0.b }, p0, [x0, x8] +; VBITS_GE_256-NEXT: st1b { z1.b }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: ashr_v64i8: @@ -160,8 +160,8 @@ define void @ashr_v32i16(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: asr z0.h, p0/m, z0.h, z1.h ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: asr z1.h, p0/m, z1.h, z3.h -; VBITS_GE_256-NEXT: st1h { z1.h }, p0, [x0] ; VBITS_GE_256-NEXT: st1h { z0.h }, p0, [x0, x8, lsl #1] +; VBITS_GE_256-NEXT: st1h { z1.h }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: ashr_v32i16: @@ -261,8 +261,8 @@ define void @ashr_v16i32(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: asr z0.s, p0/m, z0.s, z1.s ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: asr z1.s, p0/m, z1.s, z3.s -; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: st1w { z0.s }, p0, [x0, x8, lsl #2] +; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: ashr_v16i32: @@ -362,8 +362,8 @@ define void @ashr_v8i64(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: asr z0.d, p0/m, z0.d, z1.d ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: asr z1.d, p0/m, z1.d, z3.d -; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: st1d { z0.d }, p0, [x0, x8, lsl #3] +; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: ashr_v8i64: @@ -467,8 +467,8 @@ define void @lshr_v64i8(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: lsr z0.b, p0/m, z0.b, z1.b ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: lsr z1.b, p0/m, z1.b, z3.b -; VBITS_GE_256-NEXT: st1b { z1.b }, p0, [x0] ; VBITS_GE_256-NEXT: st1b { z0.b }, p0, [x0, x8] +; VBITS_GE_256-NEXT: st1b { z1.b }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: lshr_v64i8: @@ -568,8 +568,8 @@ define void @lshr_v32i16(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: lsr z0.h, p0/m, z0.h, z1.h ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: lsr z1.h, p0/m, z1.h, z3.h -; VBITS_GE_256-NEXT: st1h { z1.h }, p0, [x0] ; VBITS_GE_256-NEXT: st1h { z0.h }, p0, [x0, x8, lsl #1] +; VBITS_GE_256-NEXT: st1h { z1.h }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: lshr_v32i16: @@ -669,8 +669,8 @@ define void @lshr_v16i32(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: lsr z0.s, p0/m, z0.s, z1.s ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: lsr z1.s, p0/m, z1.s, z3.s -; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: st1w { z0.s }, p0, [x0, x8, lsl #2] +; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: lshr_v16i32: @@ -770,8 +770,8 @@ define void @lshr_v8i64(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: lsr z0.d, p0/m, z0.d, z1.d ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: lsr z1.d, p0/m, z1.d, z3.d -; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: st1d { z0.d }, p0, [x0, x8, lsl #3] +; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: lshr_v8i64: @@ -873,8 +873,8 @@ define void @shl_v64i8(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: lsl z0.b, p0/m, z0.b, z1.b ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: lsl z1.b, p0/m, z1.b, z3.b -; VBITS_GE_256-NEXT: st1b { z1.b }, p0, [x0] ; VBITS_GE_256-NEXT: st1b { z0.b }, p0, [x0, x8] +; VBITS_GE_256-NEXT: st1b { z1.b }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: shl_v64i8: @@ -972,8 +972,8 @@ define void @shl_v32i16(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: lsl z0.h, p0/m, z0.h, z1.h ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: lsl z1.h, p0/m, z1.h, z3.h -; VBITS_GE_256-NEXT: st1h { z1.h }, p0, [x0] ; VBITS_GE_256-NEXT: st1h { z0.h }, p0, [x0, x8, lsl #1] +; VBITS_GE_256-NEXT: st1h { z1.h }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: shl_v32i16: @@ -1071,8 +1071,8 @@ define void @shl_v16i32(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: lsl z0.s, p0/m, z0.s, z1.s ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: lsl z1.s, p0/m, z1.s, z3.s -; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: st1w { z0.s }, p0, [x0, x8, lsl #2] +; VBITS_GE_256-NEXT: st1w { z1.s }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: shl_v16i32: @@ -1170,8 +1170,8 @@ define void @shl_v8i64(ptr %a, ptr %b) #0 { ; VBITS_GE_256-NEXT: lsl z0.d, p0/m, z0.d, z1.d ; VBITS_GE_256-NEXT: movprfx z1, z2 ; VBITS_GE_256-NEXT: lsl z1.d, p0/m, z1.d, z3.d -; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: st1d { z0.d }, p0, [x0, x8, lsl #3] +; VBITS_GE_256-NEXT: st1d { z1.d }, p0, [x0] ; VBITS_GE_256-NEXT: ret ; ; VBITS_GE_512-LABEL: shl_v8i64: diff --git a/llvm/test/CodeGen/AArch64/sve-fpext-load.ll b/llvm/test/CodeGen/AArch64/sve-fpext-load.ll index 78decf5ed1e3..aec2150124c3 100644 --- a/llvm/test/CodeGen/AArch64/sve-fpext-load.ll +++ b/llvm/test/CodeGen/AArch64/sve-fpext-load.ll @@ -46,13 +46,13 @@ define @ext8_f16_f64(ptr %ptr, i64 %index) { ; CHECK-NEXT: uunpkhi z1.d, z1.s ; CHECK-NEXT: uunpklo z3.d, z0.s ; CHECK-NEXT: uunpkhi z4.d, z0.s +; CHECK-NEXT: fcvt z1.d, p0/m, z1.h ; CHECK-NEXT: movprfx z0, z2 ; CHECK-NEXT: fcvt z0.d, p0/m, z2.h ; CHECK-NEXT: movprfx z2, z3 ; CHECK-NEXT: fcvt z2.d, p0/m, z3.h ; CHECK-NEXT: movprfx z3, z4 ; CHECK-NEXT: fcvt z3.d, p0/m, z4.h -; CHECK-NEXT: fcvt z1.d, p0/m, z1.h ; CHECK-NEXT: ret %load = load , ptr %ptr, align 4 %load.ext = fpext %load to diff --git a/llvm/test/CodeGen/AArch64/sve-fptosi-sat.ll b/llvm/test/CodeGen/AArch64/sve-fptosi-sat.ll index 43113df07c07..813f1601e809 100644 --- a/llvm/test/CodeGen/AArch64/sve-fptosi-sat.ll +++ b/llvm/test/CodeGen/AArch64/sve-fptosi-sat.ll @@ -74,12 +74,12 @@ define @test_signed_v8f32_v8i32( %f) { ; CHECK-NEXT: mov w8, #1325400063 // =0x4effffff ; CHECK-NEXT: mov z6.s, #0x7fffffff ; CHECK-NEXT: mov z4.s, w8 -; CHECK-NEXT: movprfx z5, z1 -; CHECK-NEXT: fcvtzs z5.s, p0/m, z1.s ; CHECK-NEXT: fcmge p1.s, p0/z, z0.s, z2.s ; CHECK-NEXT: fcmge p2.s, p0/z, z1.s, z2.s ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: fcvtzs z2.s, p0/m, z0.s +; CHECK-NEXT: movprfx z5, z1 +; CHECK-NEXT: fcvtzs z5.s, p0/m, z1.s ; CHECK-NEXT: fcmgt p3.s, p0/z, z0.s, z4.s ; CHECK-NEXT: fcmgt p4.s, p0/z, z1.s, z4.s ; CHECK-NEXT: not p1.b, p0/z, p1.b @@ -134,17 +134,17 @@ define @test_signed_v8f32_v8i16( %f) { ; CHECK-NEXT: .cfi_offset w29, -16 ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: mov w8, #-956301312 // =0xc7000000 -; CHECK-NEXT: movprfx z4, z0 -; CHECK-NEXT: fcvtzs z4.s, p0/m, z0.s +; CHECK-NEXT: mov z5.s, #32767 // =0x7fff ; CHECK-NEXT: mov z2.s, w8 ; CHECK-NEXT: mov w8, #65024 // =0xfe00 -; CHECK-NEXT: mov z5.s, #32767 // =0x7fff ; CHECK-NEXT: movk w8, #18175, lsl #16 ; CHECK-NEXT: mov z3.s, w8 ; CHECK-NEXT: fcmge p1.s, p0/z, z1.s, z2.s ; CHECK-NEXT: fcmge p2.s, p0/z, z0.s, z2.s ; CHECK-NEXT: movprfx z2, z1 ; CHECK-NEXT: fcvtzs z2.s, p0/m, z1.s +; CHECK-NEXT: movprfx z4, z0 +; CHECK-NEXT: fcvtzs z4.s, p0/m, z0.s ; CHECK-NEXT: fcmgt p3.s, p0/z, z1.s, z3.s ; CHECK-NEXT: fcmgt p4.s, p0/z, z0.s, z3.s ; CHECK-NEXT: not p1.b, p0/z, p1.b @@ -206,13 +206,13 @@ define @test_signed_v4f32_v4i64( %f) { ; CHECK-NEXT: mov w8, #1593835519 // =0x5effffff ; CHECK-NEXT: mov z3.d, #0x8000000000000000 ; CHECK-NEXT: mov z4.s, w8 -; CHECK-NEXT: movprfx z5, z0 -; CHECK-NEXT: fcvtzs z5.d, p0/m, z0.s ; CHECK-NEXT: mov z6.d, #0x7fffffffffffffff ; CHECK-NEXT: fcmge p1.s, p0/z, z1.s, z2.s ; CHECK-NEXT: fcmge p2.s, p0/z, z0.s, z2.s ; CHECK-NEXT: movprfx z2, z1 ; CHECK-NEXT: fcvtzs z2.d, p0/m, z1.s +; CHECK-NEXT: movprfx z5, z0 +; CHECK-NEXT: fcvtzs z5.d, p0/m, z0.s ; CHECK-NEXT: fcmgt p3.s, p0/z, z1.s, z4.s ; CHECK-NEXT: fcmgt p4.s, p0/z, z0.s, z4.s ; CHECK-NEXT: not p1.b, p0/z, p1.b @@ -283,13 +283,13 @@ define @test_signed_v4f64_v4i32( %f) { ; CHECK-NEXT: mov x8, #281474972516352 // =0xffffffc00000 ; CHECK-NEXT: mov z6.d, #0x7fffffff ; CHECK-NEXT: movk x8, #16863, lsl #48 -; CHECK-NEXT: movprfx z5, z0 -; CHECK-NEXT: fcvtzs z5.d, p0/m, z0.d ; CHECK-NEXT: mov z4.d, x8 ; CHECK-NEXT: fcmge p1.d, p0/z, z1.d, z2.d ; CHECK-NEXT: fcmge p2.d, p0/z, z0.d, z2.d ; CHECK-NEXT: movprfx z2, z1 ; CHECK-NEXT: fcvtzs z2.d, p0/m, z1.d +; CHECK-NEXT: movprfx z5, z0 +; CHECK-NEXT: fcvtzs z5.d, p0/m, z0.d ; CHECK-NEXT: fcmgt p3.d, p0/z, z1.d, z4.d ; CHECK-NEXT: fcmgt p4.d, p0/z, z0.d, z4.d ; CHECK-NEXT: not p1.b, p0/z, p1.b @@ -324,24 +324,24 @@ define @test_signed_v8f64_v8i32( %f) { ; CHECK-NEXT: .cfi_offset w29, -16 ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #-4476578029606273024 // =0xc1e0000000000000 -; CHECK-NEXT: movprfx z6, z1 -; CHECK-NEXT: fcvtzs z6.d, p0/m, z1.d +; CHECK-NEXT: mov z26.d, #0x7fffffff ; CHECK-NEXT: mov z4.d, x8 ; CHECK-NEXT: mov x8, #281474972516352 // =0xffffffc00000 -; CHECK-NEXT: movprfx z7, z0 -; CHECK-NEXT: fcvtzs z7.d, p0/m, z0.d ; CHECK-NEXT: movk x8, #16863, lsl #48 -; CHECK-NEXT: mov z26.d, #0x7fffffff -; CHECK-NEXT: movprfx z24, z3 -; CHECK-NEXT: fcvtzs z24.d, p0/m, z3.d ; CHECK-NEXT: mov z5.d, x8 -; CHECK-NEXT: movprfx z25, z2 -; CHECK-NEXT: fcvtzs z25.d, p0/m, z2.d ; CHECK-NEXT: fcmge p1.d, p0/z, z1.d, z4.d ; CHECK-NEXT: fcmge p2.d, p0/z, z0.d, z4.d ; CHECK-NEXT: fcmge p3.d, p0/z, z3.d, z4.d ; CHECK-NEXT: fcmge p4.d, p0/z, z2.d, z4.d ; CHECK-NEXT: mov z4.d, #0xffffffff80000000 +; CHECK-NEXT: movprfx z6, z1 +; CHECK-NEXT: fcvtzs z6.d, p0/m, z1.d +; CHECK-NEXT: movprfx z7, z0 +; CHECK-NEXT: fcvtzs z7.d, p0/m, z0.d +; CHECK-NEXT: movprfx z24, z3 +; CHECK-NEXT: fcvtzs z24.d, p0/m, z3.d +; CHECK-NEXT: movprfx z25, z2 +; CHECK-NEXT: fcvtzs z25.d, p0/m, z2.d ; CHECK-NEXT: fcmgt p5.d, p0/z, z1.d, z5.d ; CHECK-NEXT: fcmgt p6.d, p0/z, z0.d, z5.d ; CHECK-NEXT: fcmgt p7.d, p0/z, z3.d, z5.d @@ -389,17 +389,17 @@ define @test_signed_v4f64_v4i16( %f) { ; CHECK-NEXT: .cfi_offset w29, -16 ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #-4548635623644200960 // =0xc0e0000000000000 -; CHECK-NEXT: movprfx z4, z0 -; CHECK-NEXT: fcvtzs z4.d, p0/m, z0.d +; CHECK-NEXT: mov z5.d, #32767 // =0x7fff ; CHECK-NEXT: mov z2.d, x8 ; CHECK-NEXT: mov x8, #281200098803712 // =0xffc000000000 -; CHECK-NEXT: mov z5.d, #32767 // =0x7fff ; CHECK-NEXT: movk x8, #16607, lsl #48 ; CHECK-NEXT: mov z3.d, x8 ; CHECK-NEXT: fcmge p1.d, p0/z, z1.d, z2.d ; CHECK-NEXT: fcmge p2.d, p0/z, z0.d, z2.d ; CHECK-NEXT: movprfx z2, z1 ; CHECK-NEXT: fcvtzs z2.d, p0/m, z1.d +; CHECK-NEXT: movprfx z4, z0 +; CHECK-NEXT: fcvtzs z4.d, p0/m, z0.d ; CHECK-NEXT: fcmgt p3.d, p0/z, z1.d, z3.d ; CHECK-NEXT: fcmgt p4.d, p0/z, z0.d, z3.d ; CHECK-NEXT: not p1.b, p0/z, p1.b @@ -434,23 +434,23 @@ define @test_signed_v8f64_v8i16( %f) { ; CHECK-NEXT: .cfi_offset w29, -16 ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #-4548635623644200960 // =0xc0e0000000000000 +; CHECK-NEXT: mov z25.d, #32767 // =0x7fff +; CHECK-NEXT: mov z4.d, x8 +; CHECK-NEXT: mov x8, #281200098803712 // =0xffc000000000 +; CHECK-NEXT: movk x8, #16607, lsl #48 +; CHECK-NEXT: fcmge p1.d, p0/z, z3.d, z4.d +; CHECK-NEXT: fcmge p2.d, p0/z, z2.d, z4.d +; CHECK-NEXT: fcmge p3.d, p0/z, z1.d, z4.d +; CHECK-NEXT: fcmge p4.d, p0/z, z0.d, z4.d ; CHECK-NEXT: movprfx z5, z3 ; CHECK-NEXT: fcvtzs z5.d, p0/m, z3.d ; CHECK-NEXT: mov z4.d, x8 -; CHECK-NEXT: mov x8, #281200098803712 // =0xffc000000000 ; CHECK-NEXT: movprfx z6, z2 ; CHECK-NEXT: fcvtzs z6.d, p0/m, z2.d -; CHECK-NEXT: movk x8, #16607, lsl #48 ; CHECK-NEXT: movprfx z7, z1 ; CHECK-NEXT: fcvtzs z7.d, p0/m, z1.d ; CHECK-NEXT: movprfx z24, z0 ; CHECK-NEXT: fcvtzs z24.d, p0/m, z0.d -; CHECK-NEXT: mov z25.d, #32767 // =0x7fff -; CHECK-NEXT: fcmge p1.d, p0/z, z3.d, z4.d -; CHECK-NEXT: fcmge p2.d, p0/z, z2.d, z4.d -; CHECK-NEXT: fcmge p3.d, p0/z, z1.d, z4.d -; CHECK-NEXT: fcmge p4.d, p0/z, z0.d, z4.d -; CHECK-NEXT: mov z4.d, x8 ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p5.d, p0/z, z3.d, z4.d ; CHECK-NEXT: fcmgt p6.d, p0/z, z2.d, z4.d @@ -528,12 +528,12 @@ define @test_signed_v4f64_v4i64( %f) { ; CHECK-NEXT: mov x8, #4890909195324358655 // =0x43dfffffffffffff ; CHECK-NEXT: mov z6.d, #0x7fffffffffffffff ; CHECK-NEXT: mov z4.d, x8 -; CHECK-NEXT: movprfx z5, z1 -; CHECK-NEXT: fcvtzs z5.d, p0/m, z1.d ; CHECK-NEXT: fcmge p1.d, p0/z, z0.d, z2.d ; CHECK-NEXT: fcmge p2.d, p0/z, z1.d, z2.d ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: fcvtzs z2.d, p0/m, z0.d +; CHECK-NEXT: movprfx z5, z1 +; CHECK-NEXT: fcvtzs z5.d, p0/m, z1.d ; CHECK-NEXT: fcmgt p3.d, p0/z, z0.d, z4.d ; CHECK-NEXT: fcmgt p4.d, p0/z, z1.d, z4.d ; CHECK-NEXT: not p1.b, p0/z, p1.b @@ -629,13 +629,13 @@ define @test_signed_v8f16_v8i32( %f) { ; CHECK-NEXT: mov w8, #31743 // =0x7bff ; CHECK-NEXT: mov z3.s, #0x80000000 ; CHECK-NEXT: mov z4.h, w8 -; CHECK-NEXT: movprfx z5, z0 -; CHECK-NEXT: fcvtzs z5.s, p0/m, z0.h ; CHECK-NEXT: mov z6.s, #0x7fffffff ; CHECK-NEXT: fcmge p1.h, p0/z, z1.h, z2.h ; CHECK-NEXT: fcmge p2.h, p0/z, z0.h, z2.h ; CHECK-NEXT: movprfx z2, z1 ; CHECK-NEXT: fcvtzs z2.s, p0/m, z1.h +; CHECK-NEXT: movprfx z5, z0 +; CHECK-NEXT: fcvtzs z5.s, p0/m, z0.h ; CHECK-NEXT: fcmgt p3.h, p0/z, z1.h, z4.h ; CHECK-NEXT: fcmgt p4.h, p0/z, z0.h, z4.h ; CHECK-NEXT: not p1.b, p0/z, p1.b @@ -742,13 +742,13 @@ define @test_signed_v4f16_v4i64( %f) { ; CHECK-NEXT: mov w8, #31743 // =0x7bff ; CHECK-NEXT: mov z3.d, #0x8000000000000000 ; CHECK-NEXT: mov z4.h, w8 -; CHECK-NEXT: movprfx z5, z0 -; CHECK-NEXT: fcvtzs z5.d, p0/m, z0.h ; CHECK-NEXT: mov z6.d, #0x7fffffffffffffff ; CHECK-NEXT: fcmge p1.h, p0/z, z1.h, z2.h ; CHECK-NEXT: fcmge p2.h, p0/z, z0.h, z2.h ; CHECK-NEXT: movprfx z2, z1 ; CHECK-NEXT: fcvtzs z2.d, p0/m, z1.h +; CHECK-NEXT: movprfx z5, z0 +; CHECK-NEXT: fcvtzs z5.d, p0/m, z0.h ; CHECK-NEXT: fcmgt p3.h, p0/z, z1.h, z4.h ; CHECK-NEXT: fcmgt p4.h, p0/z, z0.h, z4.h ; CHECK-NEXT: not p1.b, p0/z, p1.b diff --git a/llvm/test/CodeGen/AArch64/sve-fptoui-sat.ll b/llvm/test/CodeGen/AArch64/sve-fptoui-sat.ll index c9e06fd9f341..c56c0b37888d 100644 --- a/llvm/test/CodeGen/AArch64/sve-fptoui-sat.ll +++ b/llvm/test/CodeGen/AArch64/sve-fptoui-sat.ll @@ -16,10 +16,10 @@ define @test_signed_v2f32_v2i32( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov w8, #1333788671 // =0x4f7fffff -; CHECK-NEXT: movprfx z2, z0 -; CHECK-NEXT: fcvtzu z2.d, p0/m, z0.s ; CHECK-NEXT: mov z1.s, w8 ; CHECK-NEXT: fcmge p1.s, p0/z, z0.s, #0.0 +; CHECK-NEXT: movprfx z2, z0 +; CHECK-NEXT: fcvtzu z2.d, p0/m, z0.s ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.s, p0/z, z0.s, z1.s ; CHECK-NEXT: mov z0.d, #0xffffffff @@ -35,10 +35,10 @@ define @test_signed_v4f32_v4i32( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: mov w8, #1333788671 // =0x4f7fffff -; CHECK-NEXT: movprfx z1, z0 -; CHECK-NEXT: fcvtzu z1.s, p0/m, z0.s ; CHECK-NEXT: mov z2.s, w8 ; CHECK-NEXT: fcmge p1.s, p0/z, z0.s, #0.0 +; CHECK-NEXT: movprfx z1, z0 +; CHECK-NEXT: fcvtzu z1.s, p0/m, z0.s ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.s, p0/z, z0.s, z2.s ; CHECK-NEXT: mov z1.s, p1/m, #0 // =0x0 @@ -54,13 +54,13 @@ define @test_signed_v8f32_v8i32( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: mov w8, #1333788671 // =0x4f7fffff +; CHECK-NEXT: mov z4.s, w8 +; CHECK-NEXT: fcmge p1.s, p0/z, z0.s, #0.0 +; CHECK-NEXT: fcmge p2.s, p0/z, z1.s, #0.0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: fcvtzu z2.s, p0/m, z0.s -; CHECK-NEXT: mov z4.s, w8 ; CHECK-NEXT: movprfx z3, z1 ; CHECK-NEXT: fcvtzu z3.s, p0/m, z1.s -; CHECK-NEXT: fcmge p1.s, p0/z, z0.s, #0.0 -; CHECK-NEXT: fcmge p2.s, p0/z, z1.s, #0.0 ; CHECK-NEXT: fcmgt p3.s, p0/z, z0.s, z4.s ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: not p2.b, p0/z, p2.b @@ -81,11 +81,11 @@ define @test_signed_v4f32_v4i16( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: mov w8, #65280 // =0xff00 -; CHECK-NEXT: movprfx z2, z0 -; CHECK-NEXT: fcvtzu z2.s, p0/m, z0.s ; CHECK-NEXT: movk w8, #18303, lsl #16 ; CHECK-NEXT: mov z1.s, w8 ; CHECK-NEXT: fcmge p1.s, p0/z, z0.s, #0.0 +; CHECK-NEXT: movprfx z2, z0 +; CHECK-NEXT: fcvtzu z2.s, p0/m, z0.s ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.s, p0/z, z0.s, z1.s ; CHECK-NEXT: mov z0.s, #65535 // =0xffff @@ -101,14 +101,14 @@ define @test_signed_v8f32_v8i16( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: mov w8, #65280 // =0xff00 -; CHECK-NEXT: movprfx z3, z1 -; CHECK-NEXT: fcvtzu z3.s, p0/m, z1.s ; CHECK-NEXT: movk w8, #18303, lsl #16 -; CHECK-NEXT: movprfx z4, z0 -; CHECK-NEXT: fcvtzu z4.s, p0/m, z0.s ; CHECK-NEXT: mov z2.s, w8 ; CHECK-NEXT: fcmge p1.s, p0/z, z1.s, #0.0 ; CHECK-NEXT: fcmge p2.s, p0/z, z0.s, #0.0 +; CHECK-NEXT: movprfx z3, z1 +; CHECK-NEXT: fcvtzu z3.s, p0/m, z1.s +; CHECK-NEXT: movprfx z4, z0 +; CHECK-NEXT: fcvtzu z4.s, p0/m, z0.s ; CHECK-NEXT: fcmgt p3.s, p0/z, z1.s, z2.s ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: not p2.b, p0/z, p2.b @@ -129,10 +129,10 @@ define @test_signed_v2f32_v2i64( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov w8, #1602224127 // =0x5f7fffff -; CHECK-NEXT: movprfx z1, z0 -; CHECK-NEXT: fcvtzu z1.d, p0/m, z0.s ; CHECK-NEXT: mov z2.s, w8 ; CHECK-NEXT: fcmge p1.s, p0/z, z0.s, #0.0 +; CHECK-NEXT: movprfx z1, z0 +; CHECK-NEXT: fcvtzu z1.d, p0/m, z0.s ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.s, p0/z, z0.s, z2.s ; CHECK-NEXT: mov z1.d, p1/m, #0 // =0x0 @@ -150,13 +150,13 @@ define @test_signed_v4f32_v4i64( %f) { ; CHECK-NEXT: uunpklo z2.d, z0.s ; CHECK-NEXT: uunpkhi z3.d, z0.s ; CHECK-NEXT: mov w8, #1602224127 // =0x5f7fffff +; CHECK-NEXT: mov z4.s, w8 +; CHECK-NEXT: fcmge p1.s, p0/z, z2.s, #0.0 +; CHECK-NEXT: fcmge p2.s, p0/z, z3.s, #0.0 ; CHECK-NEXT: movprfx z0, z2 ; CHECK-NEXT: fcvtzu z0.d, p0/m, z2.s ; CHECK-NEXT: movprfx z1, z3 ; CHECK-NEXT: fcvtzu z1.d, p0/m, z3.s -; CHECK-NEXT: mov z4.s, w8 -; CHECK-NEXT: fcmge p1.s, p0/z, z2.s, #0.0 -; CHECK-NEXT: fcmge p2.s, p0/z, z3.s, #0.0 ; CHECK-NEXT: fcmgt p3.s, p0/z, z2.s, z4.s ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: not p2.b, p0/z, p2.b @@ -185,11 +185,11 @@ define @test_signed_v2f64_v2i32( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #281474974613504 // =0xffffffe00000 -; CHECK-NEXT: movprfx z2, z0 -; CHECK-NEXT: fcvtzu z2.d, p0/m, z0.d ; CHECK-NEXT: movk x8, #16879, lsl #48 ; CHECK-NEXT: mov z1.d, x8 ; CHECK-NEXT: fcmge p1.d, p0/z, z0.d, #0.0 +; CHECK-NEXT: movprfx z2, z0 +; CHECK-NEXT: fcvtzu z2.d, p0/m, z0.d ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.d, p0/z, z0.d, z1.d ; CHECK-NEXT: mov z0.d, #0xffffffff @@ -205,14 +205,14 @@ define @test_signed_v4f64_v4i32( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #281474974613504 // =0xffffffe00000 -; CHECK-NEXT: movprfx z3, z1 -; CHECK-NEXT: fcvtzu z3.d, p0/m, z1.d ; CHECK-NEXT: movk x8, #16879, lsl #48 -; CHECK-NEXT: movprfx z4, z0 -; CHECK-NEXT: fcvtzu z4.d, p0/m, z0.d ; CHECK-NEXT: mov z2.d, x8 ; CHECK-NEXT: fcmge p1.d, p0/z, z1.d, #0.0 ; CHECK-NEXT: fcmge p2.d, p0/z, z0.d, #0.0 +; CHECK-NEXT: movprfx z3, z1 +; CHECK-NEXT: fcvtzu z3.d, p0/m, z1.d +; CHECK-NEXT: movprfx z4, z0 +; CHECK-NEXT: fcvtzu z4.d, p0/m, z0.d ; CHECK-NEXT: fcmgt p3.d, p0/z, z1.d, z2.d ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: not p2.b, p0/z, p2.b @@ -240,20 +240,20 @@ define @test_signed_v8f64_v8i32( %f) { ; CHECK-NEXT: .cfi_offset w29, -16 ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #281474974613504 // =0xffffffe00000 +; CHECK-NEXT: movk x8, #16879, lsl #48 +; CHECK-NEXT: mov z4.d, x8 +; CHECK-NEXT: fcmge p1.d, p0/z, z1.d, #0.0 +; CHECK-NEXT: fcmge p2.d, p0/z, z0.d, #0.0 +; CHECK-NEXT: fcmge p3.d, p0/z, z3.d, #0.0 +; CHECK-NEXT: fcmge p4.d, p0/z, z2.d, #0.0 ; CHECK-NEXT: movprfx z5, z1 ; CHECK-NEXT: fcvtzu z5.d, p0/m, z1.d -; CHECK-NEXT: movk x8, #16879, lsl #48 ; CHECK-NEXT: movprfx z6, z0 ; CHECK-NEXT: fcvtzu z6.d, p0/m, z0.d ; CHECK-NEXT: movprfx z7, z3 ; CHECK-NEXT: fcvtzu z7.d, p0/m, z3.d -; CHECK-NEXT: mov z4.d, x8 ; CHECK-NEXT: movprfx z24, z2 ; CHECK-NEXT: fcvtzu z24.d, p0/m, z2.d -; CHECK-NEXT: fcmge p1.d, p0/z, z1.d, #0.0 -; CHECK-NEXT: fcmge p2.d, p0/z, z0.d, #0.0 -; CHECK-NEXT: fcmge p3.d, p0/z, z3.d, #0.0 -; CHECK-NEXT: fcmge p4.d, p0/z, z2.d, #0.0 ; CHECK-NEXT: fcmgt p5.d, p0/z, z1.d, z4.d ; CHECK-NEXT: fcmgt p6.d, p0/z, z0.d, z4.d ; CHECK-NEXT: mov z0.d, #0xffffffff @@ -288,14 +288,14 @@ define @test_signed_v4f64_v4i16( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #281337537757184 // =0xffe000000000 -; CHECK-NEXT: movprfx z3, z1 -; CHECK-NEXT: fcvtzu z3.d, p0/m, z1.d ; CHECK-NEXT: movk x8, #16623, lsl #48 -; CHECK-NEXT: movprfx z4, z0 -; CHECK-NEXT: fcvtzu z4.d, p0/m, z0.d ; CHECK-NEXT: mov z2.d, x8 ; CHECK-NEXT: fcmge p1.d, p0/z, z1.d, #0.0 ; CHECK-NEXT: fcmge p2.d, p0/z, z0.d, #0.0 +; CHECK-NEXT: movprfx z3, z1 +; CHECK-NEXT: fcvtzu z3.d, p0/m, z1.d +; CHECK-NEXT: movprfx z4, z0 +; CHECK-NEXT: fcvtzu z4.d, p0/m, z0.d ; CHECK-NEXT: fcmgt p3.d, p0/z, z1.d, z2.d ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: not p2.b, p0/z, p2.b @@ -323,20 +323,20 @@ define @test_signed_v8f64_v8i16( %f) { ; CHECK-NEXT: .cfi_offset w29, -16 ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #281337537757184 // =0xffe000000000 +; CHECK-NEXT: movk x8, #16623, lsl #48 +; CHECK-NEXT: mov z4.d, x8 +; CHECK-NEXT: fcmge p1.d, p0/z, z3.d, #0.0 +; CHECK-NEXT: fcmge p2.d, p0/z, z2.d, #0.0 +; CHECK-NEXT: fcmge p3.d, p0/z, z1.d, #0.0 +; CHECK-NEXT: fcmge p4.d, p0/z, z0.d, #0.0 ; CHECK-NEXT: movprfx z5, z3 ; CHECK-NEXT: fcvtzu z5.d, p0/m, z3.d -; CHECK-NEXT: movk x8, #16623, lsl #48 ; CHECK-NEXT: movprfx z6, z2 ; CHECK-NEXT: fcvtzu z6.d, p0/m, z2.d ; CHECK-NEXT: movprfx z7, z1 ; CHECK-NEXT: fcvtzu z7.d, p0/m, z1.d -; CHECK-NEXT: mov z4.d, x8 ; CHECK-NEXT: movprfx z24, z0 ; CHECK-NEXT: fcvtzu z24.d, p0/m, z0.d -; CHECK-NEXT: fcmge p1.d, p0/z, z3.d, #0.0 -; CHECK-NEXT: fcmge p2.d, p0/z, z2.d, #0.0 -; CHECK-NEXT: fcmge p3.d, p0/z, z1.d, #0.0 -; CHECK-NEXT: fcmge p4.d, p0/z, z0.d, #0.0 ; CHECK-NEXT: fcmgt p5.d, p0/z, z3.d, z4.d ; CHECK-NEXT: fcmgt p6.d, p0/z, z2.d, z4.d ; CHECK-NEXT: mov z2.d, #65535 // =0xffff @@ -372,10 +372,10 @@ define @test_signed_v2f64_v2i64( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #4895412794951729151 // =0x43efffffffffffff -; CHECK-NEXT: movprfx z1, z0 -; CHECK-NEXT: fcvtzu z1.d, p0/m, z0.d ; CHECK-NEXT: mov z2.d, x8 ; CHECK-NEXT: fcmge p1.d, p0/z, z0.d, #0.0 +; CHECK-NEXT: movprfx z1, z0 +; CHECK-NEXT: fcvtzu z1.d, p0/m, z0.d ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.d, p0/z, z0.d, z2.d ; CHECK-NEXT: mov z1.d, p1/m, #0 // =0x0 @@ -391,13 +391,13 @@ define @test_signed_v4f64_v4i64( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov x8, #4895412794951729151 // =0x43efffffffffffff +; CHECK-NEXT: mov z4.d, x8 +; CHECK-NEXT: fcmge p1.d, p0/z, z0.d, #0.0 +; CHECK-NEXT: fcmge p2.d, p0/z, z1.d, #0.0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: fcvtzu z2.d, p0/m, z0.d -; CHECK-NEXT: mov z4.d, x8 ; CHECK-NEXT: movprfx z3, z1 ; CHECK-NEXT: fcvtzu z3.d, p0/m, z1.d -; CHECK-NEXT: fcmge p1.d, p0/z, z0.d, #0.0 -; CHECK-NEXT: fcmge p2.d, p0/z, z1.d, #0.0 ; CHECK-NEXT: fcmgt p3.d, p0/z, z0.d, z4.d ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: not p2.b, p0/z, p2.b @@ -429,10 +429,10 @@ define @test_signed_v2f16_v2i32( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov w8, #31743 // =0x7bff -; CHECK-NEXT: movprfx z2, z0 -; CHECK-NEXT: fcvtzu z2.d, p0/m, z0.h ; CHECK-NEXT: mov z1.h, w8 ; CHECK-NEXT: fcmge p1.h, p0/z, z0.h, #0.0 +; CHECK-NEXT: movprfx z2, z0 +; CHECK-NEXT: fcvtzu z2.d, p0/m, z0.h ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.h, p0/z, z0.h, z1.h ; CHECK-NEXT: mov z0.d, #0xffffffff @@ -448,10 +448,10 @@ define @test_signed_v4f16_v4i32( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: mov w8, #31743 // =0x7bff -; CHECK-NEXT: movprfx z1, z0 -; CHECK-NEXT: fcvtzu z1.s, p0/m, z0.h ; CHECK-NEXT: mov z2.h, w8 ; CHECK-NEXT: fcmge p1.h, p0/z, z0.h, #0.0 +; CHECK-NEXT: movprfx z1, z0 +; CHECK-NEXT: fcvtzu z1.s, p0/m, z0.h ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.h, p0/z, z0.h, z2.h ; CHECK-NEXT: mov z1.s, p1/m, #0 // =0x0 @@ -469,13 +469,13 @@ define @test_signed_v8f16_v8i32( %f) { ; CHECK-NEXT: uunpklo z2.s, z0.h ; CHECK-NEXT: uunpkhi z3.s, z0.h ; CHECK-NEXT: mov w8, #31743 // =0x7bff +; CHECK-NEXT: mov z4.h, w8 +; CHECK-NEXT: fcmge p1.h, p0/z, z2.h, #0.0 +; CHECK-NEXT: fcmge p2.h, p0/z, z3.h, #0.0 ; CHECK-NEXT: movprfx z0, z2 ; CHECK-NEXT: fcvtzu z0.s, p0/m, z2.h ; CHECK-NEXT: movprfx z1, z3 ; CHECK-NEXT: fcvtzu z1.s, p0/m, z3.h -; CHECK-NEXT: mov z4.h, w8 -; CHECK-NEXT: fcmge p1.h, p0/z, z2.h, #0.0 -; CHECK-NEXT: fcmge p2.h, p0/z, z3.h, #0.0 ; CHECK-NEXT: fcmgt p3.h, p0/z, z2.h, z4.h ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: not p2.b, p0/z, p2.b @@ -494,10 +494,10 @@ define @test_signed_v4f16_v4i16( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: mov w8, #31743 // =0x7bff -; CHECK-NEXT: movprfx z2, z0 -; CHECK-NEXT: fcvtzu z2.s, p0/m, z0.h ; CHECK-NEXT: mov z1.h, w8 ; CHECK-NEXT: fcmge p1.h, p0/z, z0.h, #0.0 +; CHECK-NEXT: movprfx z2, z0 +; CHECK-NEXT: fcvtzu z2.s, p0/m, z0.h ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.h, p0/z, z0.h, z1.h ; CHECK-NEXT: mov z0.s, #65535 // =0xffff @@ -513,10 +513,10 @@ define @test_signed_v8f16_v8i16( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.h ; CHECK-NEXT: mov w8, #31743 // =0x7bff -; CHECK-NEXT: movprfx z1, z0 -; CHECK-NEXT: fcvtzu z1.h, p0/m, z0.h ; CHECK-NEXT: mov z2.h, w8 ; CHECK-NEXT: fcmge p1.h, p0/z, z0.h, #0.0 +; CHECK-NEXT: movprfx z1, z0 +; CHECK-NEXT: fcvtzu z1.h, p0/m, z0.h ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.h, p0/z, z0.h, z2.h ; CHECK-NEXT: mov z1.h, p1/m, #0 // =0x0 @@ -532,10 +532,10 @@ define @test_signed_v2f16_v2i64( %f) { ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov w8, #31743 // =0x7bff -; CHECK-NEXT: movprfx z1, z0 -; CHECK-NEXT: fcvtzu z1.d, p0/m, z0.h ; CHECK-NEXT: mov z2.h, w8 ; CHECK-NEXT: fcmge p1.h, p0/z, z0.h, #0.0 +; CHECK-NEXT: movprfx z1, z0 +; CHECK-NEXT: fcvtzu z1.d, p0/m, z0.h ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: fcmgt p0.h, p0/z, z0.h, z2.h ; CHECK-NEXT: mov z1.d, p1/m, #0 // =0x0 @@ -553,13 +553,13 @@ define @test_signed_v4f16_v4i64( %f) { ; CHECK-NEXT: uunpklo z2.d, z0.s ; CHECK-NEXT: uunpkhi z3.d, z0.s ; CHECK-NEXT: mov w8, #31743 // =0x7bff +; CHECK-NEXT: mov z4.h, w8 +; CHECK-NEXT: fcmge p1.h, p0/z, z2.h, #0.0 +; CHECK-NEXT: fcmge p2.h, p0/z, z3.h, #0.0 ; CHECK-NEXT: movprfx z0, z2 ; CHECK-NEXT: fcvtzu z0.d, p0/m, z2.h ; CHECK-NEXT: movprfx z1, z3 ; CHECK-NEXT: fcvtzu z1.d, p0/m, z3.h -; CHECK-NEXT: mov z4.h, w8 -; CHECK-NEXT: fcmge p1.h, p0/z, z2.h, #0.0 -; CHECK-NEXT: fcmge p2.h, p0/z, z3.h, #0.0 ; CHECK-NEXT: fcmgt p3.h, p0/z, z2.h, z4.h ; CHECK-NEXT: not p1.b, p0/z, p1.b ; CHECK-NEXT: not p2.b, p0/z, p2.b diff --git a/llvm/test/CodeGen/AArch64/sve-gather-scatter-addr-opts.ll b/llvm/test/CodeGen/AArch64/sve-gather-scatter-addr-opts.ll index 1a6e4814cee6..5c4c9463528b 100644 --- a/llvm/test/CodeGen/AArch64/sve-gather-scatter-addr-opts.ll +++ b/llvm/test/CodeGen/AArch64/sve-gather-scatter-addr-opts.ll @@ -71,18 +71,18 @@ define @gather_i8_index_offset_8(ptr %base, i64 %offset, %pg, %data) #0 { ; CHECK-LABEL: scatter_f16_index_offset_var: ; CHECK: // %bb.0: -; CHECK-NEXT: index z1.d, #0, #1 ; CHECK-NEXT: ptrue p1.d +; CHECK-NEXT: index z1.d, #0, #1 ; CHECK-NEXT: mov z2.d, x1 -; CHECK-NEXT: movprfx z4, z2 -; CHECK-NEXT: mla z4.d, p1/m, z1.d, z2.d ; CHECK-NEXT: punpklo p2.h, p0.b ; CHECK-NEXT: uunpklo z3.d, z0.s -; CHECK-NEXT: punpkhi p0.h, p0.b ; CHECK-NEXT: uunpkhi z0.d, z0.s +; CHECK-NEXT: punpkhi p0.h, p0.b +; CHECK-NEXT: movprfx z4, z2 +; CHECK-NEXT: mla z4.d, p1/m, z1.d, z2.d ; CHECK-NEXT: incd z1.d -; CHECK-NEXT: st1h { z3.d }, p2, [x0, z4.d, lsl #1] ; CHECK-NEXT: mad z1.d, p1/m, z2.d, z2.d +; CHECK-NEXT: st1h { z3.d }, p2, [x0, z4.d, lsl #1] ; CHECK-NEXT: st1h { z0.d }, p0, [x0, z1.d, lsl #1] ; CHECK-NEXT: ret %t0 = insertelement undef, i64 %offset, i32 0 diff --git a/llvm/test/CodeGen/AArch64/sve-masked-gather-legalize.ll b/llvm/test/CodeGen/AArch64/sve-masked-gather-legalize.ll index 3ecfa7e6c0b1..e40d65efb158 100644 --- a/llvm/test/CodeGen/AArch64/sve-masked-gather-legalize.ll +++ b/llvm/test/CodeGen/AArch64/sve-masked-gather-legalize.ll @@ -145,10 +145,10 @@ define @masked_gather_nxv4f64(ptr %base, @smulo_nxv64i8( %x, @smulo_nxv64i8( %x, , } @llvm.smul.with.overflow.nxv64i8( %x, %y) %b = extractvalue { , } %a, 0 @@ -262,9 +262,9 @@ define @smulo_nxv32i16( %x, @smulo_nxv32i16( %x, , } @llvm.smul.with.overflow.nxv32i16( %x, %y) %b = extractvalue { , } %a, 0 @@ -374,9 +374,9 @@ define @smulo_nxv16i32( %x, @smulo_nxv16i32( %x, , } @llvm.smul.with.overflow.nxv16i32( %x, %y) %b = extractvalue { , } %a, 0 @@ -465,9 +465,9 @@ define @smulo_nxv8i64( %x, @smulo_nxv8i64( %x, , } @llvm.smul.with.overflow.nxv8i64( %x, %y) %b = extractvalue { , } %a, 0 diff --git a/llvm/test/CodeGen/AArch64/sve-split-fcvt.ll b/llvm/test/CodeGen/AArch64/sve-split-fcvt.ll index 44796606e7a1..3997409172d0 100644 --- a/llvm/test/CodeGen/AArch64/sve-split-fcvt.ll +++ b/llvm/test/CodeGen/AArch64/sve-split-fcvt.ll @@ -6,8 +6,8 @@ define @fcvts_nxv8f16( %a) { ; CHECK-LABEL: fcvts_nxv8f16: ; CHECK: // %bb.0: -; CHECK-NEXT: uunpklo z1.s, z0.h ; CHECK-NEXT: ptrue p0.s +; CHECK-NEXT: uunpklo z1.s, z0.h ; CHECK-NEXT: uunpkhi z2.s, z0.h ; CHECK-NEXT: movprfx z0, z1 ; CHECK-NEXT: fcvt z0.s, p0/m, z1.h @@ -21,8 +21,8 @@ define @fcvts_nxv8f16( %a) { define @fcvtd_nxv4f16( %a) { ; CHECK-LABEL: fcvtd_nxv4f16: ; CHECK: // %bb.0: -; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: uunpkhi z2.d, z0.s ; CHECK-NEXT: movprfx z0, z1 ; CHECK-NEXT: fcvt z0.d, p0/m, z1.h @@ -43,13 +43,13 @@ define @fcvtd_nxv8f16( %a) { ; CHECK-NEXT: uunpkhi z1.d, z1.s ; CHECK-NEXT: uunpklo z3.d, z0.s ; CHECK-NEXT: uunpkhi z4.d, z0.s +; CHECK-NEXT: fcvt z1.d, p0/m, z1.h ; CHECK-NEXT: movprfx z0, z2 ; CHECK-NEXT: fcvt z0.d, p0/m, z2.h ; CHECK-NEXT: movprfx z2, z3 ; CHECK-NEXT: fcvt z2.d, p0/m, z3.h ; CHECK-NEXT: movprfx z3, z4 ; CHECK-NEXT: fcvt z3.d, p0/m, z4.h -; CHECK-NEXT: fcvt z1.d, p0/m, z1.h ; CHECK-NEXT: ret %res = fpext %a to ret %res @@ -58,8 +58,8 @@ define @fcvtd_nxv8f16( %a) { define @fcvtd_nxv4f32( %a) { ; CHECK-LABEL: fcvtd_nxv4f32: ; CHECK: // %bb.0: -; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: uunpkhi z2.d, z0.s ; CHECK-NEXT: movprfx z0, z1 ; CHECK-NEXT: fcvt z0.d, p0/m, z1.s @@ -73,17 +73,17 @@ define @fcvtd_nxv4f32( %a) { define @fcvtd_nxv8f32( %a) { ; CHECK-LABEL: fcvtd_nxv8f32: ; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: uunpklo z2.d, z0.s ; CHECK-NEXT: uunpkhi z3.d, z0.s -; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: uunpklo z4.d, z1.s +; CHECK-NEXT: uunpkhi z5.d, z1.s ; CHECK-NEXT: movprfx z0, z2 ; CHECK-NEXT: fcvt z0.d, p0/m, z2.s -; CHECK-NEXT: movprfx z2, z4 -; CHECK-NEXT: fcvt z2.d, p0/m, z4.s -; CHECK-NEXT: uunpkhi z5.d, z1.s ; CHECK-NEXT: movprfx z1, z3 ; CHECK-NEXT: fcvt z1.d, p0/m, z3.s +; CHECK-NEXT: movprfx z2, z4 +; CHECK-NEXT: fcvt z2.d, p0/m, z4.s ; CHECK-NEXT: movprfx z3, z5 ; CHECK-NEXT: fcvt z3.d, p0/m, z5.s ; CHECK-NEXT: ret @@ -195,8 +195,8 @@ define @fcvtzs_h_nxv8f64( %a) { define @fcvtzs_d_nxv4f32( %a) { ; CHECK-LABEL: fcvtzs_d_nxv4f32: ; CHECK: // %bb.0: -; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: uunpkhi z2.d, z0.s ; CHECK-NEXT: movprfx z0, z1 ; CHECK-NEXT: fcvtzs z0.d, p0/m, z1.s @@ -210,17 +210,17 @@ define @fcvtzs_d_nxv4f32( %a) { define @fcvtzs_s_nxv16f16( %a) { ; CHECK-LABEL: fcvtzs_s_nxv16f16: ; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: uunpklo z2.s, z0.h ; CHECK-NEXT: uunpkhi z3.s, z0.h -; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: uunpklo z4.s, z1.h +; CHECK-NEXT: uunpkhi z5.s, z1.h ; CHECK-NEXT: movprfx z0, z2 ; CHECK-NEXT: fcvtzs z0.s, p0/m, z2.h -; CHECK-NEXT: movprfx z2, z4 -; CHECK-NEXT: fcvtzs z2.s, p0/m, z4.h -; CHECK-NEXT: uunpkhi z5.s, z1.h ; CHECK-NEXT: movprfx z1, z3 ; CHECK-NEXT: fcvtzs z1.s, p0/m, z3.h +; CHECK-NEXT: movprfx z2, z4 +; CHECK-NEXT: fcvtzs z2.s, p0/m, z4.h ; CHECK-NEXT: movprfx z3, z5 ; CHECK-NEXT: fcvtzs z3.s, p0/m, z5.h ; CHECK-NEXT: ret @@ -247,8 +247,8 @@ define @fcvtzu_s_nxv4f64( %a) { define @fcvtzu_d_nxv4f32( %a) { ; CHECK-LABEL: fcvtzu_d_nxv4f32: ; CHECK: // %bb.0: -; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: uunpkhi z2.d, z0.s ; CHECK-NEXT: movprfx z0, z1 ; CHECK-NEXT: fcvtzu z0.d, p0/m, z1.s @@ -301,13 +301,13 @@ define @scvtf_s_nxv16i8( %a) { ; CHECK-NEXT: sunpkhi z1.s, z1.h ; CHECK-NEXT: sunpklo z3.s, z0.h ; CHECK-NEXT: sunpkhi z4.s, z0.h +; CHECK-NEXT: scvtf z1.s, p0/m, z1.s ; CHECK-NEXT: movprfx z0, z2 ; CHECK-NEXT: scvtf z0.s, p0/m, z2.s ; CHECK-NEXT: movprfx z2, z3 ; CHECK-NEXT: scvtf z2.s, p0/m, z3.s ; CHECK-NEXT: movprfx z3, z4 ; CHECK-NEXT: scvtf z3.s, p0/m, z4.s -; CHECK-NEXT: scvtf z1.s, p0/m, z1.s ; CHECK-NEXT: ret %res = sitofp %a to ret %res @@ -316,8 +316,8 @@ define @scvtf_s_nxv16i8( %a) { define @scvtf_d_nxv4i32( %a) { ; CHECK-LABEL: scvtf_d_nxv4i32: ; CHECK: // %bb.0: -; CHECK-NEXT: sunpklo z1.d, z0.s ; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: sunpklo z1.d, z0.s ; CHECK-NEXT: sunpkhi z2.d, z0.s ; CHECK-NEXT: movprfx z0, z1 ; CHECK-NEXT: scvtf z0.d, p0/m, z1.d @@ -378,8 +378,8 @@ define @ucvtf_h_nxv8i64( %a) { define @ucvtf_d_nxv4i32( %a) { ; CHECK-LABEL: ucvtf_d_nxv4i32: ; CHECK: // %bb.0: -; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: uunpklo z1.d, z0.s ; CHECK-NEXT: uunpkhi z2.d, z0.s ; CHECK-NEXT: movprfx z0, z1 ; CHECK-NEXT: ucvtf z0.d, p0/m, z1.d diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-extend-trunc.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-extend-trunc.ll index 37cc79011a98..28e02da53af4 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-extend-trunc.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-extend-trunc.ll @@ -239,10 +239,10 @@ define void @fcvt_v16f16_v16f64(ptr %a, ptr %b) { ; CHECK-NEXT: mov x8, #4 // =0x4 ; CHECK-NEXT: fcvt z0.d, p0/m, z0.h ; CHECK-NEXT: ld1h { z4.d }, p0/z, [x0, x8, lsl #1] -; CHECK-NEXT: fcvt z1.d, p0/m, z1.h ; CHECK-NEXT: mov x8, #6 // =0x6 -; CHECK-NEXT: fcvt z2.d, p0/m, z2.h +; CHECK-NEXT: fcvt z1.d, p0/m, z1.h ; CHECK-NEXT: ld1h { z5.d }, p0/z, [x0, x8, lsl #1] +; CHECK-NEXT: fcvt z2.d, p0/m, z2.h ; CHECK-NEXT: mov x8, #2 // =0x2 ; CHECK-NEXT: fcvt z3.d, p0/m, z3.h ; CHECK-NEXT: ld1h { z7.d }, p0/z, [x0, x8, lsl #1] @@ -255,8 +255,8 @@ define void @fcvt_v16f16_v16f64(ptr %a, ptr %b) { ; CHECK-NEXT: stp q2, q3, [x1, #64] ; CHECK-NEXT: movprfx z2, z7 ; CHECK-NEXT: fcvt z2.d, p0/m, z7.h -; CHECK-NEXT: stp q1, q2, [x1] ; CHECK-NEXT: stp q4, q0, [x1, #32] +; CHECK-NEXT: stp q1, q2, [x1] ; CHECK-NEXT: ret %op1 = load <16 x half>, ptr %a %res = fpext <16 x half> %op1 to <16 x double> diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-div.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-div.ll index 5e3ce0ddebe2..fcf4f21c6ea8 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-div.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-div.ll @@ -750,14 +750,14 @@ define void @udiv_constantsplat_v8i32(ptr %a) { ; SVE-NEXT: mov z0.s, w8 ; SVE-NEXT: movprfx z3, z1 ; SVE-NEXT: umulh z3.s, p0/m, z3.s, z0.s -; SVE-NEXT: sub z1.s, z1.s, z3.s ; SVE-NEXT: umulh z0.s, p0/m, z0.s, z2.s -; SVE-NEXT: lsr z1.s, z1.s, #1 +; SVE-NEXT: sub z1.s, z1.s, z3.s ; SVE-NEXT: sub z2.s, z2.s, z0.s -; SVE-NEXT: add z1.s, z1.s, z3.s +; SVE-NEXT: lsr z1.s, z1.s, #1 ; SVE-NEXT: lsr z2.s, z2.s, #1 -; SVE-NEXT: lsr z1.s, z1.s, #6 +; SVE-NEXT: add z1.s, z1.s, z3.s ; SVE-NEXT: add z0.s, z2.s, z0.s +; SVE-NEXT: lsr z1.s, z1.s, #6 ; SVE-NEXT: lsr z0.s, z0.s, #6 ; SVE-NEXT: stp q1, q0, [x0] ; SVE-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-rem.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-rem.ll index eb95a410209b..4a1209b942f4 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-rem.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-rem.ll @@ -139,7 +139,6 @@ define void @srem_v32i8(ptr %a, ptr %b) { ; CHECK-NEXT: sdiv z5.s, p0/m, z5.s, z4.s ; CHECK-NEXT: ldr q3, [x0] ; CHECK-NEXT: ldr q4, [x1] -; CHECK-NEXT: uzp1 z5.h, z5.h, z5.h ; CHECK-NEXT: mov z18.d, z3.d ; CHECK-NEXT: mov z17.d, z4.d ; CHECK-NEXT: uzp1 z6.h, z6.h, z6.h @@ -154,6 +153,7 @@ define void @srem_v32i8(ptr %a, ptr %b) { ; CHECK-NEXT: sdivr z7.s, p0/m, z7.s, z16.s ; CHECK-NEXT: sunpklo z18.s, z18.h ; CHECK-NEXT: uzp1 z2.h, z2.h, z2.h +; CHECK-NEXT: uzp1 z5.h, z5.h, z5.h ; CHECK-NEXT: sunpklo z17.s, z17.h ; CHECK-NEXT: sdivr z19.s, p0/m, z19.s, z20.s ; CHECK-NEXT: sunpklo z20.h, z3.b @@ -172,21 +172,21 @@ define void @srem_v32i8(ptr %a, ptr %b) { ; CHECK-NEXT: sdivr z18.s, p0/m, z18.s, z20.s ; CHECK-NEXT: ptrue p0.h, vl4 ; CHECK-NEXT: uzp1 z19.h, z21.h, z21.h +; CHECK-NEXT: splice z16.h, p0, z16.h, z17.h ; CHECK-NEXT: splice z2.h, p0, z2.h, z5.h ; CHECK-NEXT: splice z6.h, p0, z6.h, z7.h -; CHECK-NEXT: splice z16.h, p0, z16.h, z17.h +; CHECK-NEXT: uzp1 z5.b, z16.b, z16.b ; CHECK-NEXT: uzp1 z2.b, z2.b, z2.b ; CHECK-NEXT: uzp1 z6.b, z6.b, z6.b -; CHECK-NEXT: uzp1 z5.b, z16.b, z16.b ; CHECK-NEXT: uzp1 z18.h, z18.h, z18.h ; CHECK-NEXT: splice z19.h, p0, z19.h, z18.h ; CHECK-NEXT: ptrue p0.b, vl8 ; CHECK-NEXT: uzp1 z7.b, z19.b, z19.b ; CHECK-NEXT: splice z6.b, p0, z6.b, z2.b ; CHECK-NEXT: splice z7.b, p0, z7.b, z5.b +; CHECK-NEXT: mls z0.b, p1/m, z6.b, z1.b ; CHECK-NEXT: movprfx z2, z3 ; CHECK-NEXT: mls z2.b, p1/m, z7.b, z4.b -; CHECK-NEXT: mls z0.b, p1/m, z6.b, z1.b ; CHECK-NEXT: stp q2, q0, [x0] ; CHECK-NEXT: ret %op1 = load <32 x i8>, ptr %a @@ -293,8 +293,8 @@ define <2 x i32> @srem_v2i32(<2 x i32> %op1, <2 x i32> %op2) { ; CHECK-LABEL: srem_v2i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s, vl2 -; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: sdiv z2.s, p0/m, z2.s, z1.s ; CHECK-NEXT: mls z0.s, p0/m, z2.s, z1.s @@ -308,8 +308,8 @@ define <4 x i32> @srem_v4i32(<4 x i32> %op1, <4 x i32> %op2) { ; CHECK-LABEL: srem_v4i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s, vl4 -; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 +; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: sdiv z2.s, p0/m, z2.s, z1.s ; CHECK-NEXT: mls z0.s, p0/m, z2.s, z1.s @@ -345,8 +345,8 @@ define <1 x i64> @srem_v1i64(<1 x i64> %op1, <1 x i64> %op2) { ; CHECK-LABEL: srem_v1i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d, vl1 -; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: sdiv z2.d, p0/m, z2.d, z1.d ; CHECK-NEXT: mls z0.d, p0/m, z2.d, z1.d @@ -360,8 +360,8 @@ define <2 x i64> @srem_v2i64(<2 x i64> %op1, <2 x i64> %op2) { ; CHECK-LABEL: srem_v2i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d, vl2 -; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 +; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: sdiv z2.d, p0/m, z2.d, z1.d ; CHECK-NEXT: mls z0.d, p0/m, z2.d, z1.d @@ -528,7 +528,6 @@ define void @urem_v32i8(ptr %a, ptr %b) { ; CHECK-NEXT: udiv z5.s, p0/m, z5.s, z4.s ; CHECK-NEXT: ldr q3, [x0] ; CHECK-NEXT: ldr q4, [x1] -; CHECK-NEXT: uzp1 z5.h, z5.h, z5.h ; CHECK-NEXT: mov z18.d, z3.d ; CHECK-NEXT: mov z17.d, z4.d ; CHECK-NEXT: uzp1 z6.h, z6.h, z6.h @@ -543,6 +542,7 @@ define void @urem_v32i8(ptr %a, ptr %b) { ; CHECK-NEXT: udivr z7.s, p0/m, z7.s, z16.s ; CHECK-NEXT: uunpklo z18.s, z18.h ; CHECK-NEXT: uzp1 z2.h, z2.h, z2.h +; CHECK-NEXT: uzp1 z5.h, z5.h, z5.h ; CHECK-NEXT: uunpklo z17.s, z17.h ; CHECK-NEXT: udivr z19.s, p0/m, z19.s, z20.s ; CHECK-NEXT: uunpklo z20.h, z3.b @@ -561,21 +561,21 @@ define void @urem_v32i8(ptr %a, ptr %b) { ; CHECK-NEXT: udivr z18.s, p0/m, z18.s, z20.s ; CHECK-NEXT: ptrue p0.h, vl4 ; CHECK-NEXT: uzp1 z19.h, z21.h, z21.h +; CHECK-NEXT: splice z16.h, p0, z16.h, z17.h ; CHECK-NEXT: splice z2.h, p0, z2.h, z5.h ; CHECK-NEXT: splice z6.h, p0, z6.h, z7.h -; CHECK-NEXT: splice z16.h, p0, z16.h, z17.h +; CHECK-NEXT: uzp1 z5.b, z16.b, z16.b ; CHECK-NEXT: uzp1 z2.b, z2.b, z2.b ; CHECK-NEXT: uzp1 z6.b, z6.b, z6.b -; CHECK-NEXT: uzp1 z5.b, z16.b, z16.b ; CHECK-NEXT: uzp1 z18.h, z18.h, z18.h ; CHECK-NEXT: splice z19.h, p0, z19.h, z18.h ; CHECK-NEXT: ptrue p0.b, vl8 ; CHECK-NEXT: uzp1 z7.b, z19.b, z19.b ; CHECK-NEXT: splice z6.b, p0, z6.b, z2.b ; CHECK-NEXT: splice z7.b, p0, z7.b, z5.b +; CHECK-NEXT: mls z0.b, p1/m, z6.b, z1.b ; CHECK-NEXT: movprfx z2, z3 ; CHECK-NEXT: mls z2.b, p1/m, z7.b, z4.b -; CHECK-NEXT: mls z0.b, p1/m, z6.b, z1.b ; CHECK-NEXT: stp q2, q0, [x0] ; CHECK-NEXT: ret %op1 = load <32 x i8>, ptr %a @@ -682,8 +682,8 @@ define <2 x i32> @urem_v2i32(<2 x i32> %op1, <2 x i32> %op2) { ; CHECK-LABEL: urem_v2i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s, vl2 -; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: udiv z2.s, p0/m, z2.s, z1.s ; CHECK-NEXT: mls z0.s, p0/m, z2.s, z1.s @@ -697,8 +697,8 @@ define <4 x i32> @urem_v4i32(<4 x i32> %op1, <4 x i32> %op2) { ; CHECK-LABEL: urem_v4i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s, vl4 -; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 +; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: udiv z2.s, p0/m, z2.s, z1.s ; CHECK-NEXT: mls z0.s, p0/m, z2.s, z1.s @@ -734,8 +734,8 @@ define <1 x i64> @urem_v1i64(<1 x i64> %op1, <1 x i64> %op2) { ; CHECK-LABEL: urem_v1i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d, vl1 -; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: // kill: def $d1 killed $d1 def $z1 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: udiv z2.d, p0/m, z2.d, z1.d ; CHECK-NEXT: mls z0.d, p0/m, z2.d, z1.d @@ -749,8 +749,8 @@ define <2 x i64> @urem_v2i64(<2 x i64> %op1, <2 x i64> %op2) { ; CHECK-LABEL: urem_v2i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d, vl2 -; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 +; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 ; CHECK-NEXT: movprfx z2, z0 ; CHECK-NEXT: udiv z2.d, p0/m, z2.d, z1.d ; CHECK-NEXT: mls z0.d, p0/m, z2.d, z1.d diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-to-fp.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-to-fp.ll index c110e89326cc..5c5cf68135bf 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-to-fp.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-to-fp.ll @@ -221,21 +221,21 @@ define void @ucvtf_v16i16_v16f64(ptr %a, ptr %b) { ; CHECK-NEXT: ext z6.b, z6.b, z1.b, #8 ; CHECK-NEXT: uunpklo z1.d, z1.s ; CHECK-NEXT: ucvtf z2.d, p0/m, z2.d -; CHECK-NEXT: ucvtf z3.d, p0/m, z3.d ; CHECK-NEXT: uunpklo z7.d, z7.s +; CHECK-NEXT: ucvtf z3.d, p0/m, z3.d ; CHECK-NEXT: uunpklo z5.d, z5.s +; CHECK-NEXT: uunpklo z6.d, z6.s ; CHECK-NEXT: ucvtf z4.d, p0/m, z4.d ; CHECK-NEXT: ucvtf z0.d, p0/m, z0.d -; CHECK-NEXT: uunpklo z6.d, z6.s ; CHECK-NEXT: ucvtf z1.d, p0/m, z1.d ; CHECK-NEXT: ucvtf z5.d, p0/m, z5.d ; CHECK-NEXT: stp q2, q4, [x1, #64] ; CHECK-NEXT: movprfx z2, z6 ; CHECK-NEXT: ucvtf z2.d, p0/m, z6.d -; CHECK-NEXT: stp q1, q2, [x1, #32] ; CHECK-NEXT: stp q0, q5, [x1, #96] ; CHECK-NEXT: movprfx z0, z7 ; CHECK-NEXT: ucvtf z0.d, p0/m, z7.d +; CHECK-NEXT: stp q1, q2, [x1, #32] ; CHECK-NEXT: stp q3, q0, [x1] ; CHECK-NEXT: ret %op1 = load <16 x i16>, ptr %a @@ -481,10 +481,10 @@ define <8 x half> @ucvtf_v8i64_v8f16(ptr %a) { ; CHECK-NEXT: uzp1 z3.s, z3.s, z3.s ; CHECK-NEXT: uzp1 z2.s, z2.s, z2.s ; CHECK-NEXT: splice z1.s, p0, z1.s, z0.s -; CHECK-NEXT: movprfx z0, z1 -; CHECK-NEXT: fcvt z0.h, p1/m, z1.s ; CHECK-NEXT: splice z2.s, p0, z2.s, z3.s ; CHECK-NEXT: ptrue p0.h, vl4 +; CHECK-NEXT: movprfx z0, z1 +; CHECK-NEXT: fcvt z0.h, p1/m, z1.s ; CHECK-NEXT: movprfx z1, z2 ; CHECK-NEXT: fcvt z1.h, p1/m, z2.s ; CHECK-NEXT: uzp1 z2.h, z0.h, z0.h @@ -794,21 +794,21 @@ define void @scvtf_v16i16_v16f64(ptr %a, ptr %b) { ; CHECK-NEXT: ext z6.b, z6.b, z1.b, #8 ; CHECK-NEXT: sunpklo z1.d, z1.s ; CHECK-NEXT: scvtf z2.d, p0/m, z2.d -; CHECK-NEXT: scvtf z3.d, p0/m, z3.d ; CHECK-NEXT: sunpklo z7.d, z7.s +; CHECK-NEXT: scvtf z3.d, p0/m, z3.d ; CHECK-NEXT: sunpklo z5.d, z5.s +; CHECK-NEXT: sunpklo z6.d, z6.s ; CHECK-NEXT: scvtf z4.d, p0/m, z4.d ; CHECK-NEXT: scvtf z0.d, p0/m, z0.d -; CHECK-NEXT: sunpklo z6.d, z6.s ; CHECK-NEXT: scvtf z1.d, p0/m, z1.d ; CHECK-NEXT: scvtf z5.d, p0/m, z5.d ; CHECK-NEXT: stp q2, q4, [x1, #64] ; CHECK-NEXT: movprfx z2, z6 ; CHECK-NEXT: scvtf z2.d, p0/m, z6.d -; CHECK-NEXT: stp q1, q2, [x1, #32] ; CHECK-NEXT: stp q0, q5, [x1, #96] ; CHECK-NEXT: movprfx z0, z7 ; CHECK-NEXT: scvtf z0.d, p0/m, z7.d +; CHECK-NEXT: stp q1, q2, [x1, #32] ; CHECK-NEXT: stp q3, q0, [x1] ; CHECK-NEXT: ret %op1 = load <16 x i16>, ptr %a @@ -982,16 +982,16 @@ define void @scvtf_v16i32_v16f64(ptr %a, ptr %b) { ; CHECK-NEXT: sunpklo z0.d, z0.s ; CHECK-NEXT: sunpklo z1.d, z1.s ; CHECK-NEXT: ext z6.b, z6.b, z4.b, #8 -; CHECK-NEXT: sunpklo z4.d, z4.s ; CHECK-NEXT: ext z7.b, z7.b, z5.b, #8 +; CHECK-NEXT: sunpklo z4.d, z4.s ; CHECK-NEXT: sunpklo z5.d, z5.s ; CHECK-NEXT: sunpklo z2.d, z2.s ; CHECK-NEXT: sunpklo z3.d, z3.s ; CHECK-NEXT: scvtf z0.d, p0/m, z0.d ; CHECK-NEXT: sunpklo z6.d, z6.s +; CHECK-NEXT: sunpklo z7.d, z7.s ; CHECK-NEXT: scvtf z1.d, p0/m, z1.d ; CHECK-NEXT: scvtf z4.d, p0/m, z4.d -; CHECK-NEXT: sunpklo z7.d, z7.s ; CHECK-NEXT: scvtf z2.d, p0/m, z2.d ; CHECK-NEXT: scvtf z3.d, p0/m, z3.d ; CHECK-NEXT: stp q1, q3, [x1, #64] diff --git a/llvm/test/CodeGen/AArch64/sve-umulo-sdnode.ll b/llvm/test/CodeGen/AArch64/sve-umulo-sdnode.ll index 45d796f68c42..36d64725742e 100644 --- a/llvm/test/CodeGen/AArch64/sve-umulo-sdnode.ll +++ b/llvm/test/CodeGen/AArch64/sve-umulo-sdnode.ll @@ -120,16 +120,16 @@ define @umulo_nxv64i8( %x, , } @llvm.umul.with.overflow.nxv64i8( %x, %y) %b = extractvalue { , } %a, 0 @@ -237,16 +237,16 @@ define @umulo_nxv32i16( %x, , } @llvm.umul.with.overflow.nxv32i16( %x, %y) %b = extractvalue { , } %a, 0 @@ -334,16 +334,16 @@ define @umulo_nxv16i32( %x, , } @llvm.umul.with.overflow.nxv16i32( %x, %y) %b = extractvalue { , } %a, 0 @@ -411,16 +411,16 @@ define @umulo_nxv8i64( %x, , } @llvm.umul.with.overflow.nxv8i64( %x, %y) %b = extractvalue { , } %a, 0 diff --git a/llvm/test/CodeGen/AArch64/sve-vecreduce-dot.ll b/llvm/test/CodeGen/AArch64/sve-vecreduce-dot.ll index 4d0d2a991d0e..194d1071301d 100644 --- a/llvm/test/CodeGen/AArch64/sve-vecreduce-dot.ll +++ b/llvm/test/CodeGen/AArch64/sve-vecreduce-dot.ll @@ -31,8 +31,8 @@ define i32 @test( %bin.rdx, %bin.rdx2) { ; CHECK-NEXT: sunpkhi z24.s, z3.h ; CHECK-NEXT: mul z0.s, p0/m, z0.s, z2.s ; CHECK-NEXT: sunpkhi z2.s, z7.h -; CHECK-NEXT: sunpklo z3.s, z3.h ; CHECK-NEXT: sunpklo z7.s, z7.h +; CHECK-NEXT: sunpklo z3.s, z3.h ; CHECK-NEXT: mla z0.s, p0/m, z25.s, z24.s ; CHECK-NEXT: mad z2.s, p0/m, z6.s, z4.s ; CHECK-NEXT: mad z1.s, p0/m, z3.s, z26.s diff --git a/llvm/test/CodeGen/AArch64/sve2-xar.ll b/llvm/test/CodeGen/AArch64/sve2-xar.ll index 62680522bab9..e297ade6b9ae 100644 --- a/llvm/test/CodeGen/AArch64/sve2-xar.ll +++ b/llvm/test/CodeGen/AArch64/sve2-xar.ll @@ -155,8 +155,8 @@ define @xar_nxv2i64_l_neg1( %x, Date: Fri, 12 Apr 2024 16:49:52 +0800 Subject: [PATCH 047/464] [LoongArch] Pre commit test for #88371. NFC --- .../CodeGenPrepare/LoongArch/lit.local.cfg | 2 ++ .../CodeGenPrepare/LoongArch/splitgep.ll | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 llvm/test/Transforms/CodeGenPrepare/LoongArch/lit.local.cfg create mode 100644 llvm/test/Transforms/CodeGenPrepare/LoongArch/splitgep.ll diff --git a/llvm/test/Transforms/CodeGenPrepare/LoongArch/lit.local.cfg b/llvm/test/Transforms/CodeGenPrepare/LoongArch/lit.local.cfg new file mode 100644 index 000000000000..cc24278acbb4 --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/LoongArch/lit.local.cfg @@ -0,0 +1,2 @@ +if not "LoongArch" in config.root.targets: + config.unsupported = True diff --git a/llvm/test/Transforms/CodeGenPrepare/LoongArch/splitgep.ll b/llvm/test/Transforms/CodeGenPrepare/LoongArch/splitgep.ll new file mode 100644 index 000000000000..ca2a16a0ca7e --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/LoongArch/splitgep.ll @@ -0,0 +1,34 @@ +; RUN: opt --mtriple=loongarch64 -S --passes='require,function(codegenprepare)' %s | FileCheck %s + +; Check that we have deterministic output +define void @test(ptr %sp, ptr %t, i32 %n) { +; CHECK-LABEL: @test( +; CHECK-NEXT: entry: +; CHECK-NEXT: %s = load ptr, ptr %sp, align 8 +; CHECK-NEXT: br label %while_cond + +entry: + %s = load ptr, ptr %sp + br label %while_cond + +while_cond: + %phi = phi i32 [ 0, %entry ], [ %i, %while_body ] + %gep0 = getelementptr [65536 x i32], ptr %s, i64 0, i64 20000 + %gep1 = getelementptr [65536 x i32], ptr %s, i64 0, i64 20001 + %gep2 = getelementptr [65536 x i32], ptr %t, i64 0, i64 20000 + %gep3 = getelementptr [65536 x i32], ptr %t, i64 0, i64 20001 + %cmp = icmp slt i32 %phi, %n + br i1 %cmp, label %while_body, label %while_end + +while_body: + %i = add i32 %phi, 1 + store i32 %i, ptr %gep0 + store i32 %phi, ptr %gep1 + store i32 %i, ptr %gep2 + store i32 %phi, ptr %gep3 + br label %while_cond + +while_end: + ret void +} + -- GitLab From c39df496d73621238ba87de235d9a61e2b2203b9 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Fri, 12 Apr 2024 13:05:49 +0300 Subject: [PATCH 048/464] [clang][NFC] Refactor `CUDAFunctionTarget` Refactor `CUDAFunctionTarget` into a scoped enum at namespace scope, so that it can be forward declared. This is done in preparation for `SemaCUDA`. --- clang/include/clang/Sema/Sema.h | 29 ++++--- clang/lib/Sema/SemaCUDA.cpp | 146 ++++++++++++++++++-------------- clang/lib/Sema/SemaDecl.cpp | 8 +- clang/lib/Sema/SemaDeclAttr.cpp | 15 ++-- clang/lib/Sema/SemaExpr.cpp | 16 ++-- clang/lib/Sema/SemaExprCXX.cpp | 3 +- clang/lib/Sema/SemaOverload.cpp | 14 +-- clang/lib/Sema/SemaStmt.cpp | 3 +- clang/lib/Sema/SemaType.cpp | 32 +++---- 9 files changed, 145 insertions(+), 121 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 90c916628270..00888b7f7a73 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -435,6 +435,14 @@ enum class CXXSpecialMemberKind { Invalid }; +enum class CUDAFunctionTarget { + Device, + Global, + Host, + HostDevice, + InvalidTarget +}; + /// Sema - This implements semantic analysis and AST building for C. /// \nosubgrouping class Sema final : public SemaBase { @@ -3663,20 +3671,12 @@ public: InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL); - enum CUDAFunctionTarget { - CFT_Device, - CFT_Global, - CFT_Host, - CFT_HostDevice, - CFT_InvalidTarget - }; - /// Check validaty of calling convention attribute \p attr. If \p FD /// is not null pointer, use \p FD to determine the CUDA/HIP host/device /// target. Otherwise, it is specified by \p CFT. - bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC, - const FunctionDecl *FD = nullptr, - CUDAFunctionTarget CFT = CFT_InvalidTarget); + bool CheckCallingConvAttr( + const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr, + CUDAFunctionTarget CFT = CUDAFunctionTarget::InvalidTarget); void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, ParameterABI ABI); @@ -12967,7 +12967,8 @@ public: /// Example usage: /// /// // Variable-length arrays are not allowed in CUDA device code. - /// if (CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget()) + /// if (CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) + /// << llvm::to_underlying(CurrentCUDATarget())) /// return ExprError(); /// // Otherwise, continue parsing as normal. SemaDiagnosticBuilder CUDADiagIfDeviceCode(SourceLocation Loc, @@ -12983,7 +12984,7 @@ public: /// function. /// /// Use this rather than examining the function's attributes yourself -- you - /// will get it wrong. Returns CFT_Host if D is null. + /// will get it wrong. Returns CUDAFunctionTarget::Host if D is null. CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr = false); CUDAFunctionTarget IdentifyCUDATarget(const ParsedAttributesView &Attrs); @@ -13008,7 +13009,7 @@ public: /// Define the current global CUDA host/device context where a function may be /// called. Only used when a function is called outside of any functions. struct CUDATargetContext { - CUDAFunctionTarget Target = CFT_HostDevice; + CUDAFunctionTarget Target = CUDAFunctionTarget::HostDevice; CUDATargetContextKind Kind = CTCK_Unknown; Decl *D = nullptr; } CurCUDATargetCtx; diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index 1596222e3d1d..9d6d709e262a 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -22,6 +22,7 @@ #include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallVector.h" #include using namespace clang; @@ -64,8 +65,7 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, /*IsExecConfig=*/true); } -Sema::CUDAFunctionTarget -Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { +CUDAFunctionTarget Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { bool HasHostAttr = false; bool HasDeviceAttr = false; bool HasGlobalAttr = false; @@ -90,18 +90,18 @@ Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { } if (HasInvalidTargetAttr) - return CFT_InvalidTarget; + return CUDAFunctionTarget::InvalidTarget; if (HasGlobalAttr) - return CFT_Global; + return CUDAFunctionTarget::Global; if (HasHostAttr && HasDeviceAttr) - return CFT_HostDevice; + return CUDAFunctionTarget::HostDevice; if (HasDeviceAttr) - return CFT_Device; + return CUDAFunctionTarget::Device; - return CFT_Host; + return CUDAFunctionTarget::Host; } template @@ -120,43 +120,43 @@ Sema::CUDATargetContextRAII::CUDATargetContextRAII(Sema &S_, assert(K == CTCK_InitGlobalVar); auto *VD = dyn_cast_or_null(D); if (VD && VD->hasGlobalStorage() && !VD->isStaticLocal()) { - auto Target = CFT_Host; + auto Target = CUDAFunctionTarget::Host; if ((hasAttr(VD, /*IgnoreImplicit=*/true) && !hasAttr(VD, /*IgnoreImplicit=*/true)) || hasAttr(VD, /*IgnoreImplicit=*/true) || hasAttr(VD, /*IgnoreImplicit=*/true)) - Target = CFT_Device; + Target = CUDAFunctionTarget::Device; S.CurCUDATargetCtx = {Target, K, VD}; } } /// IdentifyCUDATarget - Determine the CUDA compilation target for this function -Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D, - bool IgnoreImplicitHDAttr) { +CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D, + bool IgnoreImplicitHDAttr) { // Code that lives outside a function gets the target from CurCUDATargetCtx. if (D == nullptr) return CurCUDATargetCtx.Target; if (D->hasAttr()) - return CFT_InvalidTarget; + return CUDAFunctionTarget::InvalidTarget; if (D->hasAttr()) - return CFT_Global; + return CUDAFunctionTarget::Global; if (hasAttr(D, IgnoreImplicitHDAttr)) { if (hasAttr(D, IgnoreImplicitHDAttr)) - return CFT_HostDevice; - return CFT_Device; + return CUDAFunctionTarget::HostDevice; + return CUDAFunctionTarget::Device; } else if (hasAttr(D, IgnoreImplicitHDAttr)) { - return CFT_Host; + return CUDAFunctionTarget::Host; } else if ((D->isImplicit() || !D->isUserProvided()) && !IgnoreImplicitHDAttr) { // Some implicit declarations (like intrinsic functions) are not marked. // Set the most lenient target on them for maximal flexibility. - return CFT_HostDevice; + return CUDAFunctionTarget::HostDevice; } - return CFT_Host; + return CUDAFunctionTarget::Host; } /// IdentifyTarget - Determine the CUDA compilation target for this variable. @@ -181,10 +181,10 @@ Sema::CUDAVariableTarget Sema::IdentifyCUDATarget(const VarDecl *Var) { // - on device side in device or global functions if (auto *FD = dyn_cast(Var->getDeclContext())) { switch (IdentifyCUDATarget(FD)) { - case CFT_HostDevice: + case CUDAFunctionTarget::HostDevice: return CVT_Both; - case CFT_Device: - case CFT_Global: + case CUDAFunctionTarget::Device: + case CUDAFunctionTarget::Global: return CVT_Device; default: return CVT_Host; @@ -230,7 +230,7 @@ Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, // trivial ctor/dtor without device attr to be used. Non-trivial ctor/dtor // will be diagnosed by checkAllowedCUDAInitializer. if (Caller == nullptr && CurCUDATargetCtx.Kind == CTCK_InitGlobalVar && - CurCUDATargetCtx.Target == CFT_Device && + CurCUDATargetCtx.Target == CUDAFunctionTarget::Device && (isa(Callee) || isa(Callee))) return CFP_HostDevice; @@ -239,40 +239,47 @@ Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, // If one of the targets is invalid, the check always fails, no matter what // the other target is. - if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget) + if (CallerTarget == CUDAFunctionTarget::InvalidTarget || + CalleeTarget == CUDAFunctionTarget::InvalidTarget) return CFP_Never; // (a) Can't call global from some contexts until we support CUDA's // dynamic parallelism. - if (CalleeTarget == CFT_Global && - (CallerTarget == CFT_Global || CallerTarget == CFT_Device)) + if (CalleeTarget == CUDAFunctionTarget::Global && + (CallerTarget == CUDAFunctionTarget::Global || + CallerTarget == CUDAFunctionTarget::Device)) return CFP_Never; // (b) Calling HostDevice is OK for everyone. - if (CalleeTarget == CFT_HostDevice) + if (CalleeTarget == CUDAFunctionTarget::HostDevice) return CFP_HostDevice; // (c) Best case scenarios if (CalleeTarget == CallerTarget || - (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) || - (CallerTarget == CFT_Global && CalleeTarget == CFT_Device)) + (CallerTarget == CUDAFunctionTarget::Host && + CalleeTarget == CUDAFunctionTarget::Global) || + (CallerTarget == CUDAFunctionTarget::Global && + CalleeTarget == CUDAFunctionTarget::Device)) return CFP_Native; // HipStdPar mode is special, in that assessing whether a device side call to // a host target is deferred to a subsequent pass, and cannot unambiguously be // adjudicated in the AST, hence we optimistically allow them to pass here. if (getLangOpts().HIPStdPar && - (CallerTarget == CFT_Global || CallerTarget == CFT_Device || - CallerTarget == CFT_HostDevice) && - CalleeTarget == CFT_Host) + (CallerTarget == CUDAFunctionTarget::Global || + CallerTarget == CUDAFunctionTarget::Device || + CallerTarget == CUDAFunctionTarget::HostDevice) && + CalleeTarget == CUDAFunctionTarget::Host) return CFP_HostDevice; // (d) HostDevice behavior depends on compilation mode. - if (CallerTarget == CFT_HostDevice) { + if (CallerTarget == CUDAFunctionTarget::HostDevice) { // It's OK to call a compilation-mode matching function from an HD one. - if ((getLangOpts().CUDAIsDevice && CalleeTarget == CFT_Device) || + if ((getLangOpts().CUDAIsDevice && + CalleeTarget == CUDAFunctionTarget::Device) || (!getLangOpts().CUDAIsDevice && - (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global))) + (CalleeTarget == CUDAFunctionTarget::Host || + CalleeTarget == CUDAFunctionTarget::Global))) return CFP_SameSide; // Calls from HD to non-mode-matching functions (i.e., to host functions @@ -283,9 +290,12 @@ Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, } // (e) Calling across device/host boundary is not something you should do. - if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) || - (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) || - (CallerTarget == CFT_Global && CalleeTarget == CFT_Host)) + if ((CallerTarget == CUDAFunctionTarget::Host && + CalleeTarget == CUDAFunctionTarget::Device) || + (CallerTarget == CUDAFunctionTarget::Device && + CalleeTarget == CUDAFunctionTarget::Host) || + (CallerTarget == CUDAFunctionTarget::Global && + CalleeTarget == CUDAFunctionTarget::Host)) return CFP_Never; llvm_unreachable("All cases should've been handled by now."); @@ -337,16 +347,16 @@ void Sema::EraseUnwantedCUDAMatches( /// \param ResolvedTarget with a target that resolves for both calls. /// \return true if there's a conflict, false otherwise. static bool -resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1, - Sema::CUDAFunctionTarget Target2, - Sema::CUDAFunctionTarget *ResolvedTarget) { +resolveCalleeCUDATargetConflict(CUDAFunctionTarget Target1, + CUDAFunctionTarget Target2, + CUDAFunctionTarget *ResolvedTarget) { // Only free functions and static member functions may be global. - assert(Target1 != Sema::CFT_Global); - assert(Target2 != Sema::CFT_Global); + assert(Target1 != CUDAFunctionTarget::Global); + assert(Target2 != CUDAFunctionTarget::Global); - if (Target1 == Sema::CFT_HostDevice) { + if (Target1 == CUDAFunctionTarget::HostDevice) { *ResolvedTarget = Target2; - } else if (Target2 == Sema::CFT_HostDevice) { + } else if (Target2 == CUDAFunctionTarget::HostDevice) { *ResolvedTarget = Target1; } else if (Target1 != Target2) { return true; @@ -422,7 +432,8 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, if (Diagnose) { Diag(ClassDecl->getLocation(), diag::note_implicit_member_target_infer_collision) - << (unsigned)CSM << *InferredTarget << BaseMethodTarget; + << (unsigned)CSM << llvm::to_underlying(*InferredTarget) + << llvm::to_underlying(BaseMethodTarget); } MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context)); return true; @@ -465,7 +476,8 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, if (Diagnose) { Diag(ClassDecl->getLocation(), diag::note_implicit_member_target_infer_collision) - << (unsigned)CSM << *InferredTarget << FieldMethodTarget; + << (unsigned)CSM << llvm::to_underlying(*InferredTarget) + << llvm::to_underlying(FieldMethodTarget); } MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context)); return true; @@ -478,9 +490,9 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, // it's the least restrictive option that can be invoked from any target. bool NeedsH = true, NeedsD = true; if (InferredTarget) { - if (*InferredTarget == CFT_Device) + if (*InferredTarget == CUDAFunctionTarget::Device) NeedsH = false; - else if (*InferredTarget == CFT_Host) + else if (*InferredTarget == CUDAFunctionTarget::Host) NeedsD = false; } @@ -677,9 +689,10 @@ void Sema::checkAllowedCUDAInitializer(VarDecl *VD) { } if (InitFn) { CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn); - if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) { + if (InitFnTarget != CUDAFunctionTarget::Host && + InitFnTarget != CUDAFunctionTarget::HostDevice) { Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer) - << InitFnTarget << InitFn; + << llvm::to_underlying(InitFnTarget) << InitFn; Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn; VD->setInvalidDecl(); } @@ -699,8 +712,9 @@ void Sema::CUDARecordImplicitHostDeviceFuncUsedByDevice( CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller); // Record whether an implicit host device function is used on device side. - if (CallerTarget != CFT_Device && CallerTarget != CFT_Global && - (CallerTarget != CFT_HostDevice || + if (CallerTarget != CUDAFunctionTarget::Device && + CallerTarget != CUDAFunctionTarget::Global && + (CallerTarget != CUDAFunctionTarget::HostDevice || (isCUDAImplicitHostDeviceFunction(Caller) && !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(Caller)))) return; @@ -806,10 +820,10 @@ Sema::SemaDiagnosticBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc, if (!CurFunContext) return SemaDiagnosticBuilder::K_Nop; switch (CurrentCUDATarget()) { - case CFT_Global: - case CFT_Device: + case CUDAFunctionTarget::Global: + case CUDAFunctionTarget::Device: return SemaDiagnosticBuilder::K_Immediate; - case CFT_HostDevice: + case CUDAFunctionTarget::HostDevice: // An HD function counts as host code if we're compiling for host, and // device code if we're compiling for device. Defer any errors in device // mode until the function is known-emitted. @@ -836,9 +850,9 @@ Sema::SemaDiagnosticBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc, if (!CurFunContext) return SemaDiagnosticBuilder::K_Nop; switch (CurrentCUDATarget()) { - case CFT_Host: + case CUDAFunctionTarget::Host: return SemaDiagnosticBuilder::K_Immediate; - case CFT_HostDevice: + case CUDAFunctionTarget::HostDevice: // An HD function counts as host code if we're compiling for host, and // device code if we're compiling for device. Defer any errors in device // mode until the function is known-emitted. @@ -911,8 +925,8 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { return true; SemaDiagnosticBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, *this) - << IdentifyCUDATarget(Callee) << /*function*/ 0 << Callee - << IdentifyCUDATarget(Caller); + << llvm::to_underlying(IdentifyCUDATarget(Callee)) << /*function*/ 0 + << Callee << llvm::to_underlying(IdentifyCUDATarget(Caller)); if (!Callee->getBuiltinID()) SemaDiagnosticBuilder(DiagKind, Callee->getLocation(), diag::note_previous_decl, Caller, *this) @@ -995,19 +1009,21 @@ void Sema::checkCUDATargetOverload(FunctionDecl *NewFD, // HD/global functions "exist" in some sense on both the host and device, so // should have the same implementation on both sides. if (NewTarget != OldTarget && - ((NewTarget == CFT_HostDevice && + ((NewTarget == CUDAFunctionTarget::HostDevice && !(LangOpts.OffloadImplicitHostDeviceTemplates && isCUDAImplicitHostDeviceFunction(NewFD) && - OldTarget == CFT_Device)) || - (OldTarget == CFT_HostDevice && + OldTarget == CUDAFunctionTarget::Device)) || + (OldTarget == CUDAFunctionTarget::HostDevice && !(LangOpts.OffloadImplicitHostDeviceTemplates && isCUDAImplicitHostDeviceFunction(OldFD) && - NewTarget == CFT_Device)) || - (NewTarget == CFT_Global) || (OldTarget == CFT_Global)) && + NewTarget == CUDAFunctionTarget::Device)) || + (NewTarget == CUDAFunctionTarget::Global) || + (OldTarget == CUDAFunctionTarget::Global)) && !IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false, /* ConsiderCudaAttrs = */ false)) { Diag(NewFD->getLocation(), diag::err_cuda_ovl_target) - << NewTarget << NewFD->getDeclName() << OldTarget << OldFD; + << llvm::to_underlying(NewTarget) << NewFD->getDeclName() + << llvm::to_underlying(OldTarget) << OldFD; Diag(OldFD->getLocation(), diag::note_previous_declaration); NewFD->setInvalidDecl(); break; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b448bacd49f3..720e56692359 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -20666,11 +20666,11 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(const FunctionDecl *FD, // when compiling for host, device and global functions are never emitted. // (Technically, we do emit a host-side stub for global functions, but this // doesn't count for our purposes here.) - Sema::CUDAFunctionTarget T = IdentifyCUDATarget(FD); - if (LangOpts.CUDAIsDevice && T == Sema::CFT_Host) + CUDAFunctionTarget T = IdentifyCUDATarget(FD); + if (LangOpts.CUDAIsDevice && T == CUDAFunctionTarget::Host) return FunctionEmissionStatus::CUDADiscarded; if (!LangOpts.CUDAIsDevice && - (T == Sema::CFT_Device || T == Sema::CFT_Global)) + (T == CUDAFunctionTarget::Device || T == CUDAFunctionTarget::Global)) return FunctionEmissionStatus::CUDADiscarded; if (IsEmittedForExternalSymbol()) @@ -20691,5 +20691,5 @@ bool Sema::shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee) { // for host, only HD functions actually called from the host get marked as // known-emitted. return LangOpts.CUDA && !LangOpts.CUDAIsDevice && - IdentifyCUDATarget(Callee) == CFT_Global; + IdentifyCUDATarget(Callee) == CUDAFunctionTarget::Global; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b91064e28e41..56c9d90c9b52 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -42,6 +42,7 @@ #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Assumptions.h" #include "llvm/MC/MCSectionMachO.h" @@ -5099,7 +5100,7 @@ static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } if (S.getLangOpts().CUDA && VD->hasLocalStorage() && S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared) - << S.CurrentCUDATarget()) + << llvm::to_underlying(S.CurrentCUDATarget())) return; D->addAttr(::new (S.Context) CUDASharedAttr(S.Context, AL)); } @@ -5493,22 +5494,22 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, // on their host/device attributes. if (LangOpts.CUDA) { auto *Aux = Context.getAuxTargetInfo(); - assert(FD || CFT != CFT_InvalidTarget); + assert(FD || CFT != CUDAFunctionTarget::InvalidTarget); auto CudaTarget = FD ? IdentifyCUDATarget(FD) : CFT; bool CheckHost = false, CheckDevice = false; switch (CudaTarget) { - case CFT_HostDevice: + case CUDAFunctionTarget::HostDevice: CheckHost = true; CheckDevice = true; break; - case CFT_Host: + case CUDAFunctionTarget::Host: CheckHost = true; break; - case CFT_Device: - case CFT_Global: + case CUDAFunctionTarget::Device: + case CUDAFunctionTarget::Global: CheckDevice = true; break; - case CFT_InvalidTarget: + case CUDAFunctionTarget::InvalidTarget: llvm_unreachable("unexpected cuda target"); } auto *HostTI = LangOpts.CUDAIsDevice ? Aux : &TI; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ec5ca2b9352e..18284e0c3e98 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -53,6 +53,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ConvertUTF.h" @@ -17307,7 +17308,8 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { if (const FunctionDecl *F = dyn_cast(CurContext)) { CUDAFunctionTarget T = IdentifyCUDATarget(F); - if (T == CFT_Global || T == CFT_Device || T == CFT_HostDevice) + if (T == CUDAFunctionTarget::Global || T == CUDAFunctionTarget::Device || + T == CUDAFunctionTarget::HostDevice) return ExprError(Diag(E->getBeginLoc(), diag::err_va_arg_in_device)); } } @@ -19182,14 +19184,16 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef, auto VarTarget = SemaRef.IdentifyCUDATarget(Var); auto UserTarget = SemaRef.IdentifyCUDATarget(FD); if (VarTarget == Sema::CVT_Host && - (UserTarget == Sema::CFT_Device || UserTarget == Sema::CFT_HostDevice || - UserTarget == Sema::CFT_Global)) { + (UserTarget == CUDAFunctionTarget::Device || + UserTarget == CUDAFunctionTarget::HostDevice || + UserTarget == CUDAFunctionTarget::Global)) { // Diagnose ODR-use of host global variables in device functions. // Reference of device global variables in host functions is allowed // through shadow variables therefore it is not diagnosed. if (SemaRef.LangOpts.CUDAIsDevice && !SemaRef.LangOpts.HIPStdPar) { SemaRef.targetDiag(Loc, diag::err_ref_bad_target) - << /*host*/ 2 << /*variable*/ 1 << Var << UserTarget; + << /*host*/ 2 << /*variable*/ 1 << Var + << llvm::to_underlying(UserTarget); SemaRef.targetDiag(Var->getLocation(), Var->getType().isConstQualified() ? diag::note_cuda_const_var_unpromoted @@ -19197,8 +19201,8 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef, } } else if (VarTarget == Sema::CVT_Device && !Var->hasAttr() && - (UserTarget == Sema::CFT_Host || - UserTarget == Sema::CFT_HostDevice)) { + (UserTarget == CUDAFunctionTarget::Host || + UserTarget == CUDAFunctionTarget::HostDevice)) { // Record a CUDA/HIP device side variable if it is ODR-used // by host code. This is done conservatively, when the variable is // referenced in any of the following contexts: diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index ac39cb99fc93..ce9d5c26e218 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -44,6 +44,7 @@ #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TypeSize.h" @@ -884,7 +885,7 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) CUDADiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions) - << "throw" << CurrentCUDATarget(); + << "throw" << llvm::to_underlying(CurrentCUDATarget()); if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw"; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 1f674dd4bb0f..e1155dc2d5d2 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1549,10 +1549,10 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, // Don't allow overloading of destructors. (In theory we could, but it // would be a giant change to clang.) if (!isa(New)) { - Sema::CUDAFunctionTarget NewTarget = SemaRef.IdentifyCUDATarget(New), - OldTarget = SemaRef.IdentifyCUDATarget(Old); - if (NewTarget != Sema::CFT_InvalidTarget) { - assert((OldTarget != Sema::CFT_InvalidTarget) && + CUDAFunctionTarget NewTarget = SemaRef.IdentifyCUDATarget(New), + OldTarget = SemaRef.IdentifyCUDATarget(Old); + if (NewTarget != CUDAFunctionTarget::InvalidTarget) { + assert((OldTarget != CUDAFunctionTarget::InvalidTarget) && "Unexpected invalid target."); // Allow overloading of functions with same signature and different CUDA @@ -11938,8 +11938,8 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true); FunctionDecl *Callee = Cand->Function; - Sema::CUDAFunctionTarget CallerTarget = S.IdentifyCUDATarget(Caller), - CalleeTarget = S.IdentifyCUDATarget(Callee); + CUDAFunctionTarget CallerTarget = S.IdentifyCUDATarget(Caller), + CalleeTarget = S.IdentifyCUDATarget(Callee); std::string FnDesc; std::pair FnKindPair = @@ -11949,7 +11949,7 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target) << (unsigned)FnKindPair.first << (unsigned)ocs_non_template << FnDesc /* Ignored */ - << CalleeTarget << CallerTarget; + << llvm::to_underlying(CalleeTarget) << llvm::to_underlying(CallerTarget); // This could be an implicit constructor for which we could not infer the // target due to a collsion. Diagnose that case. diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index e53c76e65b03..1c2f6120f621 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -37,6 +37,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -4574,7 +4575,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) CUDADiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions) - << "try" << CurrentCUDATarget(); + << "try" << llvm::to_underlying(CurrentCUDATarget()); if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try"; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index b8a1518fbe00..b3f6078952f6 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -37,6 +37,7 @@ #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -376,11 +377,10 @@ enum TypeAttrLocation { static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, const ParsedAttributesView &attrs, - Sema::CUDAFunctionTarget CFT = Sema::CFT_HostDevice); + CUDAFunctionTarget CFT = CUDAFunctionTarget::HostDevice); static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, - QualType &type, - Sema::CUDAFunctionTarget CFT); + QualType &type, CUDAFunctionTarget CFT); static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state, ParsedAttr &attr, QualType &type); @@ -627,7 +627,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, static bool distributeFunctionTypeAttrToInnermost( TypeProcessingState &state, ParsedAttr &attr, ParsedAttributesView &attrList, QualType &declSpecType, - Sema::CUDAFunctionTarget CFT) { + CUDAFunctionTarget CFT) { Declarator &declarator = state.getDeclarator(); // Put it on the innermost function chunk, if there is one. @@ -644,10 +644,10 @@ static bool distributeFunctionTypeAttrToInnermost( /// A function type attribute was written in the decl spec. Try to /// apply it somewhere. -static void -distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, - ParsedAttr &attr, QualType &declSpecType, - Sema::CUDAFunctionTarget CFT) { +static void distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, + ParsedAttr &attr, + QualType &declSpecType, + CUDAFunctionTarget CFT) { state.saveDeclSpecAttrs(); // Try to distribute to the innermost. @@ -664,9 +664,10 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, /// Try to apply it somewhere. /// `Attrs` is the attribute list containing the declaration (either of the /// declarator or the declaration). -static void distributeFunctionTypeAttrFromDeclarator( - TypeProcessingState &state, ParsedAttr &attr, QualType &declSpecType, - Sema::CUDAFunctionTarget CFT) { +static void distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state, + ParsedAttr &attr, + QualType &declSpecType, + CUDAFunctionTarget CFT) { Declarator &declarator = state.getDeclarator(); // Try to distribute to the innermost. @@ -694,7 +695,7 @@ static void distributeFunctionTypeAttrFromDeclarator( /// declarator or the declaration). static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, QualType &declSpecType, - Sema::CUDAFunctionTarget CFT) { + CUDAFunctionTarget CFT) { // The called functions in this loop actually remove things from the current // list, so iterating over the existing list isn't possible. Instead, make a // non-owning copy and iterate over that. @@ -2734,7 +2735,7 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM, bool IsCUDADevice = (getLangOpts().CUDA && getLangOpts().CUDAIsDevice); targetDiag(Loc, IsCUDADevice ? diag::err_cuda_vla : diag::err_vla_unsupported) - << (IsCUDADevice ? CurrentCUDATarget() : 0); + << (IsCUDADevice ? llvm::to_underlying(CurrentCUDATarget()) : 0); } else if (sema::FunctionScopeInfo *FSI = getCurFunction()) { // VLAs are supported on this target, but we may need to do delayed // checking that the VLA is not being used within a coroutine. @@ -8028,8 +8029,7 @@ static bool handleArmStateAttribute(Sema &S, /// Process an individual function attribute. Returns true to /// indicate that the attribute was handled, false if it wasn't. static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, - QualType &type, - Sema::CUDAFunctionTarget CFT) { + QualType &type, CUDAFunctionTarget CFT) { Sema &S = state.getSema(); FunctionTypeUnwrapper unwrapped(S, type); @@ -8863,7 +8863,7 @@ static void HandleHLSLParamModifierAttr(QualType &CurType, static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, const ParsedAttributesView &attrs, - Sema::CUDAFunctionTarget CFT) { + CUDAFunctionTarget CFT) { state.setParsedNoDeref(false); if (attrs.empty()) -- GitLab From 3bb147e05365680d0a954d823a7c014f357448e7 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Fri, 12 Apr 2024 10:54:35 +0100 Subject: [PATCH 049/464] [X86] combine-sse41-intrinsics.ll - add AVX2 test coverage --- .../CodeGen/X86/combine-sse41-intrinsics.ll | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/llvm/test/CodeGen/X86/combine-sse41-intrinsics.ll b/llvm/test/CodeGen/X86/combine-sse41-intrinsics.ll index cbb5bd09c239..6034a24099e4 100644 --- a/llvm/test/CodeGen/X86/combine-sse41-intrinsics.ll +++ b/llvm/test/CodeGen/X86/combine-sse41-intrinsics.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefixes=CHECK,AVX +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefixes=CHECK,AVX,AVX1 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2 define <2 x double> @test_x86_sse41_blend_pd(<2 x double> %a0, <2 x double> %a1) { @@ -146,12 +147,18 @@ define <16 x i8> @demandedelts_pblendvb(<16 x i8> %a0, <16 x i8> %a1, <16 x i8> ; SSE-NEXT: movdqa %xmm3, %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: demandedelts_pblendvb: -; AVX: # %bb.0: -; AVX-NEXT: vpblendvb %xmm2, %xmm1, %xmm0, %xmm0 -; AVX-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX-NEXT: vpshufb %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX1-LABEL: demandedelts_pblendvb: +; AVX1: # %bb.0: +; AVX1-NEXT: vpblendvb %xmm2, %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX1-NEXT: vpshufb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: demandedelts_pblendvb: +; AVX2: # %bb.0: +; AVX2-NEXT: vpblendvb %xmm2, %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastb %xmm0, %xmm0 +; AVX2-NEXT: retq %1 = shufflevector <16 x i8> %a0, <16 x i8> undef, <16 x i32> zeroinitializer %2 = shufflevector <16 x i8> %a1, <16 x i8> undef, <16 x i32> zeroinitializer %3 = shufflevector <16 x i8> %a2, <16 x i8> undef, <16 x i32> zeroinitializer @@ -193,15 +200,28 @@ define <4 x float> @demandedbits_uitofp_blendvps(<4 x float> %a0, <4 x float> %a ; SSE-NEXT: movaps %xmm3, %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: demandedbits_uitofp_blendvps: -; AVX: # %bb.0: -; AVX-NEXT: vpblendw {{.*#+}} xmm3 = xmm2[0],mem[1],xmm2[2],mem[3],xmm2[4],mem[5],xmm2[6],mem[7] -; AVX-NEXT: vpsrld $16, %xmm2, %xmm2 -; AVX-NEXT: vpblendw {{.*#+}} xmm2 = xmm2[0],mem[1],xmm2[2],mem[3],xmm2[4],mem[5],xmm2[6],mem[7] -; AVX-NEXT: vsubps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 -; AVX-NEXT: vaddps %xmm2, %xmm3, %xmm2 -; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX1-LABEL: demandedbits_uitofp_blendvps: +; AVX1: # %bb.0: +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm2[0],mem[1],xmm2[2],mem[3],xmm2[4],mem[5],xmm2[6],mem[7] +; AVX1-NEXT: vpsrld $16, %xmm2, %xmm2 +; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm2[0],mem[1],xmm2[2],mem[3],xmm2[4],mem[5],xmm2[6],mem[7] +; AVX1-NEXT: vsubps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; AVX1-NEXT: vaddps %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: demandedbits_uitofp_blendvps: +; AVX2: # %bb.0: +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm3 = [1258291200,1258291200,1258291200,1258291200] +; AVX2-NEXT: vpblendw {{.*#+}} xmm3 = xmm2[0],xmm3[1],xmm2[2],xmm3[3],xmm2[4],xmm3[5],xmm2[6],xmm3[7] +; AVX2-NEXT: vpsrld $16, %xmm2, %xmm2 +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm4 = [1392508928,1392508928,1392508928,1392508928] +; AVX2-NEXT: vpblendw {{.*#+}} xmm2 = xmm2[0],xmm4[1],xmm2[2],xmm4[3],xmm2[4],xmm4[5],xmm2[6],xmm4[7] +; AVX2-NEXT: vbroadcastss {{.*#+}} xmm4 = [5.49764202E+11,5.49764202E+11,5.49764202E+11,5.49764202E+11] +; AVX2-NEXT: vsubps %xmm4, %xmm2, %xmm2 +; AVX2-NEXT: vaddps %xmm2, %xmm3, %xmm2 +; AVX2-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq %cvt = uitofp <4 x i32> %a2 to <4 x float> %sel = tail call noundef <4 x float> @llvm.x86.sse41.blendvps(<4 x float> %a0, <4 x float> %a1, <4 x float> %cvt) ret <4 x float> %sel -- GitLab From 8c0f52e9d5a99bf96bb64ac23b5893482c292527 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Fri, 12 Apr 2024 11:23:51 +0100 Subject: [PATCH 050/464] [DAG] Fold extract_subvector(insert_subvector(x,y,c1),c2) --> extract_subvector(y,c2-c1) (#87925) If the extract_subvector is cheap, attempt to extract directly from an inserted subvector --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 17 + .../any_extend_vector_inreg_of_broadcast.ll | 42 +- llvm/test/CodeGen/X86/dpbusd.ll | 2 +- llvm/test/CodeGen/X86/dpbusd_i4.ll | 2 +- .../vector-interleaved-load-i16-stride-3.ll | 1300 ++++++++--------- .../vector-interleaved-store-i8-stride-7.ll | 602 ++++---- .../zero_extend_vector_inreg_of_broadcast.ll | 28 +- 7 files changed, 987 insertions(+), 1006 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 24f50b87c4cf..d9c6c28d5dac 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -24463,6 +24463,23 @@ SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode *N) { if (!LegalOperations || TLI.isOperationLegal(ISD::SPLAT_VECTOR, NVT)) return DAG.getSplatVector(NVT, DL, V.getOperand(0)); + // extract_subvector(insert_subvector(x,y,c1),c2) + // --> extract_subvector(y,c2-c1) + // iff we're just extracting from the inserted subvector. + if (V.getOpcode() == ISD::INSERT_SUBVECTOR) { + SDValue InsSub = V.getOperand(1); + EVT InsSubVT = InsSub.getValueType(); + unsigned NumInsElts = InsSubVT.getVectorMinNumElements(); + unsigned InsIdx = V.getConstantOperandVal(2); + unsigned NumSubElts = NVT.getVectorMinNumElements(); + if (InsIdx <= ExtIdx && (ExtIdx + NumSubElts) <= (InsIdx + NumInsElts) && + TLI.isExtractSubvectorCheap(NVT, InsSubVT, ExtIdx - InsIdx)) { + SDLoc DL(N); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, NVT, InsSub, + DAG.getVectorIdxConstant(ExtIdx - InsIdx, DL)); + } + } + // Try to move vector bitcast after extract_subv by scaling extraction index: // extract_subv (bitcast X), Index --> bitcast (extract_subv X, Index') if (V.getOpcode() == ISD::BITCAST && diff --git a/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast.ll b/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast.ll index 4242d8483e72..39c7ce1413d1 100644 --- a/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast.ll +++ b/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast.ll @@ -314,8 +314,8 @@ define void @vec64_i16_widen_to_i32_factor2_broadcast_to_v2i32_factor2(ptr %in.v ; ; AVX512F-LABEL: vec64_i16_widen_to_i32_factor2_broadcast_to_v2i32_factor2: ; AVX512F: # %bb.0: -; AVX512F-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512F-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512F-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512F-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512F-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,1,10,11,0,1,14,15,u,u,u,u,u,u,u,u] ; AVX512F-NEXT: vpaddb (%rdx), %ymm0, %ymm0 ; AVX512F-NEXT: vmovdqa %ymm0, (%rcx) @@ -324,8 +324,8 @@ define void @vec64_i16_widen_to_i32_factor2_broadcast_to_v2i32_factor2(ptr %in.v ; ; AVX512DQ-LABEL: vec64_i16_widen_to_i32_factor2_broadcast_to_v2i32_factor2: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512DQ-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,1,10,11,0,1,14,15,u,u,u,u,u,u,u,u] ; AVX512DQ-NEXT: vpaddb (%rdx), %ymm0, %ymm0 ; AVX512DQ-NEXT: vmovdqa %ymm0, (%rcx) @@ -981,7 +981,7 @@ define void @vec128_i32_widen_to_i64_factor2_broadcast_to_v2i64_factor2(ptr %in. ; AVX512F-NEXT: vpmovsxbd {{.*#+}} xmm0 = [0,5,0,7] ; AVX512F-NEXT: vmovdqa (%rdi), %ymm1 ; AVX512F-NEXT: vpaddb (%rsi), %ymm1, %ymm1 -; AVX512F-NEXT: vpermd %zmm1, %zmm0, %zmm0 +; AVX512F-NEXT: vpermd %ymm1, %ymm0, %ymm0 ; AVX512F-NEXT: vpaddb (%rdx), %ymm0, %ymm0 ; AVX512F-NEXT: vmovdqa %ymm0, (%rcx) ; AVX512F-NEXT: vzeroupper @@ -992,7 +992,7 @@ define void @vec128_i32_widen_to_i64_factor2_broadcast_to_v2i64_factor2(ptr %in. ; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} xmm0 = [0,5,0,7] ; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm1 ; AVX512DQ-NEXT: vpaddb (%rsi), %ymm1, %ymm1 -; AVX512DQ-NEXT: vpermd %zmm1, %zmm0, %zmm0 +; AVX512DQ-NEXT: vpermd %ymm1, %ymm0, %ymm0 ; AVX512DQ-NEXT: vpaddb (%rdx), %ymm0, %ymm0 ; AVX512DQ-NEXT: vmovdqa %ymm0, (%rcx) ; AVX512DQ-NEXT: vzeroupper @@ -3507,13 +3507,12 @@ define void @vec384_i16_widen_to_i32_factor2_broadcast_to_v12i32_factor12(ptr %i ; ; AVX512F-LABEL: vec384_i16_widen_to_i32_factor2_broadcast_to_v12i32_factor12: ; AVX512F: # %bb.0: -; AVX512F-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512F-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512F-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512F-NEXT: vmovdqa 48(%rdi), %xmm1 ; AVX512F-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 -; AVX512F-NEXT: vpbroadcastw %xmm0, %ymm2 -; AVX512F-NEXT: vpblendw {{.*#+}} ymm1 = ymm2[0],ymm1[1],ymm2[2],ymm1[3],ymm2[4],ymm1[5],ymm2[6],ymm1[7],ymm2[8],ymm1[9],ymm2[10],ymm1[11],ymm2[12],ymm1[13],ymm2[14],ymm1[15] +; AVX512F-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512F-NEXT: vpbroadcastw %xmm0, %ymm0 +; AVX512F-NEXT: vpblendw {{.*#+}} ymm1 = ymm0[0],ymm1[1],ymm0[2],ymm1[3],ymm0[4],ymm1[5],ymm0[6],ymm1[7],ymm0[8],ymm1[9],ymm0[10],ymm1[11],ymm0[12],ymm1[13],ymm0[14],ymm1[15] ; AVX512F-NEXT: vpaddb (%rdx), %ymm1, %ymm1 ; AVX512F-NEXT: vpaddb 32(%rdx), %ymm0, %ymm0 ; AVX512F-NEXT: vmovdqa %ymm0, 32(%rcx) @@ -3523,13 +3522,12 @@ define void @vec384_i16_widen_to_i32_factor2_broadcast_to_v12i32_factor12(ptr %i ; ; AVX512DQ-LABEL: vec384_i16_widen_to_i32_factor2_broadcast_to_v12i32_factor12: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512DQ-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512DQ-NEXT: vmovdqa 48(%rdi), %xmm1 ; AVX512DQ-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 -; AVX512DQ-NEXT: vpbroadcastw %xmm0, %ymm2 -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm2[0],ymm1[1],ymm2[2],ymm1[3],ymm2[4],ymm1[5],ymm2[6],ymm1[7],ymm2[8],ymm1[9],ymm2[10],ymm1[11],ymm2[12],ymm1[13],ymm2[14],ymm1[15] +; AVX512DQ-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512DQ-NEXT: vpbroadcastw %xmm0, %ymm0 +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm0[0],ymm1[1],ymm0[2],ymm1[3],ymm0[4],ymm1[5],ymm0[6],ymm1[7],ymm0[8],ymm1[9],ymm0[10],ymm1[11],ymm0[12],ymm1[13],ymm0[14],ymm1[15] ; AVX512DQ-NEXT: vpaddb (%rdx), %ymm1, %ymm1 ; AVX512DQ-NEXT: vpaddb 32(%rdx), %ymm0, %ymm0 ; AVX512DQ-NEXT: vmovdqa %ymm0, 32(%rcx) @@ -3768,10 +3766,10 @@ define void @vec384_i16_widen_to_i64_factor4_broadcast_to_v6i64_factor6(ptr %in. ; ; AVX512F-LABEL: vec384_i16_widen_to_i64_factor4_broadcast_to_v6i64_factor6: ; AVX512F: # %bb.0: -; AVX512F-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512F-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512F-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512F-NEXT: vmovdqa 48(%rdi), %xmm1 ; AVX512F-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 +; AVX512F-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512F-NEXT: vpbroadcastq %xmm0, %ymm2 ; AVX512F-NEXT: vpblendw {{.*#+}} ymm1 = ymm2[0],ymm1[1,2,3],ymm2[4],ymm1[5,6,7],ymm2[8],ymm1[9,10,11],ymm2[12],ymm1[13,14,15] ; AVX512F-NEXT: vpbroadcastw %xmm0, %ymm0 @@ -3784,10 +3782,10 @@ define void @vec384_i16_widen_to_i64_factor4_broadcast_to_v6i64_factor6(ptr %in. ; ; AVX512DQ-LABEL: vec384_i16_widen_to_i64_factor4_broadcast_to_v6i64_factor6: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512DQ-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512DQ-NEXT: vmovdqa 48(%rdi), %xmm1 ; AVX512DQ-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 +; AVX512DQ-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512DQ-NEXT: vpbroadcastq %xmm0, %ymm2 ; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm2[0],ymm1[1,2,3],ymm2[4],ymm1[5,6,7],ymm2[8],ymm1[9,10,11],ymm2[12],ymm1[13,14,15] ; AVX512DQ-NEXT: vpbroadcastw %xmm0, %ymm0 @@ -4147,9 +4145,9 @@ define void @vec384_i16_widen_to_i192_factor12_broadcast_to_v2i192_factor2(ptr % ; ; AVX512F-LABEL: vec384_i16_widen_to_i192_factor12_broadcast_to_v2i192_factor2: ; AVX512F: # %bb.0: -; AVX512F-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512F-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512F-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512F-NEXT: vmovdqa 48(%rdi), %xmm1 +; AVX512F-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512F-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 ; AVX512F-NEXT: vpblendw {{.*#+}} xmm1 = xmm0[0],xmm1[1,2,3,4,5,6,7] ; AVX512F-NEXT: vpbroadcastw %xmm0, %xmm0 @@ -4161,9 +4159,9 @@ define void @vec384_i16_widen_to_i192_factor12_broadcast_to_v2i192_factor2(ptr % ; ; AVX512DQ-LABEL: vec384_i16_widen_to_i192_factor12_broadcast_to_v2i192_factor2: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512DQ-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512DQ-NEXT: vmovdqa 48(%rdi), %xmm1 +; AVX512DQ-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512DQ-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 ; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm1 = xmm0[0],xmm1[1,2,3,4,5,6,7] ; AVX512DQ-NEXT: vpbroadcastw %xmm0, %xmm0 diff --git a/llvm/test/CodeGen/X86/dpbusd.ll b/llvm/test/CodeGen/X86/dpbusd.ll index fbea08eb1e55..04d7a9691b64 100644 --- a/llvm/test/CodeGen/X86/dpbusd.ll +++ b/llvm/test/CodeGen/X86/dpbusd.ll @@ -26,7 +26,7 @@ define i32 @no_dpbusd(ptr%a, ptr%b, i32 %c, i32 %n) { ; AVX512-NEXT: vpmovzxbw {{.*#+}} ymm1 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero,mem[8],zero,mem[9],zero,mem[10],zero,mem[11],zero,mem[12],zero,mem[13],zero,mem[14],zero,mem[15],zero ; AVX512-NEXT: vpmaddwd %ymm0, %ymm1, %ymm0 ; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm1 -; AVX512-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpaddd %xmm1, %xmm0, %xmm0 ; AVX512-NEXT: vpshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] ; AVX512-NEXT: vpaddd %xmm1, %xmm0, %xmm0 ; AVX512-NEXT: vpshufd {{.*#+}} xmm1 = xmm0[1,1,1,1] diff --git a/llvm/test/CodeGen/X86/dpbusd_i4.ll b/llvm/test/CodeGen/X86/dpbusd_i4.ll index 906fead7f8db..a212f99680ef 100644 --- a/llvm/test/CodeGen/X86/dpbusd_i4.ll +++ b/llvm/test/CodeGen/X86/dpbusd_i4.ll @@ -86,7 +86,7 @@ define i32 @mul_sext_i4i4(<16 x i4> %a, <16 x i4> %b, i32 %c) { ; CHECK-NEXT: vpsraw $12, %ymm0, %ymm0 ; CHECK-NEXT: vpmaddwd %ymm1, %ymm0, %ymm0 ; CHECK-NEXT: vextracti128 $1, %ymm0, %xmm1 -; CHECK-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; CHECK-NEXT: vpaddd %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: vpshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] ; CHECK-NEXT: vpaddd %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: vpshufd {{.*#+}} xmm1 = xmm0[1,1,1,1] diff --git a/llvm/test/CodeGen/X86/vector-interleaved-load-i16-stride-3.ll b/llvm/test/CodeGen/X86/vector-interleaved-load-i16-stride-3.ll index 1436922f9dd1..6d5fc9ed0ab5 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-load-i16-stride-3.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-load-i16-stride-3.ll @@ -1828,22 +1828,22 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; ; AVX512-LABEL: load_i16_stride3_vf32: ; AVX512: # %bb.0: -; AVX512-NEXT: vmovdqa {{.*#+}} ymm1 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] +; AVX512-NEXT: vmovdqa {{.*#+}} ymm0 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] ; AVX512-NEXT: vmovdqa 128(%rdi), %ymm5 ; AVX512-NEXT: vmovdqa 160(%rdi), %ymm6 -; AVX512-NEXT: vmovdqa %ymm1, %ymm0 -; AVX512-NEXT: vpternlogq $202, %ymm5, %ymm6, %ymm0 -; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm0[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm0 = ymm0[0],ymm2[1],ymm0[2,3],ymm2[4],ymm0[5,6],ymm2[7],ymm0[8],ymm2[9],ymm0[10,11],ymm2[12],ymm0[13,14],ymm2[15] -; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] -; AVX512-NEXT: vmovdqa 112(%rdi), %xmm0 +; AVX512-NEXT: vmovdqa %ymm0, %ymm1 +; AVX512-NEXT: vpternlogq $202, %ymm5, %ymm6, %ymm1 +; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm2[1],ymm1[2,3],ymm2[4],ymm1[5,6],ymm2[7],ymm1[8],ymm2[9],ymm1[10,11],ymm2[12],ymm1[13,14],ymm2[15] +; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] +; AVX512-NEXT: vmovdqa 112(%rdi), %xmm1 ; AVX512-NEXT: vmovdqa 96(%rdi), %xmm2 -; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm2[0],xmm0[1],xmm2[2,3],xmm0[4],xmm2[5,6],xmm0[7] +; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] ; AVX512-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[0,1,6,7,12,13,2,3,8,9,14,15,u,u,u,u] ; AVX512-NEXT: vpblendd {{.*#+}} ymm7 = ymm4[0,1,2],ymm3[3,4,5,6,7] ; AVX512-NEXT: vmovdqa (%rdi), %ymm8 ; AVX512-NEXT: vmovdqa 32(%rdi), %ymm9 -; AVX512-NEXT: vmovdqa %ymm1, %ymm3 +; AVX512-NEXT: vmovdqa %ymm0, %ymm3 ; AVX512-NEXT: vpternlogq $202, %ymm9, %ymm8, %ymm3 ; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm3[2,3,0,1] ; AVX512-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm4[1],ymm3[2,3],ymm4[4],ymm3[5,6],ymm4[7],ymm3[8],ymm4[9],ymm3[10,11],ymm4[12],ymm3[13,14],ymm4[15] @@ -1857,14 +1857,14 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; AVX512-NEXT: vpshufhw {{.*#+}} xmm10 = xmm10[0,1,2,3,6,5,4,7] ; AVX512-NEXT: vpblendd {{.*#+}} ymm10 = ymm10[0,1,2,3],ymm11[4,5,6,7] ; AVX512-NEXT: vinserti64x4 $1, %ymm7, %zmm10, %zmm7 -; AVX512-NEXT: vmovdqa %ymm1, %ymm10 +; AVX512-NEXT: vmovdqa %ymm0, %ymm10 ; AVX512-NEXT: vpternlogq $202, %ymm6, %ymm5, %ymm10 ; AVX512-NEXT: vpermq {{.*#+}} ymm11 = ymm10[2,3,0,1] ; AVX512-NEXT: vpblendw {{.*#+}} ymm10 = ymm10[0,1],ymm11[2],ymm10[3,4],ymm11[5],ymm10[6,7,8,9],ymm11[10],ymm10[11,12],ymm11[13],ymm10[14,15] ; AVX512-NEXT: vmovdqa {{.*#+}} ymm11 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] ; AVX512-NEXT: vpshufb %ymm11, %ymm10, %ymm10 -; AVX512-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0,1],xmm0[2],xmm2[3,4],xmm0[5],xmm2[6,7] -; AVX512-NEXT: vpshufb %xmm11, %xmm12, %xmm12 +; AVX512-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0,1],xmm1[2],xmm2[3,4],xmm1[5],xmm2[6,7] +; AVX512-NEXT: vpshufb {{.*#+}} xmm12 = xmm12[2,3,8,9,14,15,4,5,10,11,10,11,10,11,10,11] ; AVX512-NEXT: vpblendw {{.*#+}} xmm12 = xmm12[0,1,2,3,4],xmm10[5,6,7] ; AVX512-NEXT: vpblendd {{.*#+}} ymm10 = ymm12[0,1,2,3],ymm10[4,5,6,7] ; AVX512-NEXT: vmovdqa {{.*#+}} ymm12 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] @@ -1885,21 +1885,19 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; AVX512-NEXT: vpblendw {{.*#+}} ymm5 = ymm5[0],ymm12[1,2],ymm5[3],ymm12[4,5],ymm5[6],ymm12[7],ymm5[8],ymm12[9,10],ymm5[11],ymm12[12,13],ymm5[14],ymm12[15] ; AVX512-NEXT: vmovdqa {{.*#+}} ymm6 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] ; AVX512-NEXT: vpshufb %ymm6, %ymm5, %ymm5 -; AVX512-NEXT: vpternlogq $202, %ymm8, %ymm9, %ymm1 -; AVX512-NEXT: vpermq {{.*#+}} ymm8 = ymm1[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm1 = ymm8[0],ymm1[1,2],ymm8[3],ymm1[4,5],ymm8[6],ymm1[7],ymm8[8],ymm1[9,10],ymm8[11],ymm1[12,13],ymm8[14],ymm1[15] -; AVX512-NEXT: vpshufb %ymm6, %ymm1, %ymm1 -; AVX512-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0],xmm3[1],xmm4[2,3],xmm3[4],xmm4[5,6],xmm3[7] -; AVX512-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 -; AVX512-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3,4],ymm3[5,6,7] -; AVX512-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2],xmm0[3,4],xmm2[5],xmm0[6,7] -; AVX512-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] -; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 -; AVX512-NEXT: vextracti32x4 $2, %zmm0, %xmm0 -; AVX512-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4],xmm5[5,6,7] -; AVX512-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3],ymm5[4,5,6,7] -; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1],xmm2[2],xmm1[3,4],xmm2[5],xmm1[6,7] +; AVX512-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] +; AVX512-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1,2,3,4],xmm5[5,6,7] +; AVX512-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3],ymm5[4,5,6,7] +; AVX512-NEXT: vpternlogq $202, %ymm8, %ymm9, %ymm0 +; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm0[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm0 = ymm2[0],ymm0[1,2],ymm2[3],ymm0[4,5],ymm2[6],ymm0[7],ymm2[8],ymm0[9,10],ymm2[11],ymm0[12,13],ymm2[14],ymm0[15] +; AVX512-NEXT: vpshufb %ymm6, %ymm0, %ymm0 +; AVX512-NEXT: vpblendw {{.*#+}} xmm2 = xmm4[0],xmm3[1],xmm4[2,3],xmm3[4],xmm4[5,6],xmm3[7] +; AVX512-NEXT: vpshufb %xmm6, %xmm2, %xmm2 +; AVX512-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 +; AVX512-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3,4],ymm2[5,6,7] +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 ; AVX512-NEXT: vmovdqa64 %zmm7, (%rsi) ; AVX512-NEXT: vmovdqa64 %zmm10, (%rdx) ; AVX512-NEXT: vmovdqa64 %zmm0, (%rcx) @@ -1908,22 +1906,22 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; ; AVX512-FCP-LABEL: load_i16_stride3_vf32: ; AVX512-FCP: # %bb.0: -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] ; AVX512-FCP-NEXT: vmovdqa 128(%rdi), %ymm5 ; AVX512-FCP-NEXT: vmovdqa 160(%rdi), %ymm6 -; AVX512-FCP-NEXT: vmovdqa %ymm1, %ymm0 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm5, %ymm6, %ymm0 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm0[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm0 = ymm0[0],ymm2[1],ymm0[2,3],ymm2[4],ymm0[5,6],ymm2[7],ymm0[8],ymm2[9],ymm0[10,11],ymm2[12],ymm0[13,14],ymm2[15] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] -; AVX512-FCP-NEXT: vmovdqa 112(%rdi), %xmm0 +; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm1 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm5, %ymm6, %ymm1 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm2[1],ymm1[2,3],ymm2[4],ymm1[5,6],ymm2[7],ymm1[8],ymm2[9],ymm1[10,11],ymm2[12],ymm1[13,14],ymm2[15] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] +; AVX512-FCP-NEXT: vmovdqa 112(%rdi), %xmm1 ; AVX512-FCP-NEXT: vmovdqa 96(%rdi), %xmm2 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm2[0],xmm0[1],xmm2[2,3],xmm0[4],xmm2[5,6],xmm0[7] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] ; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[0,1,6,7,12,13,2,3,8,9,14,15,u,u,u,u] ; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm7 = ymm4[0,1,2],ymm3[3,4,5,6,7] ; AVX512-FCP-NEXT: vmovdqa (%rdi), %ymm8 ; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %ymm9 -; AVX512-FCP-NEXT: vmovdqa %ymm1, %ymm3 +; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm3 ; AVX512-FCP-NEXT: vpternlogq $202, %ymm9, %ymm8, %ymm3 ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm3[2,3,0,1] ; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm4[1],ymm3[2,3],ymm4[4],ymm3[5,6],ymm4[7],ymm3[8],ymm4[9],ymm3[10,11],ymm4[12],ymm3[13,14],ymm4[15] @@ -1937,14 +1935,14 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm10 = xmm10[0,1,2,3,6,5,4,7] ; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm10 = ymm10[0,1,2,3],ymm11[4,5,6,7] ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm10, %zmm7 -; AVX512-FCP-NEXT: vmovdqa %ymm1, %ymm10 +; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm10 ; AVX512-FCP-NEXT: vpternlogq $202, %ymm6, %ymm5, %ymm10 ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm10[2,3,0,1] ; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm10 = ymm10[0,1],ymm11[2],ymm10[3,4],ymm11[5],ymm10[6,7,8,9],ymm11[10],ymm10[11,12],ymm11[13],ymm10[14,15] ; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] ; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm10, %ymm10 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0,1],xmm0[2],xmm2[3,4],xmm0[5],xmm2[6,7] -; AVX512-FCP-NEXT: vpshufb %xmm11, %xmm12, %xmm12 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0,1],xmm1[2],xmm2[3,4],xmm1[5],xmm2[6,7] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm12 = xmm12[2,3,8,9,14,15,4,5,10,11,10,11,10,11,10,11] ; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm12[0,1,2,3,4],xmm10[5,6,7] ; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm10 = ymm12[0,1,2,3],ymm10[4,5,6,7] ; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] @@ -1965,21 +1963,19 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm5 = ymm5[0],ymm12[1,2],ymm5[3],ymm12[4,5],ymm5[6],ymm12[7],ymm5[8],ymm12[9,10],ymm5[11],ymm12[12,13],ymm5[14],ymm12[15] ; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm6 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] ; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm5, %ymm5 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm8, %ymm9, %ymm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm1[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm8[0],ymm1[1,2],ymm8[3],ymm1[4,5],ymm8[6],ymm1[7],ymm8[8],ymm1[9,10],ymm8[11],ymm1[12,13],ymm8[14],ymm1[15] -; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm1, %ymm1 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0],xmm3[1],xmm4[2,3],xmm3[4],xmm4[5,6],xmm3[7] -; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512-FCP-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3,4],ymm3[5,6,7] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2],xmm0[3,4],xmm2[5],xmm0[6,7] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 -; AVX512-FCP-NEXT: vextracti32x4 $2, %zmm0, %xmm0 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4],xmm5[5,6,7] -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3],ymm5[4,5,6,7] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1],xmm2[2],xmm1[3,4],xmm2[5],xmm1[6,7] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1,2,3,4],xmm5[5,6,7] +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3],ymm5[4,5,6,7] +; AVX512-FCP-NEXT: vpternlogq $202, %ymm8, %ymm9, %ymm0 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm0[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm0 = ymm2[0],ymm0[1,2],ymm2[3],ymm0[4,5],ymm2[6],ymm0[7],ymm2[8],ymm0[9,10],ymm2[11],ymm0[12,13],ymm2[14],ymm0[15] +; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm0, %ymm0 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm2 = xmm4[0],xmm3[1],xmm4[2,3],xmm3[4],xmm4[5,6],xmm3[7] +; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm2, %xmm2 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3,4],ymm2[5,6,7] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 ; AVX512-FCP-NEXT: vmovdqa64 %zmm7, (%rsi) ; AVX512-FCP-NEXT: vmovdqa64 %zmm10, (%rdx) ; AVX512-FCP-NEXT: vmovdqa64 %zmm0, (%rcx) @@ -1988,22 +1984,22 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; ; AVX512DQ-LABEL: load_i16_stride3_vf32: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm1 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm0 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] ; AVX512DQ-NEXT: vmovdqa 128(%rdi), %ymm5 ; AVX512DQ-NEXT: vmovdqa 160(%rdi), %ymm6 -; AVX512DQ-NEXT: vmovdqa %ymm1, %ymm0 -; AVX512DQ-NEXT: vpternlogq $202, %ymm5, %ymm6, %ymm0 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm0[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm0 = ymm0[0],ymm2[1],ymm0[2,3],ymm2[4],ymm0[5,6],ymm2[7],ymm0[8],ymm2[9],ymm0[10,11],ymm2[12],ymm0[13,14],ymm2[15] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] -; AVX512DQ-NEXT: vmovdqa 112(%rdi), %xmm0 +; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm1 +; AVX512DQ-NEXT: vpternlogq $202, %ymm5, %ymm6, %ymm1 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm2[1],ymm1[2,3],ymm2[4],ymm1[5,6],ymm2[7],ymm1[8],ymm2[9],ymm1[10,11],ymm2[12],ymm1[13,14],ymm2[15] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] +; AVX512DQ-NEXT: vmovdqa 112(%rdi), %xmm1 ; AVX512DQ-NEXT: vmovdqa 96(%rdi), %xmm2 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm2[0],xmm0[1],xmm2[2,3],xmm0[4],xmm2[5,6],xmm0[7] +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] ; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[0,1,6,7,12,13,2,3,8,9,14,15,u,u,u,u] ; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm7 = ymm4[0,1,2],ymm3[3,4,5,6,7] ; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm8 ; AVX512DQ-NEXT: vmovdqa 32(%rdi), %ymm9 -; AVX512DQ-NEXT: vmovdqa %ymm1, %ymm3 +; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm3 ; AVX512DQ-NEXT: vpternlogq $202, %ymm9, %ymm8, %ymm3 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm3[2,3,0,1] ; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm4[1],ymm3[2,3],ymm4[4],ymm3[5,6],ymm4[7],ymm3[8],ymm4[9],ymm3[10,11],ymm4[12],ymm3[13,14],ymm4[15] @@ -2017,14 +2013,14 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm10 = xmm10[0,1,2,3,6,5,4,7] ; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm10 = ymm10[0,1,2,3],ymm11[4,5,6,7] ; AVX512DQ-NEXT: vinserti64x4 $1, %ymm7, %zmm10, %zmm7 -; AVX512DQ-NEXT: vmovdqa %ymm1, %ymm10 +; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm10 ; AVX512DQ-NEXT: vpternlogq $202, %ymm6, %ymm5, %ymm10 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm11 = ymm10[2,3,0,1] ; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm10 = ymm10[0,1],ymm11[2],ymm10[3,4],ymm11[5],ymm10[6,7,8,9],ymm11[10],ymm10[11,12],ymm11[13],ymm10[14,15] ; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm11 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] ; AVX512DQ-NEXT: vpshufb %ymm11, %ymm10, %ymm10 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0,1],xmm0[2],xmm2[3,4],xmm0[5],xmm2[6,7] -; AVX512DQ-NEXT: vpshufb %xmm11, %xmm12, %xmm12 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0,1],xmm1[2],xmm2[3,4],xmm1[5],xmm2[6,7] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm12 = xmm12[2,3,8,9,14,15,4,5,10,11,10,11,10,11,10,11] ; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm12 = xmm12[0,1,2,3,4],xmm10[5,6,7] ; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm10 = ymm12[0,1,2,3],ymm10[4,5,6,7] ; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm12 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] @@ -2045,21 +2041,19 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm5 = ymm5[0],ymm12[1,2],ymm5[3],ymm12[4,5],ymm5[6],ymm12[7],ymm5[8],ymm12[9,10],ymm5[11],ymm12[12,13],ymm5[14],ymm12[15] ; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm6 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] ; AVX512DQ-NEXT: vpshufb %ymm6, %ymm5, %ymm5 -; AVX512DQ-NEXT: vpternlogq $202, %ymm8, %ymm9, %ymm1 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm8 = ymm1[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm8[0],ymm1[1,2],ymm8[3],ymm1[4,5],ymm8[6],ymm1[7],ymm8[8],ymm1[9,10],ymm8[11],ymm1[12,13],ymm8[14],ymm1[15] -; AVX512DQ-NEXT: vpshufb %ymm6, %ymm1, %ymm1 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0],xmm3[1],xmm4[2,3],xmm3[4],xmm4[5,6],xmm3[7] -; AVX512DQ-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512DQ-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3,4],ymm3[5,6,7] -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2],xmm0[3,4],xmm2[5],xmm0[6,7] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 -; AVX512DQ-NEXT: vextracti32x4 $2, %zmm0, %xmm0 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4],xmm5[5,6,7] -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3],ymm5[4,5,6,7] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1],xmm2[2],xmm1[3,4],xmm2[5],xmm1[6,7] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1,2,3,4],xmm5[5,6,7] +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3],ymm5[4,5,6,7] +; AVX512DQ-NEXT: vpternlogq $202, %ymm8, %ymm9, %ymm0 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm0[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm0 = ymm2[0],ymm0[1,2],ymm2[3],ymm0[4,5],ymm2[6],ymm0[7],ymm2[8],ymm0[9,10],ymm2[11],ymm0[12,13],ymm2[14],ymm0[15] +; AVX512DQ-NEXT: vpshufb %ymm6, %ymm0, %ymm0 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm2 = xmm4[0],xmm3[1],xmm4[2,3],xmm3[4],xmm4[5,6],xmm3[7] +; AVX512DQ-NEXT: vpshufb %xmm6, %xmm2, %xmm2 +; AVX512DQ-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3,4],ymm2[5,6,7] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 ; AVX512DQ-NEXT: vmovdqa64 %zmm7, (%rsi) ; AVX512DQ-NEXT: vmovdqa64 %zmm10, (%rdx) ; AVX512DQ-NEXT: vmovdqa64 %zmm0, (%rcx) @@ -2068,22 +2062,22 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; ; AVX512DQ-FCP-LABEL: load_i16_stride3_vf32: ; AVX512DQ-FCP: # %bb.0: -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] ; AVX512DQ-FCP-NEXT: vmovdqa 128(%rdi), %ymm5 ; AVX512DQ-FCP-NEXT: vmovdqa 160(%rdi), %ymm6 -; AVX512DQ-FCP-NEXT: vmovdqa %ymm1, %ymm0 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm5, %ymm6, %ymm0 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm0[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm0 = ymm0[0],ymm2[1],ymm0[2,3],ymm2[4],ymm0[5,6],ymm2[7],ymm0[8],ymm2[9],ymm0[10,11],ymm2[12],ymm0[13,14],ymm2[15] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] -; AVX512DQ-FCP-NEXT: vmovdqa 112(%rdi), %xmm0 +; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm1 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm5, %ymm6, %ymm1 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm2[1],ymm1[2,3],ymm2[4],ymm1[5,6],ymm2[7],ymm1[8],ymm2[9],ymm1[10,11],ymm2[12],ymm1[13,14],ymm2[15] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] +; AVX512DQ-FCP-NEXT: vmovdqa 112(%rdi), %xmm1 ; AVX512DQ-FCP-NEXT: vmovdqa 96(%rdi), %xmm2 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm2[0],xmm0[1],xmm2[2,3],xmm0[4],xmm2[5,6],xmm0[7] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[0,1,6,7,12,13,2,3,8,9,14,15,u,u,u,u] ; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm7 = ymm4[0,1,2],ymm3[3,4,5,6,7] ; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %ymm8 ; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %ymm9 -; AVX512DQ-FCP-NEXT: vmovdqa %ymm1, %ymm3 +; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm3 ; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm9, %ymm8, %ymm3 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm3[2,3,0,1] ; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm4[1],ymm3[2,3],ymm4[4],ymm3[5,6],ymm4[7],ymm3[8],ymm4[9],ymm3[10,11],ymm4[12],ymm3[13,14],ymm4[15] @@ -2097,14 +2091,14 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm10 = xmm10[0,1,2,3,6,5,4,7] ; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm10 = ymm10[0,1,2,3],ymm11[4,5,6,7] ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm10, %zmm7 -; AVX512DQ-FCP-NEXT: vmovdqa %ymm1, %ymm10 +; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm10 ; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm6, %ymm5, %ymm10 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm10[2,3,0,1] ; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm10 = ymm10[0,1],ymm11[2],ymm10[3,4],ymm11[5],ymm10[6,7,8,9],ymm11[10],ymm10[11,12],ymm11[13],ymm10[14,15] ; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] ; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm10, %ymm10 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0,1],xmm0[2],xmm2[3,4],xmm0[5],xmm2[6,7] -; AVX512DQ-FCP-NEXT: vpshufb %xmm11, %xmm12, %xmm12 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0,1],xmm1[2],xmm2[3,4],xmm1[5],xmm2[6,7] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm12 = xmm12[2,3,8,9,14,15,4,5,10,11,10,11,10,11,10,11] ; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm12[0,1,2,3,4],xmm10[5,6,7] ; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm10 = ymm12[0,1,2,3],ymm10[4,5,6,7] ; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] @@ -2125,21 +2119,19 @@ define void @load_i16_stride3_vf32(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm5 = ymm5[0],ymm12[1,2],ymm5[3],ymm12[4,5],ymm5[6],ymm12[7],ymm5[8],ymm12[9,10],ymm5[11],ymm12[12,13],ymm5[14],ymm12[15] ; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm6 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] ; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm5, %ymm5 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm8, %ymm9, %ymm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm1[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm8[0],ymm1[1,2],ymm8[3],ymm1[4,5],ymm8[6],ymm1[7],ymm8[8],ymm1[9,10],ymm8[11],ymm1[12,13],ymm8[14],ymm1[15] -; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0],xmm3[1],xmm4[2,3],xmm3[4],xmm4[5,6],xmm3[7] -; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3,4],ymm3[5,6,7] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2],xmm0[3,4],xmm2[5],xmm0[6,7] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 -; AVX512DQ-FCP-NEXT: vextracti32x4 $2, %zmm0, %xmm0 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4],xmm5[5,6,7] -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3],ymm5[4,5,6,7] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1],xmm2[2],xmm1[3,4],xmm2[5],xmm1[6,7] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1,2,3,4],xmm5[5,6,7] +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3],ymm5[4,5,6,7] +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm8, %ymm9, %ymm0 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm0[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm0 = ymm2[0],ymm0[1,2],ymm2[3],ymm0[4,5],ymm2[6],ymm0[7],ymm2[8],ymm0[9,10],ymm2[11],ymm0[12,13],ymm2[14],ymm0[15] +; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm0, %ymm0 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm2 = xmm4[0],xmm3[1],xmm4[2,3],xmm3[4],xmm4[5,6],xmm3[7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm2, %xmm2 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3,4],ymm2[5,6,7] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm7, (%rsi) ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm10, (%rdx) ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm0, (%rcx) @@ -3500,688 +3492,668 @@ define void @load_i16_stride3_vf64(ptr %in.vec, ptr %out.vec0, ptr %out.vec1, pt ; AVX512-LABEL: load_i16_stride3_vf64: ; AVX512: # %bb.0: ; AVX512-NEXT: vmovdqa {{.*#+}} ymm0 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] -; AVX512-NEXT: vmovdqa64 224(%rdi), %ymm20 -; AVX512-NEXT: vmovdqa64 192(%rdi), %ymm21 +; AVX512-NEXT: vmovdqa64 224(%rdi), %ymm18 +; AVX512-NEXT: vmovdqa64 192(%rdi), %ymm20 ; AVX512-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512-NEXT: vpternlogq $202, %ymm20, %ymm21, %ymm1 -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm1[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm3[1],ymm1[2,3],ymm3[4],ymm1[5,6],ymm3[7],ymm1[8],ymm3[9],ymm1[10,11],ymm3[12],ymm1[13,14],ymm3[15] -; AVX512-NEXT: vmovdqa {{.*#+}} ymm3 = [0,1,6,7,12,13,2,3,4,5,14,15,8,9,10,11,16,17,22,23,28,29,18,19,20,21,30,31,24,25,26,27] -; AVX512-NEXT: vpshufb %ymm3, %ymm1, %ymm5 -; AVX512-NEXT: vmovdqa 272(%rdi), %xmm8 +; AVX512-NEXT: vpternlogq $202, %ymm18, %ymm20, %ymm1 +; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm2 = ymm1[0],ymm2[1],ymm1[2,3],ymm2[4],ymm1[5,6],ymm2[7],ymm1[8],ymm2[9],ymm1[10,11],ymm2[12],ymm1[13,14],ymm2[15] +; AVX512-NEXT: vmovdqa {{.*#+}} ymm7 = [0,1,6,7,12,13,2,3,4,5,14,15,8,9,10,11,16,17,22,23,28,29,18,19,20,21,30,31,24,25,26,27] +; AVX512-NEXT: vpshufb %ymm7, %ymm2, %ymm5 +; AVX512-NEXT: vmovdqa 272(%rdi), %xmm1 ; AVX512-NEXT: vmovdqa 256(%rdi), %xmm2 -; AVX512-NEXT: vpblendw {{.*#+}} xmm6 = xmm2[0,1],xmm8[2],xmm2[3,4],xmm8[5],xmm2[6,7] -; AVX512-NEXT: vmovdqa %xmm2, %xmm14 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm9 = [4,5,14,15,0,1,2,3,8,9,14,15,4,5,10,11] -; AVX512-NEXT: vpshufb %xmm9, %xmm6, %xmm6 +; AVX512-NEXT: vpblendw {{.*#+}} xmm6 = xmm2[0,1],xmm1[2],xmm2[3,4],xmm1[5],xmm2[6,7] +; AVX512-NEXT: vmovdqa %xmm2, %xmm3 +; AVX512-NEXT: vmovdqa64 %xmm1, %xmm19 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm13 = [4,5,14,15,0,1,2,3,8,9,14,15,4,5,10,11] +; AVX512-NEXT: vpshufb %xmm13, %xmm6, %xmm6 ; AVX512-NEXT: vinserti128 $1, %xmm6, %ymm0, %ymm6 ; AVX512-NEXT: vpblendw {{.*#+}} ymm6 = ymm5[0,1,2],ymm6[3,4,5,6,7],ymm5[8,9,10],ymm6[11,12,13,14,15] ; AVX512-NEXT: vpshufhw {{.*#+}} xmm5 = xmm5[0,1,2,3,6,5,4,7] ; AVX512-NEXT: vpblendd {{.*#+}} ymm5 = ymm5[0,1,2,3],ymm6[4,5,6,7] -; AVX512-NEXT: vmovdqa64 320(%rdi), %ymm22 -; AVX512-NEXT: vmovdqa64 352(%rdi), %ymm23 -; AVX512-NEXT: vmovdqa %ymm0, %ymm6 -; AVX512-NEXT: vpternlogq $202, %ymm22, %ymm23, %ymm6 -; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm6[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm6 = ymm6[0],ymm7[1],ymm6[2,3],ymm7[4],ymm6[5,6],ymm7[7],ymm6[8],ymm7[9],ymm6[10,11],ymm7[12],ymm6[13,14],ymm7[15] -; AVX512-NEXT: vmovdqa {{.*#+}} ymm11 = [0,1,6,7,12,13,2,3,8,9,14,15,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] -; AVX512-NEXT: vpshufb %ymm11, %ymm6, %ymm12 +; AVX512-NEXT: vmovdqa64 320(%rdi), %ymm21 +; AVX512-NEXT: vmovdqa64 352(%rdi), %ymm22 +; AVX512-NEXT: vmovdqa %ymm0, %ymm8 +; AVX512-NEXT: vpternlogq $202, %ymm21, %ymm22, %ymm8 +; AVX512-NEXT: vpermq {{.*#+}} ymm9 = ymm8[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm8 = ymm8[0],ymm9[1],ymm8[2,3],ymm9[4],ymm8[5,6],ymm9[7],ymm8[8],ymm9[9],ymm8[10,11],ymm9[12],ymm8[13,14],ymm9[15] +; AVX512-NEXT: vmovdqa {{.*#+}} ymm10 = [0,1,6,7,12,13,2,3,8,9,14,15,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] +; AVX512-NEXT: vpshufb %ymm10, %ymm8, %ymm11 ; AVX512-NEXT: vmovdqa 304(%rdi), %xmm1 ; AVX512-NEXT: vmovdqa 288(%rdi), %xmm2 -; AVX512-NEXT: vpblendw {{.*#+}} xmm13 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] +; AVX512-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] ; AVX512-NEXT: vmovdqa %xmm2, %xmm4 -; AVX512-NEXT: vmovdqa %xmm1, %xmm6 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm15 = [0,1,6,7,12,13,2,3,8,9,14,15,12,13,14,15] -; AVX512-NEXT: vpshufb %xmm15, %xmm13, %xmm13 -; AVX512-NEXT: vpblendd {{.*#+}} ymm12 = ymm13[0,1,2],ymm12[3,4,5,6,7] -; AVX512-NEXT: vinserti64x4 $1, %ymm12, %zmm5, %zmm16 -; AVX512-NEXT: vmovdqa64 128(%rdi), %ymm24 -; AVX512-NEXT: vmovdqa 160(%rdi), %ymm13 +; AVX512-NEXT: vmovdqa %xmm1, %xmm8 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm14 = [0,1,6,7,12,13,2,3,8,9,14,15,12,13,14,15] +; AVX512-NEXT: vpshufb %xmm14, %xmm12, %xmm12 +; AVX512-NEXT: vpblendd {{.*#+}} ymm11 = ymm12[0,1,2],ymm11[3,4,5,6,7] +; AVX512-NEXT: vinserti64x4 $1, %ymm11, %zmm5, %zmm16 +; AVX512-NEXT: vmovdqa64 128(%rdi), %ymm23 +; AVX512-NEXT: vmovdqa 160(%rdi), %ymm11 ; AVX512-NEXT: vmovdqa %ymm0, %ymm5 -; AVX512-NEXT: vpternlogq $202, %ymm24, %ymm13, %ymm5 +; AVX512-NEXT: vpternlogq $202, %ymm23, %ymm11, %ymm5 ; AVX512-NEXT: vpermq {{.*#+}} ymm12 = ymm5[2,3,0,1] ; AVX512-NEXT: vpblendw {{.*#+}} ymm5 = ymm5[0],ymm12[1],ymm5[2,3],ymm12[4],ymm5[5,6],ymm12[7],ymm5[8],ymm12[9],ymm5[10,11],ymm12[12],ymm5[13,14],ymm12[15] -; AVX512-NEXT: vpshufb %ymm11, %ymm5, %ymm5 -; AVX512-NEXT: vmovdqa 112(%rdi), %xmm11 -; AVX512-NEXT: vmovdqa 96(%rdi), %xmm12 -; AVX512-NEXT: vpblendw {{.*#+}} xmm10 = xmm12[0],xmm11[1],xmm12[2,3],xmm11[4],xmm12[5,6],xmm11[7] -; AVX512-NEXT: vpshufb %xmm15, %xmm10, %xmm10 -; AVX512-NEXT: vpblendd {{.*#+}} ymm1 = ymm10[0,1,2],ymm5[3,4,5,6,7] -; AVX512-NEXT: vmovdqa64 (%rdi), %ymm17 -; AVX512-NEXT: vmovdqa 32(%rdi), %ymm5 +; AVX512-NEXT: vpshufb %ymm10, %ymm5, %ymm10 +; AVX512-NEXT: vmovdqa 112(%rdi), %xmm15 +; AVX512-NEXT: vmovdqa 96(%rdi), %xmm5 +; AVX512-NEXT: vpblendw {{.*#+}} xmm12 = xmm5[0],xmm15[1],xmm5[2,3],xmm15[4],xmm5[5,6],xmm15[7] +; AVX512-NEXT: vpshufb %xmm14, %xmm12, %xmm12 +; AVX512-NEXT: vpblendd {{.*#+}} ymm6 = ymm12[0,1,2],ymm10[3,4,5,6,7] +; AVX512-NEXT: vmovdqa64 (%rdi), %ymm24 +; AVX512-NEXT: vmovdqa 32(%rdi), %ymm12 ; AVX512-NEXT: vmovdqa %ymm0, %ymm10 -; AVX512-NEXT: vpternlogq $202, %ymm5, %ymm17, %ymm10 -; AVX512-NEXT: vpermq {{.*#+}} ymm15 = ymm10[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm10 = ymm10[0],ymm15[1],ymm10[2,3],ymm15[4],ymm10[5,6],ymm15[7],ymm10[8],ymm15[9],ymm10[10,11],ymm15[12],ymm10[13,14],ymm15[15] -; AVX512-NEXT: vpshufb %ymm3, %ymm10, %ymm2 +; AVX512-NEXT: vpternlogq $202, %ymm12, %ymm24, %ymm10 +; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm10[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm1 = ymm10[0],ymm1[1],ymm10[2,3],ymm1[4],ymm10[5,6],ymm1[7],ymm10[8],ymm1[9],ymm10[10,11],ymm1[12],ymm10[13,14],ymm1[15] +; AVX512-NEXT: vpshufb %ymm7, %ymm1, %ymm7 ; AVX512-NEXT: vmovdqa 80(%rdi), %xmm10 -; AVX512-NEXT: vmovdqa 64(%rdi), %xmm15 -; AVX512-NEXT: vpblendw {{.*#+}} xmm3 = xmm15[0,1],xmm10[2],xmm15[3,4],xmm10[5],xmm15[6,7] -; AVX512-NEXT: vpshufb %xmm9, %xmm3, %xmm3 -; AVX512-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 -; AVX512-NEXT: vpblendw {{.*#+}} ymm3 = ymm2[0,1,2],ymm3[3,4,5,6,7],ymm2[8,9,10],ymm3[11,12,13,14,15] -; AVX512-NEXT: vpshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,6,5,4,7] -; AVX512-NEXT: vpblendd {{.*#+}} ymm2 = ymm2[0,1,2,3],ymm3[4,5,6,7] -; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm18 -; AVX512-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512-NEXT: vpternlogq $202, %ymm23, %ymm22, %ymm1 -; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm2[2],ymm1[3,4],ymm2[5],ymm1[6,7,8,9],ymm2[10],ymm1[11,12],ymm2[13],ymm1[14,15] -; AVX512-NEXT: vmovdqa {{.*#+}} ymm2 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] -; AVX512-NEXT: vpshufb %ymm2, %ymm1, %ymm1 -; AVX512-NEXT: vmovdqa64 %ymm2, %ymm28 -; AVX512-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0,1],xmm6[2],xmm4[3,4],xmm6[5],xmm4[6,7] -; AVX512-NEXT: vmovdqa64 %xmm6, %xmm25 +; AVX512-NEXT: vmovdqa 64(%rdi), %xmm1 +; AVX512-NEXT: vpblendw {{.*#+}} xmm2 = xmm1[0,1],xmm10[2],xmm1[3,4],xmm10[5],xmm1[6,7] +; AVX512-NEXT: vpshufb %xmm13, %xmm2, %xmm2 +; AVX512-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 +; AVX512-NEXT: vpblendw {{.*#+}} ymm2 = ymm7[0,1,2],ymm2[3,4,5,6,7],ymm7[8,9,10],ymm2[11,12,13,14,15] +; AVX512-NEXT: vpshufhw {{.*#+}} xmm7 = xmm7[0,1,2,3,6,5,4,7] +; AVX512-NEXT: vpblendd {{.*#+}} ymm2 = ymm7[0,1,2,3],ymm2[4,5,6,7] +; AVX512-NEXT: vinserti64x4 $1, %ymm6, %zmm2, %zmm17 +; AVX512-NEXT: vmovdqa %ymm0, %ymm2 +; AVX512-NEXT: vpternlogq $202, %ymm22, %ymm21, %ymm2 +; AVX512-NEXT: vpermq {{.*#+}} ymm6 = ymm2[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm6[2],ymm2[3,4],ymm6[5],ymm2[6,7,8,9],ymm6[10],ymm2[11,12],ymm6[13],ymm2[14,15] +; AVX512-NEXT: vmovdqa {{.*#+}} ymm9 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] +; AVX512-NEXT: vpshufb %ymm9, %ymm2, %ymm2 +; AVX512-NEXT: vpblendw {{.*#+}} xmm7 = xmm4[0,1],xmm8[2],xmm4[3,4],xmm8[5],xmm4[6,7] +; AVX512-NEXT: vmovdqa64 %xmm8, %xmm25 ; AVX512-NEXT: vmovdqa64 %xmm4, %xmm26 ; AVX512-NEXT: vmovdqa {{.*#+}} xmm6 = [2,3,8,9,14,15,4,5,10,11,10,11,10,11,10,11] -; AVX512-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1,2,3,4],xmm1[5,6,7] -; AVX512-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3],ymm1[4,5,6,7] -; AVX512-NEXT: vmovdqa {{.*#+}} ymm9 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] -; AVX512-NEXT: vmovdqa %ymm9, %ymm1 -; AVX512-NEXT: vpternlogq $202, %ymm21, %ymm20, %ymm1 -; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm1[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm4[2],ymm1[3,4],ymm4[5],ymm1[6,7,8,9],ymm4[10],ymm1[11,12],ymm4[13],ymm1[14,15] +; AVX512-NEXT: vpshufb %xmm6, %xmm7, %xmm7 +; AVX512-NEXT: vpblendw {{.*#+}} xmm7 = xmm7[0,1,2,3,4],xmm2[5,6,7] +; AVX512-NEXT: vpblendd {{.*#+}} ymm7 = ymm7[0,1,2,3],ymm2[4,5,6,7] +; AVX512-NEXT: vmovdqa {{.*#+}} ymm13 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] +; AVX512-NEXT: vmovdqa %ymm13, %ymm2 +; AVX512-NEXT: vpternlogq $202, %ymm20, %ymm18, %ymm2 +; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm2[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm4[2],ymm2[3,4],ymm4[5],ymm2[6,7,8,9],ymm4[10],ymm2[11,12],ymm4[13],ymm2[14,15] ; AVX512-NEXT: vmovdqa {{.*#+}} ymm4 = [2,3,8,9,14,15,4,5,12,13,10,11,0,1,6,7,18,19,24,25,30,31,20,21,28,29,26,27,16,17,22,23] -; AVX512-NEXT: vpshufb %ymm4, %ymm1, %ymm1 -; AVX512-NEXT: vmovdqa %xmm14, %xmm7 -; AVX512-NEXT: vpblendw {{.*#+}} xmm14 = xmm8[0,1],xmm14[2],xmm8[3,4],xmm14[5],xmm8[6,7] -; AVX512-NEXT: vmovdqa64 %xmm8, %xmm27 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm2 = [4,5,4,5,4,5,4,5,10,11,0,1,6,7,12,13] -; AVX512-NEXT: vpshufb %xmm2, %xmm14, %xmm14 -; AVX512-NEXT: vinserti128 $1, %xmm14, %ymm0, %ymm14 -; AVX512-NEXT: vpblendw {{.*#+}} ymm14 = ymm1[0,1,2],ymm14[3,4,5,6,7],ymm1[8,9,10],ymm14[11,12,13,14,15] -; AVX512-NEXT: vpshufhw {{.*#+}} xmm1 = xmm1[0,1,2,3,5,6,7,4] -; AVX512-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3],ymm14[4,5,6,7] -; AVX512-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm19 -; AVX512-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512-NEXT: vpternlogq $202, %ymm13, %ymm24, %ymm1 -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm1[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm3[2],ymm1[3,4],ymm3[5],ymm1[6,7,8,9],ymm3[10],ymm1[11,12],ymm3[13],ymm1[14,15] -; AVX512-NEXT: vmovdqa64 %ymm28, %ymm3 -; AVX512-NEXT: vpshufb %ymm3, %ymm1, %ymm1 -; AVX512-NEXT: vpblendw {{.*#+}} xmm3 = xmm12[0,1],xmm11[2],xmm12[3,4],xmm11[5],xmm12[6,7] -; AVX512-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1,2,3,4],xmm1[5,6,7] -; AVX512-NEXT: vpblendd {{.*#+}} ymm1 = ymm3[0,1,2,3],ymm1[4,5,6,7] -; AVX512-NEXT: vmovdqa %ymm9, %ymm3 -; AVX512-NEXT: vpternlogq $202, %ymm17, %ymm5, %ymm3 -; AVX512-NEXT: vpermq {{.*#+}} ymm6 = ymm3[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0,1],ymm6[2],ymm3[3,4],ymm6[5],ymm3[6,7,8,9],ymm6[10],ymm3[11,12],ymm6[13],ymm3[14,15] -; AVX512-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm10[0,1],xmm15[2],xmm10[3,4],xmm15[5],xmm10[6,7] -; AVX512-NEXT: vpshufb %xmm2, %xmm4, %xmm2 -; AVX512-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 -; AVX512-NEXT: vpblendw {{.*#+}} ymm2 = ymm3[0,1,2],ymm2[3,4,5,6,7],ymm3[8,9,10],ymm2[11,12,13,14,15] -; AVX512-NEXT: vpshufhw {{.*#+}} xmm3 = xmm3[0,1,2,3,5,6,7,4] -; AVX512-NEXT: vpblendd {{.*#+}} ymm2 = ymm3[0,1,2,3],ymm2[4,5,6,7] -; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 -; AVX512-NEXT: vpternlogq $226, %ymm24, %ymm9, %ymm13 -; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm13[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0],ymm13[1,2],ymm2[3],ymm13[4,5],ymm2[6],ymm13[7],ymm2[8],ymm13[9,10],ymm2[11],ymm13[12,13],ymm2[14],ymm13[15] -; AVX512-NEXT: vpternlogq $226, %ymm17, %ymm0, %ymm5 -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm5[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm5[1,2],ymm3[3],ymm5[4,5],ymm3[6],ymm5[7],ymm3[8],ymm5[9,10],ymm3[11],ymm5[12,13],ymm3[14],ymm5[15] -; AVX512-NEXT: vmovdqa {{.*#+}} ymm4 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] -; AVX512-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512-NEXT: vpblendw {{.*#+}} xmm5 = xmm15[0],xmm10[1],xmm15[2,3],xmm10[4],xmm15[5,6],xmm10[7] -; AVX512-NEXT: vmovdqa {{.*#+}} xmm6 = [0,1,2,3,0,1,6,7,12,13,2,3,8,9,14,15] -; AVX512-NEXT: vpshufb %xmm6, %xmm5, %xmm5 -; AVX512-NEXT: vinserti128 $1, %xmm5, %ymm0, %ymm5 -; AVX512-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3,4],ymm5[5,6,7] ; AVX512-NEXT: vpshufb %ymm4, %ymm2, %ymm2 -; AVX512-NEXT: vpblendw {{.*#+}} xmm5 = xmm11[0,1],xmm12[2],xmm11[3,4],xmm12[5],xmm11[6,7] -; AVX512-NEXT: vmovdqa {{.*#+}} xmm8 = [4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] -; AVX512-NEXT: vpshufb %xmm8, %xmm5, %xmm5 -; AVX512-NEXT: vinserti64x4 $1, %ymm5, %zmm3, %zmm5 -; AVX512-NEXT: vextracti32x4 $2, %zmm5, %xmm5 -; AVX512-NEXT: vpblendw {{.*#+}} xmm5 = xmm5[0,1,2,3,4],xmm2[5,6,7] -; AVX512-NEXT: vpblendd {{.*#+}} ymm2 = ymm5[0,1,2,3],ymm2[4,5,6,7] +; AVX512-NEXT: vmovdqa64 %xmm19, %xmm8 +; AVX512-NEXT: vpblendw {{.*#+}} xmm14 = xmm8[0,1],xmm3[2],xmm8[3,4],xmm3[5],xmm8[6,7] +; AVX512-NEXT: vmovdqa64 %xmm3, %xmm27 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm3 = [4,5,4,5,4,5,4,5,10,11,0,1,6,7,12,13] +; AVX512-NEXT: vpshufb %xmm3, %xmm14, %xmm14 +; AVX512-NEXT: vinserti128 $1, %xmm14, %ymm0, %ymm14 +; AVX512-NEXT: vpblendw {{.*#+}} ymm14 = ymm2[0,1,2],ymm14[3,4,5,6,7],ymm2[8,9,10],ymm14[11,12,13,14,15] +; AVX512-NEXT: vpshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,5,6,7,4] +; AVX512-NEXT: vpblendd {{.*#+}} ymm2 = ymm2[0,1,2,3],ymm14[4,5,6,7] +; AVX512-NEXT: vinserti64x4 $1, %ymm7, %zmm2, %zmm19 +; AVX512-NEXT: vmovdqa %ymm0, %ymm2 +; AVX512-NEXT: vpternlogq $202, %ymm11, %ymm23, %ymm2 +; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm2[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm7[2],ymm2[3,4],ymm7[5],ymm2[6,7,8,9],ymm7[10],ymm2[11,12],ymm7[13],ymm2[14,15] +; AVX512-NEXT: vpshufb %ymm9, %ymm2, %ymm2 +; AVX512-NEXT: vpblendw {{.*#+}} xmm7 = xmm5[0,1],xmm15[2],xmm5[3,4],xmm15[5],xmm5[6,7] +; AVX512-NEXT: vpshufb %xmm6, %xmm7, %xmm6 +; AVX512-NEXT: vpblendw {{.*#+}} xmm6 = xmm6[0,1,2,3,4],xmm2[5,6,7] +; AVX512-NEXT: vpblendd {{.*#+}} ymm2 = ymm6[0,1,2,3],ymm2[4,5,6,7] +; AVX512-NEXT: vmovdqa %ymm13, %ymm6 +; AVX512-NEXT: vpternlogq $202, %ymm24, %ymm12, %ymm6 +; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm6[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm6 = ymm6[0,1],ymm7[2],ymm6[3,4],ymm7[5],ymm6[6,7,8,9],ymm7[10],ymm6[11,12],ymm7[13],ymm6[14,15] +; AVX512-NEXT: vpshufb %ymm4, %ymm6, %ymm4 +; AVX512-NEXT: vpblendw {{.*#+}} xmm6 = xmm10[0,1],xmm1[2],xmm10[3,4],xmm1[5],xmm10[6,7] +; AVX512-NEXT: vpshufb %xmm3, %xmm6, %xmm3 +; AVX512-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 +; AVX512-NEXT: vpblendw {{.*#+}} ymm3 = ymm4[0,1,2],ymm3[3,4,5,6,7],ymm4[8,9,10],ymm3[11,12,13,14,15] +; AVX512-NEXT: vpshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,5,6,7,4] +; AVX512-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] ; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 -; AVX512-NEXT: vpternlogq $202, %ymm22, %ymm23, %ymm9 -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm9[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm9[1,2],ymm3[3],ymm9[4,5],ymm3[6],ymm9[7],ymm3[8],ymm9[9,10],ymm3[11],ymm9[12,13],ymm3[14],ymm9[15] -; AVX512-NEXT: vpternlogq $202, %ymm21, %ymm20, %ymm0 -; AVX512-NEXT: vpermq {{.*#+}} ymm5 = ymm0[2,3,0,1] -; AVX512-NEXT: vpblendw {{.*#+}} ymm0 = ymm5[0],ymm0[1,2],ymm5[3],ymm0[4,5],ymm5[6],ymm0[7],ymm5[8],ymm0[9,10],ymm5[11],ymm0[12,13],ymm5[14],ymm0[15] -; AVX512-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512-NEXT: vpshufb %ymm4, %ymm0, %ymm0 +; AVX512-NEXT: vpternlogq $226, %ymm23, %ymm13, %ymm11 +; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm11[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm11[1,2],ymm3[3],ymm11[4,5],ymm3[6],ymm11[7],ymm3[8],ymm11[9,10],ymm3[11],ymm11[12,13],ymm3[14],ymm11[15] +; AVX512-NEXT: vmovdqa {{.*#+}} ymm11 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] +; AVX512-NEXT: vpshufb %ymm11, %ymm3, %ymm3 +; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm15[0,1],xmm5[2],xmm15[3,4],xmm5[5],xmm15[6,7] +; AVX512-NEXT: vmovdqa {{.*#+}} xmm5 = [4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] +; AVX512-NEXT: vpshufb %xmm5, %xmm4, %xmm4 +; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] +; AVX512-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] +; AVX512-NEXT: vpternlogq $226, %ymm24, %ymm0, %ymm12 +; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm12[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm4 = ymm4[0],ymm12[1,2],ymm4[3],ymm12[4,5],ymm4[6],ymm12[7],ymm4[8],ymm12[9,10],ymm4[11],ymm12[12,13],ymm4[14],ymm12[15] +; AVX512-NEXT: vpshufb %ymm11, %ymm4, %ymm4 +; AVX512-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm10[1],xmm1[2,3],xmm10[4],xmm1[5,6],xmm10[7] +; AVX512-NEXT: vmovdqa {{.*#+}} xmm6 = [0,1,2,3,0,1,6,7,12,13,2,3,8,9,14,15] +; AVX512-NEXT: vpshufb %xmm6, %xmm1, %xmm1 +; AVX512-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm1 +; AVX512-NEXT: vpblendd {{.*#+}} ymm1 = ymm4[0,1,2,3,4],ymm1[5,6,7] +; AVX512-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1 +; AVX512-NEXT: vpternlogq $202, %ymm21, %ymm22, %ymm13 +; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm13[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm13[1,2],ymm3[3],ymm13[4,5],ymm3[6],ymm13[7],ymm3[8],ymm13[9,10],ymm3[11],ymm13[12,13],ymm3[14],ymm13[15] +; AVX512-NEXT: vmovdqa64 %xmm25, %xmm4 +; AVX512-NEXT: vmovdqa64 %xmm26, %xmm7 +; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1],xmm7[2],xmm4[3,4],xmm7[5],xmm4[6,7] +; AVX512-NEXT: vpshufb %xmm5, %xmm4, %xmm4 +; AVX512-NEXT: vpshufb %ymm11, %ymm3, %ymm3 +; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] +; AVX512-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] +; AVX512-NEXT: vpternlogq $202, %ymm20, %ymm18, %ymm0 +; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm0[2,3,0,1] +; AVX512-NEXT: vpblendw {{.*#+}} ymm0 = ymm4[0],ymm0[1,2],ymm4[3],ymm0[4,5],ymm4[6],ymm0[7],ymm4[8],ymm0[9,10],ymm4[11],ymm0[12,13],ymm4[14],ymm0[15] +; AVX512-NEXT: vpshufb %ymm11, %ymm0, %ymm0 ; AVX512-NEXT: vmovdqa64 %xmm27, %xmm4 -; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm7[0],xmm4[1],xmm7[2,3],xmm4[4],xmm7[5,6],xmm4[7] +; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0],xmm8[1],xmm4[2,3],xmm8[4],xmm4[5,6],xmm8[7] ; AVX512-NEXT: vpshufb %xmm6, %xmm4, %xmm4 ; AVX512-NEXT: vinserti128 $1, %xmm4, %ymm0, %ymm4 ; AVX512-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3,4],ymm4[5,6,7] -; AVX512-NEXT: vmovdqa64 %xmm25, %xmm4 -; AVX512-NEXT: vmovdqa64 %xmm26, %xmm5 -; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1],xmm5[2],xmm4[3,4],xmm5[5],xmm4[6,7] -; AVX512-NEXT: vpshufb %xmm8, %xmm4, %xmm4 -; AVX512-NEXT: vinserti64x4 $1, %ymm4, %zmm0, %zmm4 -; AVX512-NEXT: vextracti32x4 $2, %zmm4, %xmm4 -; AVX512-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] -; AVX512-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] ; AVX512-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 -; AVX512-NEXT: vmovdqa64 %zmm18, (%rsi) +; AVX512-NEXT: vmovdqa64 %zmm17, (%rsi) ; AVX512-NEXT: vmovdqa64 %zmm16, 64(%rsi) ; AVX512-NEXT: vmovdqa64 %zmm19, 64(%rdx) -; AVX512-NEXT: vmovdqa64 %zmm1, (%rdx) +; AVX512-NEXT: vmovdqa64 %zmm2, (%rdx) ; AVX512-NEXT: vmovdqa64 %zmm0, 64(%rcx) -; AVX512-NEXT: vmovdqa64 %zmm2, (%rcx) +; AVX512-NEXT: vmovdqa64 %zmm1, (%rcx) ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; ; AVX512-FCP-LABEL: load_i16_stride3_vf64: ; AVX512-FCP: # %bb.0: ; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] -; AVX512-FCP-NEXT: vmovdqa64 224(%rdi), %ymm20 -; AVX512-FCP-NEXT: vmovdqa64 192(%rdi), %ymm21 +; AVX512-FCP-NEXT: vmovdqa64 224(%rdi), %ymm18 +; AVX512-FCP-NEXT: vmovdqa64 192(%rdi), %ymm20 ; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm20, %ymm21, %ymm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm1[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm3[1],ymm1[2,3],ymm3[4],ymm1[5,6],ymm3[7],ymm1[8],ymm3[9],ymm1[10,11],ymm3[12],ymm1[13,14],ymm3[15] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm3 = [0,1,6,7,12,13,2,3,4,5,14,15,8,9,10,11,16,17,22,23,28,29,18,19,20,21,30,31,24,25,26,27] -; AVX512-FCP-NEXT: vpshufb %ymm3, %ymm1, %ymm5 -; AVX512-FCP-NEXT: vmovdqa 272(%rdi), %xmm8 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm18, %ymm20, %ymm1 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm1[0],ymm2[1],ymm1[2,3],ymm2[4],ymm1[5,6],ymm2[7],ymm1[8],ymm2[9],ymm1[10,11],ymm2[12],ymm1[13,14],ymm2[15] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm7 = [0,1,6,7,12,13,2,3,4,5,14,15,8,9,10,11,16,17,22,23,28,29,18,19,20,21,30,31,24,25,26,27] +; AVX512-FCP-NEXT: vpshufb %ymm7, %ymm2, %ymm5 +; AVX512-FCP-NEXT: vmovdqa 272(%rdi), %xmm1 ; AVX512-FCP-NEXT: vmovdqa 256(%rdi), %xmm2 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm6 = xmm2[0,1],xmm8[2],xmm2[3,4],xmm8[5],xmm2[6,7] -; AVX512-FCP-NEXT: vmovdqa %xmm2, %xmm14 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [4,5,14,15,0,1,2,3,8,9,14,15,4,5,10,11] -; AVX512-FCP-NEXT: vpshufb %xmm9, %xmm6, %xmm6 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm6 = xmm2[0,1],xmm1[2],xmm2[3,4],xmm1[5],xmm2[6,7] +; AVX512-FCP-NEXT: vmovdqa %xmm2, %xmm3 +; AVX512-FCP-NEXT: vmovdqa64 %xmm1, %xmm19 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm13 = [4,5,14,15,0,1,2,3,8,9,14,15,4,5,10,11] +; AVX512-FCP-NEXT: vpshufb %xmm13, %xmm6, %xmm6 ; AVX512-FCP-NEXT: vinserti128 $1, %xmm6, %ymm0, %ymm6 ; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm6 = ymm5[0,1,2],ymm6[3,4,5,6,7],ymm5[8,9,10],ymm6[11,12,13,14,15] ; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm5 = xmm5[0,1,2,3,6,5,4,7] ; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm5 = ymm5[0,1,2,3],ymm6[4,5,6,7] -; AVX512-FCP-NEXT: vmovdqa64 320(%rdi), %ymm22 -; AVX512-FCP-NEXT: vmovdqa64 352(%rdi), %ymm23 -; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm6 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm22, %ymm23, %ymm6 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm6[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm6 = ymm6[0],ymm7[1],ymm6[2,3],ymm7[4],ymm6[5,6],ymm7[7],ymm6[8],ymm7[9],ymm6[10,11],ymm7[12],ymm6[13,14],ymm7[15] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [0,1,6,7,12,13,2,3,8,9,14,15,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] -; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm6, %ymm12 +; AVX512-FCP-NEXT: vmovdqa64 320(%rdi), %ymm21 +; AVX512-FCP-NEXT: vmovdqa64 352(%rdi), %ymm22 +; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm8 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm21, %ymm22, %ymm8 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm8[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm8 = ymm8[0],ymm9[1],ymm8[2,3],ymm9[4],ymm8[5,6],ymm9[7],ymm8[8],ymm9[9],ymm8[10,11],ymm9[12],ymm8[13,14],ymm9[15] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [0,1,6,7,12,13,2,3,8,9,14,15,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] +; AVX512-FCP-NEXT: vpshufb %ymm10, %ymm8, %ymm11 ; AVX512-FCP-NEXT: vmovdqa 304(%rdi), %xmm1 ; AVX512-FCP-NEXT: vmovdqa 288(%rdi), %xmm2 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm13 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] ; AVX512-FCP-NEXT: vmovdqa %xmm2, %xmm4 -; AVX512-FCP-NEXT: vmovdqa %xmm1, %xmm6 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm15 = [0,1,6,7,12,13,2,3,8,9,14,15,12,13,14,15] -; AVX512-FCP-NEXT: vpshufb %xmm15, %xmm13, %xmm13 -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm12 = ymm13[0,1,2],ymm12[3,4,5,6,7] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm5, %zmm16 -; AVX512-FCP-NEXT: vmovdqa64 128(%rdi), %ymm24 -; AVX512-FCP-NEXT: vmovdqa 160(%rdi), %ymm13 +; AVX512-FCP-NEXT: vmovdqa %xmm1, %xmm8 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm14 = [0,1,6,7,12,13,2,3,8,9,14,15,12,13,14,15] +; AVX512-FCP-NEXT: vpshufb %xmm14, %xmm12, %xmm12 +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm11 = ymm12[0,1,2],ymm11[3,4,5,6,7] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm5, %zmm16 +; AVX512-FCP-NEXT: vmovdqa64 128(%rdi), %ymm23 +; AVX512-FCP-NEXT: vmovdqa 160(%rdi), %ymm11 ; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm5 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm24, %ymm13, %ymm5 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm23, %ymm11, %ymm5 ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm5[2,3,0,1] ; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm5 = ymm5[0],ymm12[1],ymm5[2,3],ymm12[4],ymm5[5,6],ymm12[7],ymm5[8],ymm12[9],ymm5[10,11],ymm12[12],ymm5[13,14],ymm12[15] -; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm5, %ymm5 -; AVX512-FCP-NEXT: vmovdqa 112(%rdi), %xmm11 -; AVX512-FCP-NEXT: vmovdqa 96(%rdi), %xmm12 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm10 = xmm12[0],xmm11[1],xmm12[2,3],xmm11[4],xmm12[5,6],xmm11[7] -; AVX512-FCP-NEXT: vpshufb %xmm15, %xmm10, %xmm10 -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm10[0,1,2],ymm5[3,4,5,6,7] -; AVX512-FCP-NEXT: vmovdqa64 (%rdi), %ymm17 -; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %ymm5 +; AVX512-FCP-NEXT: vpshufb %ymm10, %ymm5, %ymm10 +; AVX512-FCP-NEXT: vmovdqa 112(%rdi), %xmm15 +; AVX512-FCP-NEXT: vmovdqa 96(%rdi), %xmm5 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm5[0],xmm15[1],xmm5[2,3],xmm15[4],xmm5[5,6],xmm15[7] +; AVX512-FCP-NEXT: vpshufb %xmm14, %xmm12, %xmm12 +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm6 = ymm12[0,1,2],ymm10[3,4,5,6,7] +; AVX512-FCP-NEXT: vmovdqa64 (%rdi), %ymm24 +; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %ymm12 ; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm10 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm5, %ymm17, %ymm10 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm10[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm10 = ymm10[0],ymm15[1],ymm10[2,3],ymm15[4],ymm10[5,6],ymm15[7],ymm10[8],ymm15[9],ymm10[10,11],ymm15[12],ymm10[13,14],ymm15[15] -; AVX512-FCP-NEXT: vpshufb %ymm3, %ymm10, %ymm2 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm12, %ymm24, %ymm10 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm10[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm10[0],ymm1[1],ymm10[2,3],ymm1[4],ymm10[5,6],ymm1[7],ymm10[8],ymm1[9],ymm10[10,11],ymm1[12],ymm10[13,14],ymm1[15] +; AVX512-FCP-NEXT: vpshufb %ymm7, %ymm1, %ymm7 ; AVX512-FCP-NEXT: vmovdqa 80(%rdi), %xmm10 -; AVX512-FCP-NEXT: vmovdqa 64(%rdi), %xmm15 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm15[0,1],xmm10[2],xmm15[3,4],xmm10[5],xmm15[6,7] -; AVX512-FCP-NEXT: vpshufb %xmm9, %xmm3, %xmm3 -; AVX512-FCP-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm2[0,1,2],ymm3[3,4,5,6,7],ymm2[8,9,10],ymm3[11,12,13,14,15] -; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,6,5,4,7] -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm2[0,1,2,3],ymm3[4,5,6,7] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm18 -; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm23, %ymm22, %ymm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm2[2],ymm1[3,4],ymm2[5],ymm1[6,7,8,9],ymm2[10],ymm1[11,12],ymm2[13],ymm1[14,15] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm2 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] -; AVX512-FCP-NEXT: vpshufb %ymm2, %ymm1, %ymm1 -; AVX512-FCP-NEXT: vmovdqa64 %ymm2, %ymm28 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0,1],xmm6[2],xmm4[3,4],xmm6[5],xmm4[6,7] -; AVX512-FCP-NEXT: vmovdqa64 %xmm6, %xmm25 +; AVX512-FCP-NEXT: vmovdqa 64(%rdi), %xmm1 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm2 = xmm1[0,1],xmm10[2],xmm1[3,4],xmm10[5],xmm1[6,7] +; AVX512-FCP-NEXT: vpshufb %xmm13, %xmm2, %xmm2 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm7[0,1,2],ymm2[3,4,5,6,7],ymm7[8,9,10],ymm2[11,12,13,14,15] +; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm7 = xmm7[0,1,2,3,6,5,4,7] +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm7[0,1,2,3],ymm2[4,5,6,7] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm2, %zmm17 +; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm2 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm22, %ymm21, %ymm2 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm2[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm6[2],ymm2[3,4],ymm6[5],ymm2[6,7,8,9],ymm6[10],ymm2[11,12],ymm6[13],ymm2[14,15] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] +; AVX512-FCP-NEXT: vpshufb %ymm9, %ymm2, %ymm2 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm7 = xmm4[0,1],xmm8[2],xmm4[3,4],xmm8[5],xmm4[6,7] +; AVX512-FCP-NEXT: vmovdqa64 %xmm8, %xmm25 ; AVX512-FCP-NEXT: vmovdqa64 %xmm4, %xmm26 ; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [2,3,8,9,14,15,4,5,10,11,10,11,10,11,10,11] -; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1,2,3,4],xmm1[5,6,7] -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3],ymm1[4,5,6,7] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] -; AVX512-FCP-NEXT: vmovdqa %ymm9, %ymm1 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm21, %ymm20, %ymm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm1[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm4[2],ymm1[3,4],ymm4[5],ymm1[6,7,8,9],ymm4[10],ymm1[11,12],ymm4[13],ymm1[14,15] +; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm7, %xmm7 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm7 = xmm7[0,1,2,3,4],xmm2[5,6,7] +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm7 = ymm7[0,1,2,3],ymm2[4,5,6,7] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm13 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] +; AVX512-FCP-NEXT: vmovdqa %ymm13, %ymm2 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm20, %ymm18, %ymm2 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm2[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm4[2],ymm2[3,4],ymm4[5],ymm2[6,7,8,9],ymm4[10],ymm2[11,12],ymm4[13],ymm2[14,15] ; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [2,3,8,9,14,15,4,5,12,13,10,11,0,1,6,7,18,19,24,25,30,31,20,21,28,29,26,27,16,17,22,23] -; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm1, %ymm1 -; AVX512-FCP-NEXT: vmovdqa %xmm14, %xmm7 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm14 = xmm8[0,1],xmm14[2],xmm8[3,4],xmm14[5],xmm8[6,7] -; AVX512-FCP-NEXT: vmovdqa64 %xmm8, %xmm27 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm2 = [4,5,4,5,4,5,4,5,10,11,0,1,6,7,12,13] -; AVX512-FCP-NEXT: vpshufb %xmm2, %xmm14, %xmm14 -; AVX512-FCP-NEXT: vinserti128 $1, %xmm14, %ymm0, %ymm14 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm14 = ymm1[0,1,2],ymm14[3,4,5,6,7],ymm1[8,9,10],ymm14[11,12,13,14,15] -; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm1 = xmm1[0,1,2,3,5,6,7,4] -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3],ymm14[4,5,6,7] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm19 -; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm13, %ymm24, %ymm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm1[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm3[2],ymm1[3,4],ymm3[5],ymm1[6,7,8,9],ymm3[10],ymm1[11,12],ymm3[13],ymm1[14,15] -; AVX512-FCP-NEXT: vmovdqa64 %ymm28, %ymm3 -; AVX512-FCP-NEXT: vpshufb %ymm3, %ymm1, %ymm1 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm12[0,1],xmm11[2],xmm12[3,4],xmm11[5],xmm12[6,7] -; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1,2,3,4],xmm1[5,6,7] -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm3[0,1,2,3],ymm1[4,5,6,7] -; AVX512-FCP-NEXT: vmovdqa %ymm9, %ymm3 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm17, %ymm5, %ymm3 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm3[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0,1],ymm6[2],ymm3[3,4],ymm6[5],ymm3[6,7,8,9],ymm6[10],ymm3[11,12],ymm6[13],ymm3[14,15] -; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm10[0,1],xmm15[2],xmm10[3,4],xmm15[5],xmm10[6,7] -; AVX512-FCP-NEXT: vpshufb %xmm2, %xmm4, %xmm2 -; AVX512-FCP-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm3[0,1,2],ymm2[3,4,5,6,7],ymm3[8,9,10],ymm2[11,12,13,14,15] -; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm3 = xmm3[0,1,2,3,5,6,7,4] -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm3[0,1,2,3],ymm2[4,5,6,7] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 -; AVX512-FCP-NEXT: vpternlogq $226, %ymm24, %ymm9, %ymm13 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm13[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0],ymm13[1,2],ymm2[3],ymm13[4,5],ymm2[6],ymm13[7],ymm2[8],ymm13[9,10],ymm2[11],ymm13[12,13],ymm2[14],ymm13[15] -; AVX512-FCP-NEXT: vpternlogq $226, %ymm17, %ymm0, %ymm5 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm5[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm5[1,2],ymm3[3],ymm5[4,5],ymm3[6],ymm5[7],ymm3[8],ymm5[9,10],ymm3[11],ymm5[12,13],ymm3[14],ymm5[15] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] -; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm5 = xmm15[0],xmm10[1],xmm15[2,3],xmm10[4],xmm15[5,6],xmm10[7] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [0,1,2,3,0,1,6,7,12,13,2,3,8,9,14,15] -; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm5, %xmm5 -; AVX512-FCP-NEXT: vinserti128 $1, %xmm5, %ymm0, %ymm5 -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3,4],ymm5[5,6,7] ; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm2, %ymm2 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm5 = xmm11[0,1],xmm12[2],xmm11[3,4],xmm12[5],xmm11[6,7] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] -; AVX512-FCP-NEXT: vpshufb %xmm8, %xmm5, %xmm5 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm3, %zmm5 -; AVX512-FCP-NEXT: vextracti32x4 $2, %zmm5, %xmm5 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm5 = xmm5[0,1,2,3,4],xmm2[5,6,7] -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm5[0,1,2,3],ymm2[4,5,6,7] +; AVX512-FCP-NEXT: vmovdqa64 %xmm19, %xmm8 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm14 = xmm8[0,1],xmm3[2],xmm8[3,4],xmm3[5],xmm8[6,7] +; AVX512-FCP-NEXT: vmovdqa64 %xmm3, %xmm27 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [4,5,4,5,4,5,4,5,10,11,0,1,6,7,12,13] +; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm14, %xmm14 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm14, %ymm0, %ymm14 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm14 = ymm2[0,1,2],ymm14[3,4,5,6,7],ymm2[8,9,10],ymm14[11,12,13,14,15] +; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,5,6,7,4] +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm2[0,1,2,3],ymm14[4,5,6,7] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm2, %zmm19 +; AVX512-FCP-NEXT: vmovdqa %ymm0, %ymm2 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm11, %ymm23, %ymm2 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm2[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm7[2],ymm2[3,4],ymm7[5],ymm2[6,7,8,9],ymm7[10],ymm2[11,12],ymm7[13],ymm2[14,15] +; AVX512-FCP-NEXT: vpshufb %ymm9, %ymm2, %ymm2 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm7 = xmm5[0,1],xmm15[2],xmm5[3,4],xmm15[5],xmm5[6,7] +; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm7, %xmm6 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm6 = xmm6[0,1,2,3,4],xmm2[5,6,7] +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm6[0,1,2,3],ymm2[4,5,6,7] +; AVX512-FCP-NEXT: vmovdqa %ymm13, %ymm6 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm24, %ymm12, %ymm6 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm6[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm6 = ymm6[0,1],ymm7[2],ymm6[3,4],ymm7[5],ymm6[6,7,8,9],ymm7[10],ymm6[11,12],ymm7[13],ymm6[14,15] +; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm6, %ymm4 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm6 = xmm10[0,1],xmm1[2],xmm10[3,4],xmm1[5],xmm10[6,7] +; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm6, %xmm3 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm4[0,1,2],ymm3[3,4,5,6,7],ymm4[8,9,10],ymm3[11,12,13,14,15] +; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,5,6,7,4] +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 -; AVX512-FCP-NEXT: vpternlogq $202, %ymm22, %ymm23, %ymm9 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm9[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm9[1,2],ymm3[3],ymm9[4,5],ymm3[6],ymm9[7],ymm3[8],ymm9[9,10],ymm3[11],ymm9[12,13],ymm3[14],ymm9[15] -; AVX512-FCP-NEXT: vpternlogq $202, %ymm21, %ymm20, %ymm0 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm0[2,3,0,1] -; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm0 = ymm5[0],ymm0[1,2],ymm5[3],ymm0[4,5],ymm5[6],ymm0[7],ymm5[8],ymm0[9,10],ymm5[11],ymm0[12,13],ymm5[14],ymm0[15] -; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm0, %ymm0 +; AVX512-FCP-NEXT: vpternlogq $226, %ymm23, %ymm13, %ymm11 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm11[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm11[1,2],ymm3[3],ymm11[4,5],ymm3[6],ymm11[7],ymm3[8],ymm11[9,10],ymm3[11],ymm11[12,13],ymm3[14],ymm11[15] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] +; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm3 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm15[0,1],xmm5[2],xmm15[3,4],xmm5[5],xmm15[6,7] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm5 = [4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] +; AVX512-FCP-NEXT: vpshufb %xmm5, %xmm4, %xmm4 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] +; AVX512-FCP-NEXT: vpternlogq $226, %ymm24, %ymm0, %ymm12 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm12[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm4 = ymm4[0],ymm12[1,2],ymm4[3],ymm12[4,5],ymm4[6],ymm12[7],ymm4[8],ymm12[9,10],ymm4[11],ymm12[12,13],ymm4[14],ymm12[15] +; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm4, %ymm4 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm10[1],xmm1[2,3],xmm10[4],xmm1[5,6],xmm10[7] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [0,1,2,3,0,1,6,7,12,13,2,3,8,9,14,15] +; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm1, %xmm1 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm1 +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm4[0,1,2,3,4],ymm1[5,6,7] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1 +; AVX512-FCP-NEXT: vpternlogq $202, %ymm21, %ymm22, %ymm13 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm13[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm13[1,2],ymm3[3],ymm13[4,5],ymm3[6],ymm13[7],ymm3[8],ymm13[9,10],ymm3[11],ymm13[12,13],ymm3[14],ymm13[15] +; AVX512-FCP-NEXT: vmovdqa64 %xmm25, %xmm4 +; AVX512-FCP-NEXT: vmovdqa64 %xmm26, %xmm7 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1],xmm7[2],xmm4[3,4],xmm7[5],xmm4[6,7] +; AVX512-FCP-NEXT: vpshufb %xmm5, %xmm4, %xmm4 +; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm3 +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] +; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] +; AVX512-FCP-NEXT: vpternlogq $202, %ymm20, %ymm18, %ymm0 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm0[2,3,0,1] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} ymm0 = ymm4[0],ymm0[1,2],ymm4[3],ymm0[4,5],ymm4[6],ymm0[7],ymm4[8],ymm0[9,10],ymm4[11],ymm0[12,13],ymm4[14],ymm0[15] +; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm0, %ymm0 ; AVX512-FCP-NEXT: vmovdqa64 %xmm27, %xmm4 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm7[0],xmm4[1],xmm7[2,3],xmm4[4],xmm7[5,6],xmm4[7] +; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0],xmm8[1],xmm4[2,3],xmm8[4],xmm4[5,6],xmm8[7] ; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm4, %xmm4 ; AVX512-FCP-NEXT: vinserti128 $1, %xmm4, %ymm0, %ymm4 ; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3,4],ymm4[5,6,7] -; AVX512-FCP-NEXT: vmovdqa64 %xmm25, %xmm4 -; AVX512-FCP-NEXT: vmovdqa64 %xmm26, %xmm5 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1],xmm5[2],xmm4[3,4],xmm5[5],xmm4[6,7] -; AVX512-FCP-NEXT: vpshufb %xmm8, %xmm4, %xmm4 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm0, %zmm4 -; AVX512-FCP-NEXT: vextracti32x4 $2, %zmm4, %xmm4 -; AVX512-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] -; AVX512-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vmovdqa64 %zmm18, (%rsi) +; AVX512-FCP-NEXT: vmovdqa64 %zmm17, (%rsi) ; AVX512-FCP-NEXT: vmovdqa64 %zmm16, 64(%rsi) ; AVX512-FCP-NEXT: vmovdqa64 %zmm19, 64(%rdx) -; AVX512-FCP-NEXT: vmovdqa64 %zmm1, (%rdx) +; AVX512-FCP-NEXT: vmovdqa64 %zmm2, (%rdx) ; AVX512-FCP-NEXT: vmovdqa64 %zmm0, 64(%rcx) -; AVX512-FCP-NEXT: vmovdqa64 %zmm2, (%rcx) +; AVX512-FCP-NEXT: vmovdqa64 %zmm1, (%rcx) ; AVX512-FCP-NEXT: vzeroupper ; AVX512-FCP-NEXT: retq ; ; AVX512DQ-LABEL: load_i16_stride3_vf64: ; AVX512DQ: # %bb.0: ; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm0 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] -; AVX512DQ-NEXT: vmovdqa64 224(%rdi), %ymm20 -; AVX512DQ-NEXT: vmovdqa64 192(%rdi), %ymm21 +; AVX512DQ-NEXT: vmovdqa64 224(%rdi), %ymm18 +; AVX512DQ-NEXT: vmovdqa64 192(%rdi), %ymm20 ; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512DQ-NEXT: vpternlogq $202, %ymm20, %ymm21, %ymm1 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm1[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm3[1],ymm1[2,3],ymm3[4],ymm1[5,6],ymm3[7],ymm1[8],ymm3[9],ymm1[10,11],ymm3[12],ymm1[13,14],ymm3[15] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm3 = [0,1,6,7,12,13,2,3,4,5,14,15,8,9,10,11,16,17,22,23,28,29,18,19,20,21,30,31,24,25,26,27] -; AVX512DQ-NEXT: vpshufb %ymm3, %ymm1, %ymm5 -; AVX512DQ-NEXT: vmovdqa 272(%rdi), %xmm8 +; AVX512DQ-NEXT: vpternlogq $202, %ymm18, %ymm20, %ymm1 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm2 = ymm1[0],ymm2[1],ymm1[2,3],ymm2[4],ymm1[5,6],ymm2[7],ymm1[8],ymm2[9],ymm1[10,11],ymm2[12],ymm1[13,14],ymm2[15] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm7 = [0,1,6,7,12,13,2,3,4,5,14,15,8,9,10,11,16,17,22,23,28,29,18,19,20,21,30,31,24,25,26,27] +; AVX512DQ-NEXT: vpshufb %ymm7, %ymm2, %ymm5 +; AVX512DQ-NEXT: vmovdqa 272(%rdi), %xmm1 ; AVX512DQ-NEXT: vmovdqa 256(%rdi), %xmm2 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm6 = xmm2[0,1],xmm8[2],xmm2[3,4],xmm8[5],xmm2[6,7] -; AVX512DQ-NEXT: vmovdqa %xmm2, %xmm14 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm9 = [4,5,14,15,0,1,2,3,8,9,14,15,4,5,10,11] -; AVX512DQ-NEXT: vpshufb %xmm9, %xmm6, %xmm6 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm6 = xmm2[0,1],xmm1[2],xmm2[3,4],xmm1[5],xmm2[6,7] +; AVX512DQ-NEXT: vmovdqa %xmm2, %xmm3 +; AVX512DQ-NEXT: vmovdqa64 %xmm1, %xmm19 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm13 = [4,5,14,15,0,1,2,3,8,9,14,15,4,5,10,11] +; AVX512DQ-NEXT: vpshufb %xmm13, %xmm6, %xmm6 ; AVX512DQ-NEXT: vinserti128 $1, %xmm6, %ymm0, %ymm6 ; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm6 = ymm5[0,1,2],ymm6[3,4,5,6,7],ymm5[8,9,10],ymm6[11,12,13,14,15] ; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm5 = xmm5[0,1,2,3,6,5,4,7] ; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm5 = ymm5[0,1,2,3],ymm6[4,5,6,7] -; AVX512DQ-NEXT: vmovdqa64 320(%rdi), %ymm22 -; AVX512DQ-NEXT: vmovdqa64 352(%rdi), %ymm23 -; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm6 -; AVX512DQ-NEXT: vpternlogq $202, %ymm22, %ymm23, %ymm6 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm6[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm6 = ymm6[0],ymm7[1],ymm6[2,3],ymm7[4],ymm6[5,6],ymm7[7],ymm6[8],ymm7[9],ymm6[10,11],ymm7[12],ymm6[13,14],ymm7[15] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm11 = [0,1,6,7,12,13,2,3,8,9,14,15,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] -; AVX512DQ-NEXT: vpshufb %ymm11, %ymm6, %ymm12 +; AVX512DQ-NEXT: vmovdqa64 320(%rdi), %ymm21 +; AVX512DQ-NEXT: vmovdqa64 352(%rdi), %ymm22 +; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm8 +; AVX512DQ-NEXT: vpternlogq $202, %ymm21, %ymm22, %ymm8 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm9 = ymm8[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm8 = ymm8[0],ymm9[1],ymm8[2,3],ymm9[4],ymm8[5,6],ymm9[7],ymm8[8],ymm9[9],ymm8[10,11],ymm9[12],ymm8[13,14],ymm9[15] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm10 = [0,1,6,7,12,13,2,3,8,9,14,15,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] +; AVX512DQ-NEXT: vpshufb %ymm10, %ymm8, %ymm11 ; AVX512DQ-NEXT: vmovdqa 304(%rdi), %xmm1 ; AVX512DQ-NEXT: vmovdqa 288(%rdi), %xmm2 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm13 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] ; AVX512DQ-NEXT: vmovdqa %xmm2, %xmm4 -; AVX512DQ-NEXT: vmovdqa %xmm1, %xmm6 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm15 = [0,1,6,7,12,13,2,3,8,9,14,15,12,13,14,15] -; AVX512DQ-NEXT: vpshufb %xmm15, %xmm13, %xmm13 -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm12 = ymm13[0,1,2],ymm12[3,4,5,6,7] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm12, %zmm5, %zmm16 -; AVX512DQ-NEXT: vmovdqa64 128(%rdi), %ymm24 -; AVX512DQ-NEXT: vmovdqa 160(%rdi), %ymm13 +; AVX512DQ-NEXT: vmovdqa %xmm1, %xmm8 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm14 = [0,1,6,7,12,13,2,3,8,9,14,15,12,13,14,15] +; AVX512DQ-NEXT: vpshufb %xmm14, %xmm12, %xmm12 +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm11 = ymm12[0,1,2],ymm11[3,4,5,6,7] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm11, %zmm5, %zmm16 +; AVX512DQ-NEXT: vmovdqa64 128(%rdi), %ymm23 +; AVX512DQ-NEXT: vmovdqa 160(%rdi), %ymm11 ; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm5 -; AVX512DQ-NEXT: vpternlogq $202, %ymm24, %ymm13, %ymm5 +; AVX512DQ-NEXT: vpternlogq $202, %ymm23, %ymm11, %ymm5 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm12 = ymm5[2,3,0,1] ; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm5 = ymm5[0],ymm12[1],ymm5[2,3],ymm12[4],ymm5[5,6],ymm12[7],ymm5[8],ymm12[9],ymm5[10,11],ymm12[12],ymm5[13,14],ymm12[15] -; AVX512DQ-NEXT: vpshufb %ymm11, %ymm5, %ymm5 -; AVX512DQ-NEXT: vmovdqa 112(%rdi), %xmm11 -; AVX512DQ-NEXT: vmovdqa 96(%rdi), %xmm12 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm10 = xmm12[0],xmm11[1],xmm12[2,3],xmm11[4],xmm12[5,6],xmm11[7] -; AVX512DQ-NEXT: vpshufb %xmm15, %xmm10, %xmm10 -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm1 = ymm10[0,1,2],ymm5[3,4,5,6,7] -; AVX512DQ-NEXT: vmovdqa64 (%rdi), %ymm17 -; AVX512DQ-NEXT: vmovdqa 32(%rdi), %ymm5 +; AVX512DQ-NEXT: vpshufb %ymm10, %ymm5, %ymm10 +; AVX512DQ-NEXT: vmovdqa 112(%rdi), %xmm15 +; AVX512DQ-NEXT: vmovdqa 96(%rdi), %xmm5 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm12 = xmm5[0],xmm15[1],xmm5[2,3],xmm15[4],xmm5[5,6],xmm15[7] +; AVX512DQ-NEXT: vpshufb %xmm14, %xmm12, %xmm12 +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm6 = ymm12[0,1,2],ymm10[3,4,5,6,7] +; AVX512DQ-NEXT: vmovdqa64 (%rdi), %ymm24 +; AVX512DQ-NEXT: vmovdqa 32(%rdi), %ymm12 ; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm10 -; AVX512DQ-NEXT: vpternlogq $202, %ymm5, %ymm17, %ymm10 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm15 = ymm10[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm10 = ymm10[0],ymm15[1],ymm10[2,3],ymm15[4],ymm10[5,6],ymm15[7],ymm10[8],ymm15[9],ymm10[10,11],ymm15[12],ymm10[13,14],ymm15[15] -; AVX512DQ-NEXT: vpshufb %ymm3, %ymm10, %ymm2 +; AVX512DQ-NEXT: vpternlogq $202, %ymm12, %ymm24, %ymm10 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm10[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm10[0],ymm1[1],ymm10[2,3],ymm1[4],ymm10[5,6],ymm1[7],ymm10[8],ymm1[9],ymm10[10,11],ymm1[12],ymm10[13,14],ymm1[15] +; AVX512DQ-NEXT: vpshufb %ymm7, %ymm1, %ymm7 ; AVX512DQ-NEXT: vmovdqa 80(%rdi), %xmm10 -; AVX512DQ-NEXT: vmovdqa 64(%rdi), %xmm15 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm3 = xmm15[0,1],xmm10[2],xmm15[3,4],xmm10[5],xmm15[6,7] -; AVX512DQ-NEXT: vpshufb %xmm9, %xmm3, %xmm3 -; AVX512DQ-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm3 = ymm2[0,1,2],ymm3[3,4,5,6,7],ymm2[8,9,10],ymm3[11,12,13,14,15] -; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,6,5,4,7] -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm2 = ymm2[0,1,2,3],ymm3[4,5,6,7] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm18 -; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512DQ-NEXT: vpternlogq $202, %ymm23, %ymm22, %ymm1 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm2[2],ymm1[3,4],ymm2[5],ymm1[6,7,8,9],ymm2[10],ymm1[11,12],ymm2[13],ymm1[14,15] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm2 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm1, %ymm1 -; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm28 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0,1],xmm6[2],xmm4[3,4],xmm6[5],xmm4[6,7] -; AVX512DQ-NEXT: vmovdqa64 %xmm6, %xmm25 +; AVX512DQ-NEXT: vmovdqa 64(%rdi), %xmm1 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm2 = xmm1[0,1],xmm10[2],xmm1[3,4],xmm10[5],xmm1[6,7] +; AVX512DQ-NEXT: vpshufb %xmm13, %xmm2, %xmm2 +; AVX512DQ-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm2 = ymm7[0,1,2],ymm2[3,4,5,6,7],ymm7[8,9,10],ymm2[11,12,13,14,15] +; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm7 = xmm7[0,1,2,3,6,5,4,7] +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm2 = ymm7[0,1,2,3],ymm2[4,5,6,7] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm6, %zmm2, %zmm17 +; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm2 +; AVX512DQ-NEXT: vpternlogq $202, %ymm22, %ymm21, %ymm2 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm6 = ymm2[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm6[2],ymm2[3,4],ymm6[5],ymm2[6,7,8,9],ymm6[10],ymm2[11,12],ymm6[13],ymm2[14,15] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm9 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] +; AVX512DQ-NEXT: vpshufb %ymm9, %ymm2, %ymm2 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm7 = xmm4[0,1],xmm8[2],xmm4[3,4],xmm8[5],xmm4[6,7] +; AVX512DQ-NEXT: vmovdqa64 %xmm8, %xmm25 ; AVX512DQ-NEXT: vmovdqa64 %xmm4, %xmm26 ; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm6 = [2,3,8,9,14,15,4,5,10,11,10,11,10,11,10,11] -; AVX512DQ-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1,2,3,4],xmm1[5,6,7] -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3],ymm1[4,5,6,7] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm9 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] -; AVX512DQ-NEXT: vmovdqa %ymm9, %ymm1 -; AVX512DQ-NEXT: vpternlogq $202, %ymm21, %ymm20, %ymm1 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm1[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm4[2],ymm1[3,4],ymm4[5],ymm1[6,7,8,9],ymm4[10],ymm1[11,12],ymm4[13],ymm1[14,15] +; AVX512DQ-NEXT: vpshufb %xmm6, %xmm7, %xmm7 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm7 = xmm7[0,1,2,3,4],xmm2[5,6,7] +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm7 = ymm7[0,1,2,3],ymm2[4,5,6,7] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm13 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] +; AVX512DQ-NEXT: vmovdqa %ymm13, %ymm2 +; AVX512DQ-NEXT: vpternlogq $202, %ymm20, %ymm18, %ymm2 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm2[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm4[2],ymm2[3,4],ymm4[5],ymm2[6,7,8,9],ymm4[10],ymm2[11,12],ymm4[13],ymm2[14,15] ; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm4 = [2,3,8,9,14,15,4,5,12,13,10,11,0,1,6,7,18,19,24,25,30,31,20,21,28,29,26,27,16,17,22,23] -; AVX512DQ-NEXT: vpshufb %ymm4, %ymm1, %ymm1 -; AVX512DQ-NEXT: vmovdqa %xmm14, %xmm7 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm14 = xmm8[0,1],xmm14[2],xmm8[3,4],xmm14[5],xmm8[6,7] -; AVX512DQ-NEXT: vmovdqa64 %xmm8, %xmm27 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm2 = [4,5,4,5,4,5,4,5,10,11,0,1,6,7,12,13] -; AVX512DQ-NEXT: vpshufb %xmm2, %xmm14, %xmm14 -; AVX512DQ-NEXT: vinserti128 $1, %xmm14, %ymm0, %ymm14 -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm14 = ymm1[0,1,2],ymm14[3,4,5,6,7],ymm1[8,9,10],ymm14[11,12,13,14,15] -; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm1 = xmm1[0,1,2,3,5,6,7,4] -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3],ymm14[4,5,6,7] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm19 -; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512DQ-NEXT: vpternlogq $202, %ymm13, %ymm24, %ymm1 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm1[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm3[2],ymm1[3,4],ymm3[5],ymm1[6,7,8,9],ymm3[10],ymm1[11,12],ymm3[13],ymm1[14,15] -; AVX512DQ-NEXT: vmovdqa64 %ymm28, %ymm3 -; AVX512DQ-NEXT: vpshufb %ymm3, %ymm1, %ymm1 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm3 = xmm12[0,1],xmm11[2],xmm12[3,4],xmm11[5],xmm12[6,7] -; AVX512DQ-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1,2,3,4],xmm1[5,6,7] -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm1 = ymm3[0,1,2,3],ymm1[4,5,6,7] -; AVX512DQ-NEXT: vmovdqa %ymm9, %ymm3 -; AVX512DQ-NEXT: vpternlogq $202, %ymm17, %ymm5, %ymm3 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm6 = ymm3[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0,1],ymm6[2],ymm3[3,4],ymm6[5],ymm3[6,7,8,9],ymm6[10],ymm3[11,12],ymm6[13],ymm3[14,15] -; AVX512DQ-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm10[0,1],xmm15[2],xmm10[3,4],xmm15[5],xmm10[6,7] -; AVX512DQ-NEXT: vpshufb %xmm2, %xmm4, %xmm2 -; AVX512DQ-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm2 = ymm3[0,1,2],ymm2[3,4,5,6,7],ymm3[8,9,10],ymm2[11,12,13,14,15] -; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm3 = xmm3[0,1,2,3,5,6,7,4] -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm2 = ymm3[0,1,2,3],ymm2[4,5,6,7] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 -; AVX512DQ-NEXT: vpternlogq $226, %ymm24, %ymm9, %ymm13 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm13[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0],ymm13[1,2],ymm2[3],ymm13[4,5],ymm2[6],ymm13[7],ymm2[8],ymm13[9,10],ymm2[11],ymm13[12,13],ymm2[14],ymm13[15] -; AVX512DQ-NEXT: vpternlogq $226, %ymm17, %ymm0, %ymm5 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm5[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm5[1,2],ymm3[3],ymm5[4,5],ymm3[6],ymm5[7],ymm3[8],ymm5[9,10],ymm3[11],ymm5[12,13],ymm3[14],ymm5[15] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm4 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] -; AVX512DQ-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm5 = xmm15[0],xmm10[1],xmm15[2,3],xmm10[4],xmm15[5,6],xmm10[7] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm6 = [0,1,2,3,0,1,6,7,12,13,2,3,8,9,14,15] -; AVX512DQ-NEXT: vpshufb %xmm6, %xmm5, %xmm5 -; AVX512DQ-NEXT: vinserti128 $1, %xmm5, %ymm0, %ymm5 -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3,4],ymm5[5,6,7] ; AVX512DQ-NEXT: vpshufb %ymm4, %ymm2, %ymm2 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm5 = xmm11[0,1],xmm12[2],xmm11[3,4],xmm12[5],xmm11[6,7] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm8 = [4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] -; AVX512DQ-NEXT: vpshufb %xmm8, %xmm5, %xmm5 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm5, %zmm3, %zmm5 -; AVX512DQ-NEXT: vextracti32x4 $2, %zmm5, %xmm5 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm5 = xmm5[0,1,2,3,4],xmm2[5,6,7] -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm2 = ymm5[0,1,2,3],ymm2[4,5,6,7] +; AVX512DQ-NEXT: vmovdqa64 %xmm19, %xmm8 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm14 = xmm8[0,1],xmm3[2],xmm8[3,4],xmm3[5],xmm8[6,7] +; AVX512DQ-NEXT: vmovdqa64 %xmm3, %xmm27 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [4,5,4,5,4,5,4,5,10,11,0,1,6,7,12,13] +; AVX512DQ-NEXT: vpshufb %xmm3, %xmm14, %xmm14 +; AVX512DQ-NEXT: vinserti128 $1, %xmm14, %ymm0, %ymm14 +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm14 = ymm2[0,1,2],ymm14[3,4,5,6,7],ymm2[8,9,10],ymm14[11,12,13,14,15] +; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,5,6,7,4] +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm2 = ymm2[0,1,2,3],ymm14[4,5,6,7] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm7, %zmm2, %zmm19 +; AVX512DQ-NEXT: vmovdqa %ymm0, %ymm2 +; AVX512DQ-NEXT: vpternlogq $202, %ymm11, %ymm23, %ymm2 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm2[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm7[2],ymm2[3,4],ymm7[5],ymm2[6,7,8,9],ymm7[10],ymm2[11,12],ymm7[13],ymm2[14,15] +; AVX512DQ-NEXT: vpshufb %ymm9, %ymm2, %ymm2 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm7 = xmm5[0,1],xmm15[2],xmm5[3,4],xmm15[5],xmm5[6,7] +; AVX512DQ-NEXT: vpshufb %xmm6, %xmm7, %xmm6 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm6 = xmm6[0,1,2,3,4],xmm2[5,6,7] +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm2 = ymm6[0,1,2,3],ymm2[4,5,6,7] +; AVX512DQ-NEXT: vmovdqa %ymm13, %ymm6 +; AVX512DQ-NEXT: vpternlogq $202, %ymm24, %ymm12, %ymm6 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm6[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm6 = ymm6[0,1],ymm7[2],ymm6[3,4],ymm7[5],ymm6[6,7,8,9],ymm7[10],ymm6[11,12],ymm7[13],ymm6[14,15] +; AVX512DQ-NEXT: vpshufb %ymm4, %ymm6, %ymm4 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm6 = xmm10[0,1],xmm1[2],xmm10[3,4],xmm1[5],xmm10[6,7] +; AVX512DQ-NEXT: vpshufb %xmm3, %xmm6, %xmm3 +; AVX512DQ-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm3 = ymm4[0,1,2],ymm3[3,4,5,6,7],ymm4[8,9,10],ymm3[11,12,13,14,15] +; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,5,6,7,4] +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] ; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 -; AVX512DQ-NEXT: vpternlogq $202, %ymm22, %ymm23, %ymm9 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm9[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm9[1,2],ymm3[3],ymm9[4,5],ymm3[6],ymm9[7],ymm3[8],ymm9[9,10],ymm3[11],ymm9[12,13],ymm3[14],ymm9[15] -; AVX512DQ-NEXT: vpternlogq $202, %ymm21, %ymm20, %ymm0 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm5 = ymm0[2,3,0,1] -; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm0 = ymm5[0],ymm0[1,2],ymm5[3],ymm0[4,5],ymm5[6],ymm0[7],ymm5[8],ymm0[9,10],ymm5[11],ymm0[12,13],ymm5[14],ymm0[15] -; AVX512DQ-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512DQ-NEXT: vpshufb %ymm4, %ymm0, %ymm0 +; AVX512DQ-NEXT: vpternlogq $226, %ymm23, %ymm13, %ymm11 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm11[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm11[1,2],ymm3[3],ymm11[4,5],ymm3[6],ymm11[7],ymm3[8],ymm11[9,10],ymm3[11],ymm11[12,13],ymm3[14],ymm11[15] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm11 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] +; AVX512DQ-NEXT: vpshufb %ymm11, %ymm3, %ymm3 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm15[0,1],xmm5[2],xmm15[3,4],xmm5[5],xmm15[6,7] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm5 = [4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] +; AVX512DQ-NEXT: vpshufb %xmm5, %xmm4, %xmm4 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] +; AVX512DQ-NEXT: vpternlogq $226, %ymm24, %ymm0, %ymm12 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm12[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm4 = ymm4[0],ymm12[1,2],ymm4[3],ymm12[4,5],ymm4[6],ymm12[7],ymm4[8],ymm12[9,10],ymm4[11],ymm12[12,13],ymm4[14],ymm12[15] +; AVX512DQ-NEXT: vpshufb %ymm11, %ymm4, %ymm4 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm10[1],xmm1[2,3],xmm10[4],xmm1[5,6],xmm10[7] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm6 = [0,1,2,3,0,1,6,7,12,13,2,3,8,9,14,15] +; AVX512DQ-NEXT: vpshufb %xmm6, %xmm1, %xmm1 +; AVX512DQ-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm1 +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm1 = ymm4[0,1,2,3,4],ymm1[5,6,7] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1 +; AVX512DQ-NEXT: vpternlogq $202, %ymm21, %ymm22, %ymm13 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm13[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm13[1,2],ymm3[3],ymm13[4,5],ymm3[6],ymm13[7],ymm3[8],ymm13[9,10],ymm3[11],ymm13[12,13],ymm3[14],ymm13[15] +; AVX512DQ-NEXT: vmovdqa64 %xmm25, %xmm4 +; AVX512DQ-NEXT: vmovdqa64 %xmm26, %xmm7 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1],xmm7[2],xmm4[3,4],xmm7[5],xmm4[6,7] +; AVX512DQ-NEXT: vpshufb %xmm5, %xmm4, %xmm4 +; AVX512DQ-NEXT: vpshufb %ymm11, %ymm3, %ymm3 +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] +; AVX512DQ-NEXT: vpternlogq $202, %ymm20, %ymm18, %ymm0 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm0[2,3,0,1] +; AVX512DQ-NEXT: vpblendw {{.*#+}} ymm0 = ymm4[0],ymm0[1,2],ymm4[3],ymm0[4,5],ymm4[6],ymm0[7],ymm4[8],ymm0[9,10],ymm4[11],ymm0[12,13],ymm4[14],ymm0[15] +; AVX512DQ-NEXT: vpshufb %ymm11, %ymm0, %ymm0 ; AVX512DQ-NEXT: vmovdqa64 %xmm27, %xmm4 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm7[0],xmm4[1],xmm7[2,3],xmm4[4],xmm7[5,6],xmm4[7] +; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0],xmm8[1],xmm4[2,3],xmm8[4],xmm4[5,6],xmm8[7] ; AVX512DQ-NEXT: vpshufb %xmm6, %xmm4, %xmm4 ; AVX512DQ-NEXT: vinserti128 $1, %xmm4, %ymm0, %ymm4 ; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3,4],ymm4[5,6,7] -; AVX512DQ-NEXT: vmovdqa64 %xmm25, %xmm4 -; AVX512DQ-NEXT: vmovdqa64 %xmm26, %xmm5 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1],xmm5[2],xmm4[3,4],xmm5[5],xmm4[6,7] -; AVX512DQ-NEXT: vpshufb %xmm8, %xmm4, %xmm4 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm4, %zmm0, %zmm4 -; AVX512DQ-NEXT: vextracti32x4 $2, %zmm4, %xmm4 -; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] -; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] ; AVX512DQ-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 -; AVX512DQ-NEXT: vmovdqa64 %zmm18, (%rsi) +; AVX512DQ-NEXT: vmovdqa64 %zmm17, (%rsi) ; AVX512DQ-NEXT: vmovdqa64 %zmm16, 64(%rsi) ; AVX512DQ-NEXT: vmovdqa64 %zmm19, 64(%rdx) -; AVX512DQ-NEXT: vmovdqa64 %zmm1, (%rdx) +; AVX512DQ-NEXT: vmovdqa64 %zmm2, (%rdx) ; AVX512DQ-NEXT: vmovdqa64 %zmm0, 64(%rcx) -; AVX512DQ-NEXT: vmovdqa64 %zmm2, (%rcx) +; AVX512DQ-NEXT: vmovdqa64 %zmm1, (%rcx) ; AVX512DQ-NEXT: vzeroupper ; AVX512DQ-NEXT: retq ; ; AVX512DQ-FCP-LABEL: load_i16_stride3_vf64: ; AVX512DQ-FCP: # %bb.0: ; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535] -; AVX512DQ-FCP-NEXT: vmovdqa64 224(%rdi), %ymm20 -; AVX512DQ-FCP-NEXT: vmovdqa64 192(%rdi), %ymm21 +; AVX512DQ-FCP-NEXT: vmovdqa64 224(%rdi), %ymm18 +; AVX512DQ-FCP-NEXT: vmovdqa64 192(%rdi), %ymm20 ; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm20, %ymm21, %ymm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm1[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm3[1],ymm1[2,3],ymm3[4],ymm1[5,6],ymm3[7],ymm1[8],ymm3[9],ymm1[10,11],ymm3[12],ymm1[13,14],ymm3[15] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm3 = [0,1,6,7,12,13,2,3,4,5,14,15,8,9,10,11,16,17,22,23,28,29,18,19,20,21,30,31,24,25,26,27] -; AVX512DQ-FCP-NEXT: vpshufb %ymm3, %ymm1, %ymm5 -; AVX512DQ-FCP-NEXT: vmovdqa 272(%rdi), %xmm8 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm18, %ymm20, %ymm1 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm1[0],ymm2[1],ymm1[2,3],ymm2[4],ymm1[5,6],ymm2[7],ymm1[8],ymm2[9],ymm1[10,11],ymm2[12],ymm1[13,14],ymm2[15] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm7 = [0,1,6,7,12,13,2,3,4,5,14,15,8,9,10,11,16,17,22,23,28,29,18,19,20,21,30,31,24,25,26,27] +; AVX512DQ-FCP-NEXT: vpshufb %ymm7, %ymm2, %ymm5 +; AVX512DQ-FCP-NEXT: vmovdqa 272(%rdi), %xmm1 ; AVX512DQ-FCP-NEXT: vmovdqa 256(%rdi), %xmm2 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm6 = xmm2[0,1],xmm8[2],xmm2[3,4],xmm8[5],xmm2[6,7] -; AVX512DQ-FCP-NEXT: vmovdqa %xmm2, %xmm14 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [4,5,14,15,0,1,2,3,8,9,14,15,4,5,10,11] -; AVX512DQ-FCP-NEXT: vpshufb %xmm9, %xmm6, %xmm6 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm6 = xmm2[0,1],xmm1[2],xmm2[3,4],xmm1[5],xmm2[6,7] +; AVX512DQ-FCP-NEXT: vmovdqa %xmm2, %xmm3 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm1, %xmm19 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm13 = [4,5,14,15,0,1,2,3,8,9,14,15,4,5,10,11] +; AVX512DQ-FCP-NEXT: vpshufb %xmm13, %xmm6, %xmm6 ; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm6, %ymm0, %ymm6 ; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm6 = ymm5[0,1,2],ymm6[3,4,5,6,7],ymm5[8,9,10],ymm6[11,12,13,14,15] ; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm5 = xmm5[0,1,2,3,6,5,4,7] ; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm5 = ymm5[0,1,2,3],ymm6[4,5,6,7] -; AVX512DQ-FCP-NEXT: vmovdqa64 320(%rdi), %ymm22 -; AVX512DQ-FCP-NEXT: vmovdqa64 352(%rdi), %ymm23 -; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm6 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm22, %ymm23, %ymm6 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm6[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm6 = ymm6[0],ymm7[1],ymm6[2,3],ymm7[4],ymm6[5,6],ymm7[7],ymm6[8],ymm7[9],ymm6[10,11],ymm7[12],ymm6[13,14],ymm7[15] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [0,1,6,7,12,13,2,3,8,9,14,15,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] -; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm6, %ymm12 +; AVX512DQ-FCP-NEXT: vmovdqa64 320(%rdi), %ymm21 +; AVX512DQ-FCP-NEXT: vmovdqa64 352(%rdi), %ymm22 +; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm8 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm21, %ymm22, %ymm8 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm8[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm8 = ymm8[0],ymm9[1],ymm8[2,3],ymm9[4],ymm8[5,6],ymm9[7],ymm8[8],ymm9[9],ymm8[10,11],ymm9[12],ymm8[13,14],ymm9[15] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [0,1,6,7,12,13,2,3,8,9,14,15,4,5,10,11,16,17,22,23,28,29,18,19,24,25,30,31,20,21,26,27] +; AVX512DQ-FCP-NEXT: vpshufb %ymm10, %ymm8, %ymm11 ; AVX512DQ-FCP-NEXT: vmovdqa 304(%rdi), %xmm1 ; AVX512DQ-FCP-NEXT: vmovdqa 288(%rdi), %xmm2 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm13 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm2[0],xmm1[1],xmm2[2,3],xmm1[4],xmm2[5,6],xmm1[7] ; AVX512DQ-FCP-NEXT: vmovdqa %xmm2, %xmm4 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm1, %xmm6 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm15 = [0,1,6,7,12,13,2,3,8,9,14,15,12,13,14,15] -; AVX512DQ-FCP-NEXT: vpshufb %xmm15, %xmm13, %xmm13 -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm12 = ymm13[0,1,2],ymm12[3,4,5,6,7] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm5, %zmm16 -; AVX512DQ-FCP-NEXT: vmovdqa64 128(%rdi), %ymm24 -; AVX512DQ-FCP-NEXT: vmovdqa 160(%rdi), %ymm13 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm1, %xmm8 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm14 = [0,1,6,7,12,13,2,3,8,9,14,15,12,13,14,15] +; AVX512DQ-FCP-NEXT: vpshufb %xmm14, %xmm12, %xmm12 +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm11 = ymm12[0,1,2],ymm11[3,4,5,6,7] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm5, %zmm16 +; AVX512DQ-FCP-NEXT: vmovdqa64 128(%rdi), %ymm23 +; AVX512DQ-FCP-NEXT: vmovdqa 160(%rdi), %ymm11 ; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm5 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm24, %ymm13, %ymm5 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm23, %ymm11, %ymm5 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm5[2,3,0,1] ; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm5 = ymm5[0],ymm12[1],ymm5[2,3],ymm12[4],ymm5[5,6],ymm12[7],ymm5[8],ymm12[9],ymm5[10,11],ymm12[12],ymm5[13,14],ymm12[15] -; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm5, %ymm5 -; AVX512DQ-FCP-NEXT: vmovdqa 112(%rdi), %xmm11 -; AVX512DQ-FCP-NEXT: vmovdqa 96(%rdi), %xmm12 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm10 = xmm12[0],xmm11[1],xmm12[2,3],xmm11[4],xmm12[5,6],xmm11[7] -; AVX512DQ-FCP-NEXT: vpshufb %xmm15, %xmm10, %xmm10 -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm10[0,1,2],ymm5[3,4,5,6,7] -; AVX512DQ-FCP-NEXT: vmovdqa64 (%rdi), %ymm17 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %ymm5 +; AVX512DQ-FCP-NEXT: vpshufb %ymm10, %ymm5, %ymm10 +; AVX512DQ-FCP-NEXT: vmovdqa 112(%rdi), %xmm15 +; AVX512DQ-FCP-NEXT: vmovdqa 96(%rdi), %xmm5 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm12 = xmm5[0],xmm15[1],xmm5[2,3],xmm15[4],xmm5[5,6],xmm15[7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm14, %xmm12, %xmm12 +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm6 = ymm12[0,1,2],ymm10[3,4,5,6,7] +; AVX512DQ-FCP-NEXT: vmovdqa64 (%rdi), %ymm24 +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %ymm12 ; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm10 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm5, %ymm17, %ymm10 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm10[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm10 = ymm10[0],ymm15[1],ymm10[2,3],ymm15[4],ymm10[5,6],ymm15[7],ymm10[8],ymm15[9],ymm10[10,11],ymm15[12],ymm10[13,14],ymm15[15] -; AVX512DQ-FCP-NEXT: vpshufb %ymm3, %ymm10, %ymm2 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm12, %ymm24, %ymm10 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm10[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm10[0],ymm1[1],ymm10[2,3],ymm1[4],ymm10[5,6],ymm1[7],ymm10[8],ymm1[9],ymm10[10,11],ymm1[12],ymm10[13,14],ymm1[15] +; AVX512DQ-FCP-NEXT: vpshufb %ymm7, %ymm1, %ymm7 ; AVX512DQ-FCP-NEXT: vmovdqa 80(%rdi), %xmm10 -; AVX512DQ-FCP-NEXT: vmovdqa 64(%rdi), %xmm15 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm15[0,1],xmm10[2],xmm15[3,4],xmm10[5],xmm15[6,7] -; AVX512DQ-FCP-NEXT: vpshufb %xmm9, %xmm3, %xmm3 -; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm2[0,1,2],ymm3[3,4,5,6,7],ymm2[8,9,10],ymm3[11,12,13,14,15] -; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,6,5,4,7] -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm2[0,1,2,3],ymm3[4,5,6,7] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm18 -; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm23, %ymm22, %ymm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm1[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm2[2],ymm1[3,4],ymm2[5],ymm1[6,7,8,9],ymm2[10],ymm1[11,12],ymm2[13],ymm1[14,15] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm2 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] -; AVX512DQ-FCP-NEXT: vpshufb %ymm2, %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm2, %ymm28 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0,1],xmm6[2],xmm4[3,4],xmm6[5],xmm4[6,7] -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm6, %xmm25 +; AVX512DQ-FCP-NEXT: vmovdqa 64(%rdi), %xmm1 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm2 = xmm1[0,1],xmm10[2],xmm1[3,4],xmm10[5],xmm1[6,7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm13, %xmm2, %xmm2 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm7[0,1,2],ymm2[3,4,5,6,7],ymm7[8,9,10],ymm2[11,12,13,14,15] +; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm7 = xmm7[0,1,2,3,6,5,4,7] +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm7[0,1,2,3],ymm2[4,5,6,7] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm2, %zmm17 +; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm2 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm22, %ymm21, %ymm2 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm2[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm6[2],ymm2[3,4],ymm6[5],ymm2[6,7,8,9],ymm6[10],ymm2[11,12],ymm6[13],ymm2[14,15] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [2,3,8,9,14,15,4,5,10,11,0,1,6,7,12,13,18,19,24,25,30,31,20,21,26,27,16,17,22,23,28,29] +; AVX512DQ-FCP-NEXT: vpshufb %ymm9, %ymm2, %ymm2 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm7 = xmm4[0,1],xmm8[2],xmm4[3,4],xmm8[5],xmm4[6,7] +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm8, %xmm25 ; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm4, %xmm26 ; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [2,3,8,9,14,15,4,5,10,11,10,11,10,11,10,11] -; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1,2,3,4],xmm1[5,6,7] -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3],ymm1[4,5,6,7] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] -; AVX512DQ-FCP-NEXT: vmovdqa %ymm9, %ymm1 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm21, %ymm20, %ymm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm1[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm4[2],ymm1[3,4],ymm4[5],ymm1[6,7,8,9],ymm4[10],ymm1[11,12],ymm4[13],ymm1[14,15] +; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm7, %xmm7 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm7 = xmm7[0,1,2,3,4],xmm2[5,6,7] +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm7 = ymm7[0,1,2,3],ymm2[4,5,6,7] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm13 = [65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535,0,65535,65535] +; AVX512DQ-FCP-NEXT: vmovdqa %ymm13, %ymm2 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm20, %ymm18, %ymm2 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm2[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm4[2],ymm2[3,4],ymm4[5],ymm2[6,7,8,9],ymm4[10],ymm2[11,12],ymm4[13],ymm2[14,15] ; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [2,3,8,9,14,15,4,5,12,13,10,11,0,1,6,7,18,19,24,25,30,31,20,21,28,29,26,27,16,17,22,23] -; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm14, %xmm7 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm14 = xmm8[0,1],xmm14[2],xmm8[3,4],xmm14[5],xmm8[6,7] -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm8, %xmm27 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm2 = [4,5,4,5,4,5,4,5,10,11,0,1,6,7,12,13] -; AVX512DQ-FCP-NEXT: vpshufb %xmm2, %xmm14, %xmm14 -; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm14, %ymm0, %ymm14 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm14 = ymm1[0,1,2],ymm14[3,4,5,6,7],ymm1[8,9,10],ymm14[11,12,13,14,15] -; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm1 = xmm1[0,1,2,3,5,6,7,4] -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0,1,2,3],ymm14[4,5,6,7] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm19 -; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm1 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm13, %ymm24, %ymm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm1[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0,1],ymm3[2],ymm1[3,4],ymm3[5],ymm1[6,7,8,9],ymm3[10],ymm1[11,12],ymm3[13],ymm1[14,15] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm28, %ymm3 -; AVX512DQ-FCP-NEXT: vpshufb %ymm3, %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm12[0,1],xmm11[2],xmm12[3,4],xmm11[5],xmm12[6,7] -; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm3, %xmm3 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1,2,3,4],xmm1[5,6,7] -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm3[0,1,2,3],ymm1[4,5,6,7] -; AVX512DQ-FCP-NEXT: vmovdqa %ymm9, %ymm3 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm17, %ymm5, %ymm3 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm3[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0,1],ymm6[2],ymm3[3,4],ymm6[5],ymm3[6,7,8,9],ymm6[10],ymm3[11,12],ymm6[13],ymm3[14,15] -; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm10[0,1],xmm15[2],xmm10[3,4],xmm15[5],xmm10[6,7] -; AVX512DQ-FCP-NEXT: vpshufb %xmm2, %xmm4, %xmm2 -; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm3[0,1,2],ymm2[3,4,5,6,7],ymm3[8,9,10],ymm2[11,12,13,14,15] -; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm3 = xmm3[0,1,2,3,5,6,7,4] -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm3[0,1,2,3],ymm2[4,5,6,7] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 -; AVX512DQ-FCP-NEXT: vpternlogq $226, %ymm24, %ymm9, %ymm13 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm13[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0],ymm13[1,2],ymm2[3],ymm13[4,5],ymm2[6],ymm13[7],ymm2[8],ymm13[9,10],ymm2[11],ymm13[12,13],ymm2[14],ymm13[15] -; AVX512DQ-FCP-NEXT: vpternlogq $226, %ymm17, %ymm0, %ymm5 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm5[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm5[1,2],ymm3[3],ymm5[4,5],ymm3[6],ymm5[7],ymm3[8],ymm5[9,10],ymm3[11],ymm5[12,13],ymm3[14],ymm5[15] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] -; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm5 = xmm15[0],xmm10[1],xmm15[2,3],xmm10[4],xmm15[5,6],xmm10[7] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [0,1,2,3,0,1,6,7,12,13,2,3,8,9,14,15] -; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm5, %xmm5 -; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm5, %ymm0, %ymm5 -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3,4],ymm5[5,6,7] ; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm2, %ymm2 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm5 = xmm11[0,1],xmm12[2],xmm11[3,4],xmm12[5],xmm11[6,7] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] -; AVX512DQ-FCP-NEXT: vpshufb %xmm8, %xmm5, %xmm5 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm3, %zmm5 -; AVX512DQ-FCP-NEXT: vextracti32x4 $2, %zmm5, %xmm5 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm5 = xmm5[0,1,2,3,4],xmm2[5,6,7] -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm5[0,1,2,3],ymm2[4,5,6,7] +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm19, %xmm8 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm14 = xmm8[0,1],xmm3[2],xmm8[3,4],xmm3[5],xmm8[6,7] +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm3, %xmm27 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [4,5,4,5,4,5,4,5,10,11,0,1,6,7,12,13] +; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm14, %xmm14 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm14, %ymm0, %ymm14 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm14 = ymm2[0,1,2],ymm14[3,4,5,6,7],ymm2[8,9,10],ymm14[11,12,13,14,15] +; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,5,6,7,4] +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm2[0,1,2,3],ymm14[4,5,6,7] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm2, %zmm19 +; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, %ymm2 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm11, %ymm23, %ymm2 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm2[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0,1],ymm7[2],ymm2[3,4],ymm7[5],ymm2[6,7,8,9],ymm7[10],ymm2[11,12],ymm7[13],ymm2[14,15] +; AVX512DQ-FCP-NEXT: vpshufb %ymm9, %ymm2, %ymm2 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm7 = xmm5[0,1],xmm15[2],xmm5[3,4],xmm15[5],xmm5[6,7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm7, %xmm6 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm6 = xmm6[0,1,2,3,4],xmm2[5,6,7] +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm2 = ymm6[0,1,2,3],ymm2[4,5,6,7] +; AVX512DQ-FCP-NEXT: vmovdqa %ymm13, %ymm6 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm24, %ymm12, %ymm6 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm6[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm6 = ymm6[0,1],ymm7[2],ymm6[3,4],ymm7[5],ymm6[6,7,8,9],ymm7[10],ymm6[11,12],ymm7[13],ymm6[14,15] +; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm6, %ymm4 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm6 = xmm10[0,1],xmm1[2],xmm10[3,4],xmm1[5],xmm10[6,7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm6, %xmm3 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm3 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm4[0,1,2],ymm3[3,4,5,6,7],ymm4[8,9,10],ymm3[11,12,13,14,15] +; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,5,6,7,4] +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm22, %ymm23, %ymm9 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm9[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm9[1,2],ymm3[3],ymm9[4,5],ymm3[6],ymm9[7],ymm3[8],ymm9[9,10],ymm3[11],ymm9[12,13],ymm3[14],ymm9[15] -; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm21, %ymm20, %ymm0 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm0[2,3,0,1] -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm0 = ymm5[0],ymm0[1,2],ymm5[3],ymm0[4,5],ymm5[6],ymm0[7],ymm5[8],ymm0[9,10],ymm5[11],ymm0[12,13],ymm5[14],ymm0[15] -; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm3 -; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm0, %ymm0 +; AVX512DQ-FCP-NEXT: vpternlogq $226, %ymm23, %ymm13, %ymm11 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm11[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm11[1,2],ymm3[3],ymm11[4,5],ymm3[6],ymm11[7],ymm3[8],ymm11[9,10],ymm3[11],ymm11[12,13],ymm3[14],ymm11[15] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [4,5,10,11,0,1,6,7,12,13,2,3,8,9,14,15,20,21,26,27,16,17,22,23,28,29,18,19,24,25,30,31] +; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm3 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm15[0,1],xmm5[2],xmm15[3,4],xmm5[5],xmm15[6,7] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm5 = [4,5,10,11,0,1,6,7,12,13,14,15,0,1,2,3] +; AVX512DQ-FCP-NEXT: vpshufb %xmm5, %xmm4, %xmm4 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] +; AVX512DQ-FCP-NEXT: vpternlogq $226, %ymm24, %ymm0, %ymm12 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm12[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm4 = ymm4[0],ymm12[1,2],ymm4[3],ymm12[4,5],ymm4[6],ymm12[7],ymm4[8],ymm12[9,10],ymm4[11],ymm12[12,13],ymm4[14],ymm12[15] +; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm4, %ymm4 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm10[1],xmm1[2,3],xmm10[4],xmm1[5,6],xmm10[7] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [0,1,2,3,0,1,6,7,12,13,2,3,8,9,14,15] +; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm1, %xmm1 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm1 +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm1 = ymm4[0,1,2,3,4],ymm1[5,6,7] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1 +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm21, %ymm22, %ymm13 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm13[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm13[1,2],ymm3[3],ymm13[4,5],ymm3[6],ymm13[7],ymm3[8],ymm13[9,10],ymm3[11],ymm13[12,13],ymm3[14],ymm13[15] +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm25, %xmm4 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm26, %xmm7 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1],xmm7[2],xmm4[3,4],xmm7[5],xmm4[6,7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm5, %xmm4, %xmm4 +; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm3 +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] +; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] +; AVX512DQ-FCP-NEXT: vpternlogq $202, %ymm20, %ymm18, %ymm0 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm0[2,3,0,1] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} ymm0 = ymm4[0],ymm0[1,2],ymm4[3],ymm0[4,5],ymm4[6],ymm0[7],ymm4[8],ymm0[9,10],ymm4[11],ymm0[12,13],ymm4[14],ymm0[15] +; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm0, %ymm0 ; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm27, %xmm4 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm7[0],xmm4[1],xmm7[2,3],xmm4[4],xmm7[5,6],xmm4[7] +; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0],xmm8[1],xmm4[2,3],xmm8[4],xmm4[5,6],xmm8[7] ; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm4, %xmm4 ; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm4, %ymm0, %ymm4 ; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0,1,2,3,4],ymm4[5,6,7] -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm25, %xmm4 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm26, %xmm5 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1],xmm5[2],xmm4[3,4],xmm5[5],xmm4[6,7] -; AVX512DQ-FCP-NEXT: vpshufb %xmm8, %xmm4, %xmm4 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm0, %zmm4 -; AVX512DQ-FCP-NEXT: vextracti32x4 $2, %zmm4, %xmm4 -; AVX512DQ-FCP-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0,1,2,3,4],xmm3[5,6,7] -; AVX512DQ-FCP-NEXT: vpblendd {{.*#+}} ymm3 = ymm4[0,1,2,3],ymm3[4,5,6,7] ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm18, (%rsi) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm17, (%rsi) ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm16, 64(%rsi) ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm19, 64(%rdx) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm1, (%rdx) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm2, (%rdx) ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm0, 64(%rcx) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm2, (%rcx) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm1, (%rcx) ; AVX512DQ-FCP-NEXT: vzeroupper ; AVX512DQ-FCP-NEXT: retq ; diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-7.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-7.ll index 8b6ba51506ab..8091afbbfd70 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-7.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-7.ll @@ -1246,29 +1246,28 @@ define void @store_i8_stride7_vf8(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vecp ; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [1,3,5,7,1,3,5,7] -; AVX512BW-FCP-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512BW-FCP-NEXT: vpermd %ymm2, %ymm0, %ymm0 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm0[1,5,9,13],zero,zero,zero,ymm0[2,6,10,14],zero,zero,zero,ymm0[19,23,27,31],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm3 = [1,3,5,0,5,1,3,0] -; AVX512BW-FCP-NEXT: vpermd %ymm1, %ymm3, %ymm3 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[0,4,8],zero,zero,zero,zero,ymm3[1,5,9],zero,zero,zero,zero,ymm3[2,6,18],zero,zero,zero,zero,ymm3[23,27,19],zero,zero,zero,zero,zero,zero,zero,zero +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[0,8],zero,zero,zero,zero,zero,ymm2[1,9],zero,zero,zero,zero,zero,ymm2[2,10,18,26],zero,zero,zero,zero,zero,ymm2[19,27],zero,zero,zero,zero,zero,ymm2[20,28] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm2[2,3,0,1] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = zero,zero,ymm3[0,8],zero,zero,zero,zero,zero,ymm3[1,9],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm3[19,27],zero,zero,zero,zero,zero,ymm3[20,28],zero,zero ; AVX512BW-FCP-NEXT: vpor %ymm0, %ymm3, %ymm0 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm2[0,8],zero,zero,zero,zero,zero,ymm2[1,9],zero,zero,zero,zero,zero,ymm2[2,10,18,26],zero,zero,zero,zero,zero,ymm2[19,27],zero,zero,zero,zero,zero,ymm2[20,28] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,0,1] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = zero,zero,ymm2[0,8],zero,zero,zero,zero,zero,ymm2[1,9],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm2[19,27],zero,zero,zero,zero,zero,ymm2[20,28],zero,zero -; AVX512BW-FCP-NEXT: vpor %ymm3, %ymm2, %ymm2 ; AVX512BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [0,2,4,6,0,2,4,6] ; AVX512BW-FCP-NEXT: # ymm3 = mem[0,1,0,1] -; AVX512BW-FCP-NEXT: vpermd %ymm1, %ymm3, %ymm1 +; AVX512BW-FCP-NEXT: vpermd %ymm1, %ymm3, %ymm3 ; AVX512BW-FCP-NEXT: movl $236730480, %ecx # imm = 0xE1C3870 ; AVX512BW-FCP-NEXT: kmovd %ecx, %k1 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 {%k1} = ymm1[u,u,u,u,0,4,8,u,u,u,u,1,5,9,u,u,u,u,18,22,26,u,u,u,u,19,23,27,u,u,u,u] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm2, %zmm0 -; AVX512BW-FCP-NEXT: vmovdqa %ymm2, (%rax) -; AVX512BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) -; AVX512BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm0 -; AVX512BW-FCP-NEXT: vmovq %xmm0, 48(%rax) +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 {%k1} = ymm3[u,u,u,u,0,4,8,u,u,u,u,1,5,9,u,u,u,u,18,22,26,u,u,u,u,19,23,27,u,u,u,u] +; AVX512BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [1,3,5,7,1,3,5,7] +; AVX512BW-FCP-NEXT: # ymm3 = mem[0,1,0,1] +; AVX512BW-FCP-NEXT: vpermd %ymm2, %ymm3, %ymm2 +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = zero,zero,zero,ymm2[1,5,9,13],zero,zero,zero,ymm2[2,6,10,14],zero,zero,zero,ymm2[19,23,27,31],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm3 = [1,3,5,0,5,1,3,0] +; AVX512BW-FCP-NEXT: vpermd %ymm1, %ymm3, %ymm1 +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[0,4,8],zero,zero,zero,zero,ymm1[1,5,9],zero,zero,zero,zero,ymm1[2,6,18],zero,zero,zero,zero,ymm1[23,27,19],zero,zero,zero,zero,zero,zero,zero,zero +; AVX512BW-FCP-NEXT: vpor %ymm2, %ymm1, %ymm1 +; AVX512BW-FCP-NEXT: vextracti128 $1, %ymm1, %xmm2 +; AVX512BW-FCP-NEXT: vmovq %xmm2, 48(%rax) +; AVX512BW-FCP-NEXT: vmovdqa %xmm1, 32(%rax) +; AVX512BW-FCP-NEXT: vmovdqa %ymm0, (%rax) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; @@ -1326,29 +1325,28 @@ define void @store_i8_stride7_vf8(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vecp ; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512DQ-BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512DQ-BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [1,3,5,7,1,3,5,7] -; AVX512DQ-BW-FCP-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512DQ-BW-FCP-NEXT: vpermd %ymm2, %ymm0, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm0[1,5,9,13],zero,zero,zero,ymm0[2,6,10,14],zero,zero,zero,ymm0[19,23,27,31],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm3 = [1,3,5,0,5,1,3,0] -; AVX512DQ-BW-FCP-NEXT: vpermd %ymm1, %ymm3, %ymm3 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[0,4,8],zero,zero,zero,zero,ymm3[1,5,9],zero,zero,zero,zero,ymm3[2,6,18],zero,zero,zero,zero,ymm3[23,27,19],zero,zero,zero,zero,zero,zero,zero,zero +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[0,8],zero,zero,zero,zero,zero,ymm2[1,9],zero,zero,zero,zero,zero,ymm2[2,10,18,26],zero,zero,zero,zero,zero,ymm2[19,27],zero,zero,zero,zero,zero,ymm2[20,28] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm2[2,3,0,1] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = zero,zero,ymm3[0,8],zero,zero,zero,zero,zero,ymm3[1,9],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm3[19,27],zero,zero,zero,zero,zero,ymm3[20,28],zero,zero ; AVX512DQ-BW-FCP-NEXT: vpor %ymm0, %ymm3, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm2[0,8],zero,zero,zero,zero,zero,ymm2[1,9],zero,zero,zero,zero,zero,ymm2[2,10,18,26],zero,zero,zero,zero,zero,ymm2[19,27],zero,zero,zero,zero,zero,ymm2[20,28] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,0,1] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = zero,zero,ymm2[0,8],zero,zero,zero,zero,zero,ymm2[1,9],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm2[19,27],zero,zero,zero,zero,zero,ymm2[20,28],zero,zero -; AVX512DQ-BW-FCP-NEXT: vpor %ymm3, %ymm2, %ymm2 ; AVX512DQ-BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [0,2,4,6,0,2,4,6] ; AVX512DQ-BW-FCP-NEXT: # ymm3 = mem[0,1,0,1] -; AVX512DQ-BW-FCP-NEXT: vpermd %ymm1, %ymm3, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vpermd %ymm1, %ymm3, %ymm3 ; AVX512DQ-BW-FCP-NEXT: movl $236730480, %ecx # imm = 0xE1C3870 ; AVX512DQ-BW-FCP-NEXT: kmovd %ecx, %k1 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 {%k1} = ymm1[u,u,u,u,0,4,8,u,u,u,u,1,5,9,u,u,u,u,18,22,26,u,u,u,u,19,23,27,u,u,u,u] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm2, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa %ymm2, (%rax) -; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) -; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm0 -; AVX512DQ-BW-FCP-NEXT: vmovq %xmm0, 48(%rax) +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 {%k1} = ymm3[u,u,u,u,0,4,8,u,u,u,u,1,5,9,u,u,u,u,18,22,26,u,u,u,u,19,23,27,u,u,u,u] +; AVX512DQ-BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [1,3,5,7,1,3,5,7] +; AVX512DQ-BW-FCP-NEXT: # ymm3 = mem[0,1,0,1] +; AVX512DQ-BW-FCP-NEXT: vpermd %ymm2, %ymm3, %ymm2 +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = zero,zero,zero,ymm2[1,5,9,13],zero,zero,zero,ymm2[2,6,10,14],zero,zero,zero,ymm2[19,23,27,31],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm3 = [1,3,5,0,5,1,3,0] +; AVX512DQ-BW-FCP-NEXT: vpermd %ymm1, %ymm3, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[0,4,8],zero,zero,zero,zero,ymm1[1,5,9],zero,zero,zero,zero,ymm1[2,6,18],zero,zero,zero,zero,ymm1[23,27,19],zero,zero,zero,zero,zero,zero,zero,zero +; AVX512DQ-BW-FCP-NEXT: vpor %ymm2, %ymm1, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vextracti128 $1, %ymm1, %xmm2 +; AVX512DQ-BW-FCP-NEXT: vmovq %xmm2, 48(%rax) +; AVX512DQ-BW-FCP-NEXT: vmovdqa %xmm1, 32(%rax) +; AVX512DQ-BW-FCP-NEXT: vmovdqa %ymm0, (%rax) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <8 x i8>, ptr %in.vecptr0, align 64 @@ -2053,77 +2051,76 @@ define void @store_i8_stride7_vf16(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512: # %bb.0: ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512-NEXT: vmovdqa (%rdi), %xmm4 -; AVX512-NEXT: vmovdqa (%rsi), %xmm5 -; AVX512-NEXT: vmovdqa (%rdx), %xmm6 -; AVX512-NEXT: vmovdqa (%rcx), %xmm7 -; AVX512-NEXT: vmovdqa (%r8), %xmm0 -; AVX512-NEXT: vmovdqa (%r10), %xmm1 -; AVX512-NEXT: vinserti128 $1, %xmm7, %ymm6, %ymm3 -; AVX512-NEXT: vinserti128 $1, %xmm5, %ymm4, %ymm2 -; AVX512-NEXT: vinserti128 $1, (%r9), %ymm0, %ymm0 -; AVX512-NEXT: vinserti32x4 $2, %xmm1, %zmm0, %zmm0 -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm6[8],xmm7[8],xmm6[9],xmm7[9],xmm6[10],xmm7[10],xmm6[11],xmm7[11],xmm6[12],xmm7[12],xmm6[13],xmm7[13],xmm6[14],xmm7[14],xmm6[15],xmm7[15] -; AVX512-NEXT: vpshufb {{.*#+}} xmm6 = xmm6[u,u],zero,zero,xmm6[12,13,u,u,u],zero,zero,xmm6[14,15,u,u,u] -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] -; AVX512-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,u,12,13],zero,zero,xmm4[u,u,u,14,15],zero,zero,xmm4[u,u,u] -; AVX512-NEXT: vpor %xmm6, %xmm4, %xmm4 -; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm5 -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; AVX512-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[10],zero,xmm5[u,u,u,u,13,12],zero,xmm5[u,u,u,u,15,14],zero -; AVX512-NEXT: vpshufb {{.*#+}} xmm6 = zero,xmm1[13,u,u,u,u],zero,zero,xmm1[14,u,u,u,u],zero,zero,xmm1[15] -; AVX512-NEXT: vpor %xmm6, %xmm5, %xmm5 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm5 -; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm2[3,1,1,3] -; AVX512-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[1],zero,zero,ymm4[u,u,u,10,2],zero,zero,ymm4[u,u,u,11,3],zero,zero,ymm4[u,u,u,20,28],zero,zero,ymm4[u,u,u,21,29],zero,zero,ymm4[u] -; AVX512-NEXT: vpermq {{.*#+}} ymm6 = ymm3[1,3,3,1] -; AVX512-NEXT: vpshufb {{.*#+}} ymm6 = zero,ymm6[1,9,u,u,u],zero,zero,ymm6[2,10,u,u,u],zero,zero,ymm6[3,19,u,u,u],zero,zero,ymm6[28,20,u,u,u],zero,zero,ymm6[29,21,u] -; AVX512-NEXT: vpor %ymm4, %ymm6, %ymm4 -; AVX512-NEXT: vpshufhw {{.*#+}} xmm6 = xmm1[0,1,2,3,4,5,5,6] -; AVX512-NEXT: vpshufd {{.*#+}} xmm6 = xmm6[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,1,0,1] -; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm0[1,3,1,3] +; AVX512-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512-NEXT: vmovdqa (%rsi), %xmm1 +; AVX512-NEXT: vmovdqa (%rdx), %xmm5 +; AVX512-NEXT: vmovdqa (%rcx), %xmm6 +; AVX512-NEXT: vmovdqa (%r8), %xmm3 +; AVX512-NEXT: vmovdqa (%r9), %xmm4 +; AVX512-NEXT: vmovdqa (%r10), %xmm2 +; AVX512-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm8 +; AVX512-NEXT: vinserti128 $1, %xmm6, %ymm5, %ymm9 +; AVX512-NEXT: vinserti128 $1, %xmm4, %ymm3, %ymm7 +; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = ymm9[u,u,u,u,u,5],zero,ymm9[u,u,u,u,u,6],zero,ymm9[u,u,u,u,u],zero,ymm9[23,u,u,u,u,u],zero,ymm9[24,u,u,u,u] +; AVX512-NEXT: vpermq {{.*#+}} ymm11 = ymm9[2,3,0,1] +; AVX512-NEXT: vpshufb {{.*#+}} ymm11 = ymm11[u,u,u,u,u],zero,ymm11[5,u,u,u,u,u],zero,ymm11[6,u,u,u,u,u,23],zero,ymm11[u,u,u,u,u,24],zero,ymm11[u,u,u,u] +; AVX512-NEXT: vmovdqa {{.*#+}} ymm12 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255] +; AVX512-NEXT: vpternlogq $50, %ymm10, %ymm12, %ymm11 +; AVX512-NEXT: vpermq {{.*#+}} ymm10 = ymm9[0,2,0,2] +; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = zero,zero,ymm10[0,8,u,u,u],zero,zero,ymm10[1,9,u,u,u],zero,zero,ymm10[18,26,u,u,u],zero,zero,ymm10[19,27,u,u,u],zero,zero,ymm10[20,28] +; AVX512-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 +; AVX512-NEXT: vpshufb {{.*#+}} ymm11 = ymm8[u,u,u,5],zero,ymm8[u,u,u,u,u,6],zero,ymm8[u,u,u,u,u],zero,ymm8[23,u,u,u,u,u],zero,ymm8[24,u,u,u,u,u],zero +; AVX512-NEXT: vpermq {{.*#+}} ymm13 = ymm8[2,3,0,1] +; AVX512-NEXT: vpshufb {{.*#+}} ymm13 = ymm13[u,u,u],zero,ymm13[5,u,u,u,u,u],zero,ymm13[6,u,u,u,u,u,23],zero,ymm13[u,u,u,u,u,24],zero,ymm13[u,u,u,u,u,25] +; AVX512-NEXT: vpternlogq $200, %ymm11, %ymm12, %ymm13 +; AVX512-NEXT: vpermq {{.*#+}} ymm11 = ymm8[0,2,0,2] +; AVX512-NEXT: vpshufb {{.*#+}} ymm11 = ymm11[0,8],zero,zero,ymm11[u,u,u,1,9],zero,zero,ymm11[u,u,u,2,10],zero,zero,ymm11[u,u,u,19,27],zero,zero,ymm11[u,u,u,20,28],zero,zero +; AVX512-NEXT: vinserti64x4 $1, %ymm13, %zmm11, %zmm11 +; AVX512-NEXT: vporq %zmm10, %zmm11, %zmm10 +; AVX512-NEXT: vpshufb {{.*#+}} ymm11 = ymm7[4],zero,ymm7[u,u,u,u,u,5],zero,ymm7[u,u,u,u,u,6],zero,ymm7[u,u,u,u,u],zero,ymm7[23,u,u,u,u,u],zero,ymm7[24,u,u] +; AVX512-NEXT: vpermq {{.*#+}} ymm12 = ymm7[2,3,0,1] +; AVX512-NEXT: vpshufb {{.*#+}} ymm12 = zero,ymm12[4,u,u,u,u,u],zero,ymm12[5,u,u,u,u,u],zero,ymm12[6,u,u,u,u,u,23],zero,ymm12[u,u,u,u,u,24],zero,ymm12[u,u] +; AVX512-NEXT: vmovdqa {{.*#+}} ymm13 = [255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255] +; AVX512-NEXT: vpternlogq $200, %ymm11, %ymm13, %ymm12 +; AVX512-NEXT: vpermq {{.*#+}} ymm11 = ymm7[0,2,0,2] +; AVX512-NEXT: vpshufb {{.*#+}} ymm11 = ymm11[u,u,u,u,0,8],zero,ymm11[u,u,u,u,1,9],zero,ymm11[u,u,u,u,18,26],zero,ymm11[u,u,u,u,19,27],zero,ymm11[u,u,u,u] +; AVX512-NEXT: vinserti64x4 $1, %ymm12, %zmm11, %zmm11 +; AVX512-NEXT: vpshufb {{.*#+}} xmm12 = xmm2[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512-NEXT: vpermq {{.*#+}} ymm12 = ymm12[0,0,1,0] +; AVX512-NEXT: vpandn %ymm12, %ymm13, %ymm12 +; AVX512-NEXT: vpshuflw {{.*#+}} xmm13 = xmm2[1,1,0,0,4,5,6,7] +; AVX512-NEXT: vpshufd {{.*#+}} xmm13 = xmm13[0,1,2,0] +; AVX512-NEXT: vpermq {{.*#+}} ymm13 = ymm13[0,0,1,0] +; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm13, %ymm13 +; AVX512-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm12 +; AVX512-NEXT: vporq %zmm12, %zmm11, %zmm11 +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm11 +; AVX512-NEXT: vpermq {{.*#+}} ymm8 = ymm8[3,1,1,3] +; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm8[1],zero,zero,ymm8[u,u,u,10,2],zero,zero,ymm8[u,u,u,11,3],zero,zero,ymm8[u,u,u,20,28],zero,zero,ymm8[u,u,u,21,29],zero,zero,ymm8[u] +; AVX512-NEXT: vpermq {{.*#+}} ymm9 = ymm9[1,3,3,1] +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = zero,ymm9[1,9,u,u,u],zero,zero,ymm9[2,10,u,u,u],zero,zero,ymm9[3,19,u,u,u],zero,zero,ymm9[28,20,u,u,u],zero,zero,ymm9[29,21,u] +; AVX512-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX512-NEXT: vpshufhw {{.*#+}} xmm9 = xmm2[0,1,2,3,4,5,5,6] +; AVX512-NEXT: vpshufd {{.*#+}} xmm9 = xmm9[2,2,3,3] +; AVX512-NEXT: vpermq {{.*#+}} ymm9 = ymm9[0,1,0,1] +; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm7[1,3,1,3] ; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[u,u,u,1,9],zero,ymm7[u,u,u,u,2,10],zero,ymm7[u,u,u,u,19,27],zero,ymm7[u,u,u,u,20,28],zero,ymm7[u,u,u,u,21] -; AVX512-NEXT: vpternlogq $244, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm6, %ymm7 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm7 -; AVX512-NEXT: vinserti32x4 $2, %xmm5, %zmm7, %zmm4 -; AVX512-NEXT: vpshufb {{.*#+}} ymm6 = ymm3[u,u,u,u,u,5],zero,ymm3[u,u,u,u,u,6],zero,ymm3[u,u,u,u,u],zero,ymm3[23,u,u,u,u,u],zero,ymm3[24,u,u,u,u] -; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm3[2,3,0,1] -; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[u,u,u,u,u],zero,ymm7[5,u,u,u,u,u],zero,ymm7[6,u,u,u,u,u,23],zero,ymm7[u,u,u,u,u,24],zero,ymm7[u,u,u,u] -; AVX512-NEXT: vmovdqa {{.*#+}} ymm8 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255] -; AVX512-NEXT: vpternlogq $50, %ymm6, %ymm8, %ymm7 -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm3[0,2,0,2] -; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = zero,zero,ymm3[0,8,u,u,u],zero,zero,ymm3[1,9,u,u,u],zero,zero,ymm3[18,26,u,u,u],zero,zero,ymm3[19,27,u,u,u],zero,zero,ymm3[20,28] -; AVX512-NEXT: vinserti64x4 $1, %ymm7, %zmm3, %zmm3 -; AVX512-NEXT: vpshufb {{.*#+}} ymm6 = ymm2[u,u,u,5],zero,ymm2[u,u,u,u,u,6],zero,ymm2[u,u,u,u,u],zero,ymm2[23,u,u,u,u,u],zero,ymm2[24,u,u,u,u,u],zero -; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm2[2,3,0,1] -; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[u,u,u],zero,ymm7[5,u,u,u,u,u],zero,ymm7[6,u,u,u,u,u,23],zero,ymm7[u,u,u,u,u,24],zero,ymm7[u,u,u,u,u,25] -; AVX512-NEXT: vpternlogq $200, %ymm6, %ymm8, %ymm7 -; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm2[0,2,0,2] -; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[0,8],zero,zero,ymm2[u,u,u,1,9],zero,zero,ymm2[u,u,u,2,10],zero,zero,ymm2[u,u,u,19,27],zero,zero,ymm2[u,u,u,20,28],zero,zero -; AVX512-NEXT: vinserti64x4 $1, %ymm7, %zmm2, %zmm2 -; AVX512-NEXT: vporq %zmm3, %zmm2, %zmm2 -; AVX512-NEXT: vpshufb {{.*#+}} xmm3 = xmm1[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm3[0,0,1,0] -; AVX512-NEXT: vmovdqa {{.*#+}} ymm6 = [255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255] -; AVX512-NEXT: vpandn %ymm3, %ymm6, %ymm3 -; AVX512-NEXT: vpshuflw {{.*#+}} xmm1 = xmm1[1,1,0,0,4,5,6,7] -; AVX512-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[0,1,2,0] -; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,1,0] -; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm1 -; AVX512-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1 -; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm0[4],zero,ymm0[u,u,u,u,u,5],zero,ymm0[u,u,u,u,u,6],zero,ymm0[u,u,u,u,u],zero,ymm0[23,u,u,u,u,u],zero,ymm0[24,u,u] -; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm0[2,3,0,1] -; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = zero,ymm7[4,u,u,u,u,u],zero,ymm7[5,u,u,u,u,u],zero,ymm7[6,u,u,u,u,u,23],zero,ymm7[u,u,u,u,u,24],zero,ymm7[u,u] -; AVX512-NEXT: vpternlogq $200, %ymm3, %ymm6, %ymm7 -; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,0,2] -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,0,8],zero,ymm0[u,u,u,u,1,9],zero,ymm0[u,u,u,u,18,26],zero,ymm0[u,u,u,u,19,27],zero,ymm0[u,u,u,u] -; AVX512-NEXT: vinserti64x4 $1, %ymm7, %zmm0, %zmm0 -; AVX512-NEXT: vporq %zmm1, %zmm0, %zmm0 -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 -; AVX512-NEXT: vmovdqa %xmm5, 96(%rax) -; AVX512-NEXT: vmovdqa64 %zmm0, (%rax) -; AVX512-NEXT: vmovdqa %ymm4, 64(%rax) +; AVX512-NEXT: vpternlogq $244, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm9, %ymm7 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm8, %ymm7 +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm5[8],xmm6[8],xmm5[9],xmm6[9],xmm5[10],xmm6[10],xmm5[11],xmm6[11],xmm5[12],xmm6[12],xmm5[13],xmm6[13],xmm5[14],xmm6[14],xmm5[15],xmm6[15] +; AVX512-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[u,u],zero,zero,xmm5[12,13,u,u,u],zero,zero,xmm5[14,15,u,u,u] +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; AVX512-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[u,u,12,13],zero,zero,xmm0[u,u,u,14,15],zero,zero,xmm0[u,u,u] +; AVX512-NEXT: vpor %xmm5, %xmm0, %xmm0 +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] +; AVX512-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[10],zero,xmm1[u,u,u,u,13,12],zero,xmm1[u,u,u,u,15,14],zero +; AVX512-NEXT: vpshufb {{.*#+}} xmm2 = zero,xmm2[13,u,u,u,u],zero,zero,xmm2[14,u,u,u,u],zero,zero,xmm2[15] +; AVX512-NEXT: vpor %xmm2, %xmm1, %xmm1 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1 +; AVX512-NEXT: vinserti32x4 $2, %xmm1, %zmm7, %zmm0 +; AVX512-NEXT: vmovdqa %xmm1, 96(%rax) +; AVX512-NEXT: vmovdqa %ymm0, 64(%rax) +; AVX512-NEXT: vmovdqa64 %zmm11, (%rax) ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; @@ -2131,70 +2128,69 @@ define void @store_i8_stride7_vf16(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP: # %bb.0: ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512-FCP-NEXT: vmovdqa (%rdi), %xmm2 -; AVX512-FCP-NEXT: vmovdqa (%rsi), %xmm3 -; AVX512-FCP-NEXT: vmovdqa (%rdx), %xmm4 -; AVX512-FCP-NEXT: vmovdqa (%rcx), %xmm5 -; AVX512-FCP-NEXT: vmovdqa (%r8), %xmm1 -; AVX512-FCP-NEXT: vmovdqa (%r10), %xmm0 -; AVX512-FCP-NEXT: vinserti128 $1, %xmm5, %ymm4, %ymm6 -; AVX512-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm7 -; AVX512-FCP-NEXT: vinserti128 $1, (%r9), %ymm1, %ymm1 -; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm1 -; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,u],zero,zero,xmm4[12,13,u,u,u],zero,zero,xmm4[14,15,u,u,u] -; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm2[8],xmm3[8],xmm2[9],xmm3[9],xmm2[10],xmm3[10],xmm2[11],xmm3[11],xmm2[12],xmm3[12],xmm2[13],xmm3[13],xmm2[14],xmm3[14],xmm2[15],xmm3[15] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm2 = xmm2[u,u,12,13],zero,zero,xmm2[u,u,u,14,15],zero,zero,xmm2[u,u,u] -; AVX512-FCP-NEXT: vpor %xmm4, %xmm2, %xmm2 -; AVX512-FCP-NEXT: vextracti128 $1, %ymm1, %xmm3 -; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm3[8],xmm1[8],xmm3[9],xmm1[9],xmm3[10],xmm1[10],xmm3[11],xmm1[11],xmm3[12],xmm1[12],xmm3[13],xmm1[13],xmm3[14],xmm1[14],xmm3[15],xmm1[15] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm3 = xmm3[10],zero,xmm3[u,u,u,u,13,12],zero,xmm3[u,u,u,u,15,14],zero -; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm4 = zero,xmm0[13,u,u,u,u],zero,zero,xmm0[14,u,u,u,u],zero,zero,xmm0[15] -; AVX512-FCP-NEXT: vpor %xmm4, %xmm3, %xmm3 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm3 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm7[3,1,1,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[1],zero,zero,ymm2[u,u,u,10,2],zero,zero,ymm2[u,u,u,11,3],zero,zero,ymm2[u,u,u,20,28],zero,zero,ymm2[u,u,u,21,29],zero,zero,ymm2[u] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm6[1,3,3,1] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm4 = zero,ymm4[1,9,u,u,u],zero,zero,ymm4[2,10,u,u,u],zero,zero,ymm4[3,19,u,u,u],zero,zero,ymm4[28,20,u,u,u],zero,zero,ymm4[29,21,u] -; AVX512-FCP-NEXT: vpor %ymm2, %ymm4, %ymm2 -; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm4 = xmm0[0,1,2,3,4,5,5,6] -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [2,2,3,3,2,2,3,3] -; AVX512-FCP-NEXT: # ymm5 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpermd %ymm4, %ymm5, %ymm4 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm1[1,3,1,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm5[u,u,u,1,9],zero,ymm5[u,u,u,u,2,10],zero,ymm5[u,u,u,u,19,27],zero,ymm5[u,u,u,u,20,28],zero,ymm5[u,u,u,u,21] -; AVX512-FCP-NEXT: vpternlogq $244, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm5 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm5 -; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm3, %zmm5, %zmm2 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm6[0,2,0,2] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm4 = zero,zero,ymm4[0,8,u,u,u],zero,zero,ymm4[1,9,u,u,u],zero,zero,ymm4[18,26,u,u,u],zero,zero,ymm4[19,27,u,u,u],zero,zero,ymm4[20,28] -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [1,5,2,6,1,5,2,6] -; AVX512-FCP-NEXT: # ymm5 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpermd %ymm6, %ymm5, %ymm6 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[u,u,u],zero,zero,ymm6[1,5,u,u,u],zero,zero,ymm6[2,6,u,u,u],zero,zero,ymm6[19,23,u,u,u],zero,zero,ymm6[24,28,u,u,u],zero -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm4, %zmm4 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm7[0,2,0,2] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[0,8],zero,zero,ymm6[u,u,u,1,9],zero,zero,ymm6[u,u,u,2,10],zero,zero,ymm6[u,u,u,19,27],zero,zero,ymm6[u,u,u,20,28],zero,zero -; AVX512-FCP-NEXT: vpermd %ymm7, %ymm5, %ymm7 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[u,u,u,1,5],zero,zero,ymm7[u,u,u,2,6],zero,zero,ymm7[u,u,u,19,23],zero,zero,ymm7[u,u,u,24,28],zero,zero,ymm7[u,u,u,25] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm6, %zmm6 -; AVX512-FCP-NEXT: vporq %zmm4, %zmm6, %zmm4 -; AVX512-FCP-NEXT: vpshuflw {{.*#+}} xmm6 = xmm0[1,1,0,0,4,5,6,7] -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm7 = [0,1,0,1,0,0,0,0] -; AVX512-FCP-NEXT: vpermd %ymm6, %ymm7, %ymm6 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,0] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm6, %zmm0 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm1[0,2,0,2] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[u,u,u,u,0,8],zero,ymm6[u,u,u,u,1,9],zero,ymm6[u,u,u,u,18,26],zero,ymm6[u,u,u,u,19,27],zero,ymm6[u,u,u,u] -; AVX512-FCP-NEXT: vpermd %ymm1, %ymm5, %ymm1 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[0,4],zero,ymm1[u,u,u,u,1,5],zero,ymm1[u,u,u,u,2,6],zero,ymm1[u,u,u,u,19,23],zero,ymm1[u,u,u,u,24,28],zero,ymm1[u] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm6, %zmm1 -; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 -; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm4, %zmm1 -; AVX512-FCP-NEXT: vmovdqa %xmm3, 96(%rax) -; AVX512-FCP-NEXT: vmovdqa64 %zmm1, (%rax) -; AVX512-FCP-NEXT: vmovdqa %ymm2, 64(%rax) +; AVX512-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512-FCP-NEXT: vmovdqa (%rsi), %xmm1 +; AVX512-FCP-NEXT: vmovdqa (%rdx), %xmm5 +; AVX512-FCP-NEXT: vmovdqa (%rcx), %xmm6 +; AVX512-FCP-NEXT: vmovdqa (%r8), %xmm3 +; AVX512-FCP-NEXT: vmovdqa (%r9), %xmm4 +; AVX512-FCP-NEXT: vmovdqa (%r10), %xmm2 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm7 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm6, %ymm5, %ymm8 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm4, %ymm3, %ymm9 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm8[0,2,0,2] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = zero,zero,ymm10[0,8,u,u,u],zero,zero,ymm10[1,9,u,u,u],zero,zero,ymm10[18,26,u,u,u],zero,zero,ymm10[19,27,u,u,u],zero,zero,ymm10[20,28] +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [1,5,2,6,1,5,2,6] +; AVX512-FCP-NEXT: # ymm11 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpermd %ymm8, %ymm11, %ymm12 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm12[u,u,u],zero,zero,ymm12[1,5,u,u,u],zero,zero,ymm12[2,6,u,u,u],zero,zero,ymm12[19,23,u,u,u],zero,zero,ymm12[24,28,u,u,u],zero +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm10, %zmm10 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm7[0,2,0,2] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm12[0,8],zero,zero,ymm12[u,u,u,1,9],zero,zero,ymm12[u,u,u,2,10],zero,zero,ymm12[u,u,u,19,27],zero,zero,ymm12[u,u,u,20,28],zero,zero +; AVX512-FCP-NEXT: vpermd %ymm7, %ymm11, %ymm13 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm13[u,u,u,1,5],zero,zero,ymm13[u,u,u,2,6],zero,zero,ymm13[u,u,u,19,23],zero,zero,ymm13[u,u,u,24,28],zero,zero,ymm13[u,u,u,25] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm12, %zmm12 +; AVX512-FCP-NEXT: vporq %zmm10, %zmm12, %zmm10 +; AVX512-FCP-NEXT: vpshuflw {{.*#+}} xmm12 = xmm2[1,1,0,0,4,5,6,7] +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm13 = [0,1,0,1,0,0,0,0] +; AVX512-FCP-NEXT: vpermd %ymm12, %ymm13, %ymm12 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm13 = xmm2[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[0,0,1,0] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm12, %zmm12 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm9[0,2,0,2] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm13[u,u,u,u,0,8],zero,ymm13[u,u,u,u,1,9],zero,ymm13[u,u,u,u,18,26],zero,ymm13[u,u,u,u,19,27],zero,ymm13[u,u,u,u] +; AVX512-FCP-NEXT: vpermd %ymm9, %ymm11, %ymm11 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm11[0,4],zero,ymm11[u,u,u,u,1,5],zero,ymm11[u,u,u,u,2,6],zero,ymm11[u,u,u,u,19,23],zero,ymm11[u,u,u,u,24,28],zero,ymm11[u] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm13, %zmm11 +; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm12, %zmm11 +; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm11 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[3,1,1,3] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[1],zero,zero,ymm7[u,u,u,10,2],zero,zero,ymm7[u,u,u,11,3],zero,zero,ymm7[u,u,u,20,28],zero,zero,ymm7[u,u,u,21,29],zero,zero,ymm7[u] +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[1,3,3,1] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm8 = zero,ymm8[1,9,u,u,u],zero,zero,ymm8[2,10,u,u,u],zero,zero,ymm8[3,19,u,u,u],zero,zero,ymm8[28,20,u,u,u],zero,zero,ymm8[29,21,u] +; AVX512-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 +; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm8 = xmm2[0,1,2,3,4,5,5,6] +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [2,2,3,3,2,2,3,3] +; AVX512-FCP-NEXT: # ymm10 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpermd %ymm8, %ymm10, %ymm8 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[1,3,1,3] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm9[u,u,u,1,9],zero,ymm9[u,u,u,u,2,10],zero,ymm9[u,u,u,u,19,27],zero,ymm9[u,u,u,u,20,28],zero,ymm9[u,u,u,u,21] +; AVX512-FCP-NEXT: vpternlogq $244, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm8, %ymm9 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm7, %ymm9 +; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm5[8],xmm6[8],xmm5[9],xmm6[9],xmm5[10],xmm6[10],xmm5[11],xmm6[11],xmm5[12],xmm6[12],xmm5[13],xmm6[13],xmm5[14],xmm6[14],xmm5[15],xmm6[15] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[u,u],zero,zero,xmm5[12,13,u,u,u],zero,zero,xmm5[14,15,u,u,u] +; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[u,u,12,13],zero,zero,xmm0[u,u,u,14,15],zero,zero,xmm0[u,u,u] +; AVX512-FCP-NEXT: vpor %xmm5, %xmm0, %xmm0 +; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[10],zero,xmm1[u,u,u,u,13,12],zero,xmm1[u,u,u,u,15,14],zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm2 = zero,xmm2[13,u,u,u,u],zero,zero,xmm2[14,u,u,u,u],zero,zero,xmm2[15] +; AVX512-FCP-NEXT: vpor %xmm2, %xmm1, %xmm1 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1 +; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm9, %zmm0 +; AVX512-FCP-NEXT: vmovdqa %xmm1, 96(%rax) +; AVX512-FCP-NEXT: vmovdqa64 %zmm11, (%rax) +; AVX512-FCP-NEXT: vmovdqa %ymm0, 64(%rax) ; AVX512-FCP-NEXT: vzeroupper ; AVX512-FCP-NEXT: retq ; @@ -2202,77 +2198,76 @@ define void @store_i8_stride7_vf16(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ: # %bb.0: ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm4 -; AVX512DQ-NEXT: vmovdqa (%rsi), %xmm5 -; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm6 -; AVX512DQ-NEXT: vmovdqa (%rcx), %xmm7 -; AVX512DQ-NEXT: vmovdqa (%r8), %xmm0 -; AVX512DQ-NEXT: vmovdqa (%r10), %xmm1 -; AVX512DQ-NEXT: vinserti128 $1, %xmm7, %ymm6, %ymm3 -; AVX512DQ-NEXT: vinserti128 $1, %xmm5, %ymm4, %ymm2 -; AVX512DQ-NEXT: vinserti128 $1, (%r9), %ymm0, %ymm0 -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm1, %zmm0, %zmm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm6[8],xmm7[8],xmm6[9],xmm7[9],xmm6[10],xmm7[10],xmm6[11],xmm7[11],xmm6[12],xmm7[12],xmm6[13],xmm7[13],xmm6[14],xmm7[14],xmm6[15],xmm7[15] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm6 = xmm6[u,u],zero,zero,xmm6[12,13,u,u,u],zero,zero,xmm6[14,15,u,u,u] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,u,12,13],zero,zero,xmm4[u,u,u,14,15],zero,zero,xmm4[u,u,u] -; AVX512DQ-NEXT: vpor %xmm6, %xmm4, %xmm4 -; AVX512DQ-NEXT: vextracti128 $1, %ymm0, %xmm5 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[10],zero,xmm5[u,u,u,u,13,12],zero,xmm5[u,u,u,u,15,14],zero -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm6 = zero,xmm1[13,u,u,u,u],zero,zero,xmm1[14,u,u,u,u],zero,zero,xmm1[15] -; AVX512DQ-NEXT: vpor %xmm6, %xmm5, %xmm5 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm5 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm2[3,1,1,3] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[1],zero,zero,ymm4[u,u,u,10,2],zero,zero,ymm4[u,u,u,11,3],zero,zero,ymm4[u,u,u,20,28],zero,zero,ymm4[u,u,u,21,29],zero,zero,ymm4[u] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm6 = ymm3[1,3,3,1] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm6 = zero,ymm6[1,9,u,u,u],zero,zero,ymm6[2,10,u,u,u],zero,zero,ymm6[3,19,u,u,u],zero,zero,ymm6[28,20,u,u,u],zero,zero,ymm6[29,21,u] -; AVX512DQ-NEXT: vpor %ymm4, %ymm6, %ymm4 -; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm6 = xmm1[0,1,2,3,4,5,5,6] -; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm6 = xmm6[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,1,0,1] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm0[1,3,1,3] +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-NEXT: vmovdqa (%rsi), %xmm1 +; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm5 +; AVX512DQ-NEXT: vmovdqa (%rcx), %xmm6 +; AVX512DQ-NEXT: vmovdqa (%r8), %xmm3 +; AVX512DQ-NEXT: vmovdqa (%r9), %xmm4 +; AVX512DQ-NEXT: vmovdqa (%r10), %xmm2 +; AVX512DQ-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm8 +; AVX512DQ-NEXT: vinserti128 $1, %xmm6, %ymm5, %ymm9 +; AVX512DQ-NEXT: vinserti128 $1, %xmm4, %ymm3, %ymm7 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = ymm9[u,u,u,u,u,5],zero,ymm9[u,u,u,u,u,6],zero,ymm9[u,u,u,u,u],zero,ymm9[23,u,u,u,u,u],zero,ymm9[24,u,u,u,u] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm11 = ymm9[2,3,0,1] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm11 = ymm11[u,u,u,u,u],zero,ymm11[5,u,u,u,u,u],zero,ymm11[6,u,u,u,u,u,23],zero,ymm11[u,u,u,u,u,24],zero,ymm11[u,u,u,u] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm12 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255] +; AVX512DQ-NEXT: vpternlogq $50, %ymm10, %ymm12, %ymm11 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm10 = ymm9[0,2,0,2] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = zero,zero,ymm10[0,8,u,u,u],zero,zero,ymm10[1,9,u,u,u],zero,zero,ymm10[18,26,u,u,u],zero,zero,ymm10[19,27,u,u,u],zero,zero,ymm10[20,28] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm11 = ymm8[u,u,u,5],zero,ymm8[u,u,u,u,u,6],zero,ymm8[u,u,u,u,u],zero,ymm8[23,u,u,u,u,u],zero,ymm8[24,u,u,u,u,u],zero +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm13 = ymm8[2,3,0,1] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm13 = ymm13[u,u,u],zero,ymm13[5,u,u,u,u,u],zero,ymm13[6,u,u,u,u,u,23],zero,ymm13[u,u,u,u,u,24],zero,ymm13[u,u,u,u,u,25] +; AVX512DQ-NEXT: vpternlogq $200, %ymm11, %ymm12, %ymm13 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm11 = ymm8[0,2,0,2] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm11 = ymm11[0,8],zero,zero,ymm11[u,u,u,1,9],zero,zero,ymm11[u,u,u,2,10],zero,zero,ymm11[u,u,u,19,27],zero,zero,ymm11[u,u,u,20,28],zero,zero +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm13, %zmm11, %zmm11 +; AVX512DQ-NEXT: vporq %zmm10, %zmm11, %zmm10 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm11 = ymm7[4],zero,ymm7[u,u,u,u,u,5],zero,ymm7[u,u,u,u,u,6],zero,ymm7[u,u,u,u,u],zero,ymm7[23,u,u,u,u,u],zero,ymm7[24,u,u] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm12 = ymm7[2,3,0,1] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm12 = zero,ymm12[4,u,u,u,u,u],zero,ymm12[5,u,u,u,u,u],zero,ymm12[6,u,u,u,u,u,23],zero,ymm12[u,u,u,u,u,24],zero,ymm12[u,u] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm13 = [255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255] +; AVX512DQ-NEXT: vpternlogq $200, %ymm11, %ymm13, %ymm12 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm11 = ymm7[0,2,0,2] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm11 = ymm11[u,u,u,u,0,8],zero,ymm11[u,u,u,u,1,9],zero,ymm11[u,u,u,u,18,26],zero,ymm11[u,u,u,u,19,27],zero,ymm11[u,u,u,u] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm12, %zmm11, %zmm11 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm12 = xmm2[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm12 = ymm12[0,0,1,0] +; AVX512DQ-NEXT: vpandn %ymm12, %ymm13, %ymm12 +; AVX512DQ-NEXT: vpshuflw {{.*#+}} xmm13 = xmm2[1,1,0,0,4,5,6,7] +; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm13 = xmm13[0,1,2,0] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm13 = ymm13[0,0,1,0] +; AVX512DQ-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm13, %ymm13 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm12 +; AVX512DQ-NEXT: vporq %zmm12, %zmm11, %zmm11 +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm11 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm8 = ymm8[3,1,1,3] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm8[1],zero,zero,ymm8[u,u,u,10,2],zero,zero,ymm8[u,u,u,11,3],zero,zero,ymm8[u,u,u,20,28],zero,zero,ymm8[u,u,u,21,29],zero,zero,ymm8[u] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm9 = ymm9[1,3,3,1] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = zero,ymm9[1,9,u,u,u],zero,zero,ymm9[2,10,u,u,u],zero,zero,ymm9[3,19,u,u,u],zero,zero,ymm9[28,20,u,u,u],zero,zero,ymm9[29,21,u] +; AVX512DQ-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm9 = xmm2[0,1,2,3,4,5,5,6] +; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm9 = xmm9[2,2,3,3] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm9 = ymm9[0,1,0,1] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm7[1,3,1,3] ; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[u,u,u,1,9],zero,ymm7[u,u,u,u,2,10],zero,ymm7[u,u,u,u,19,27],zero,ymm7[u,u,u,u,20,28],zero,ymm7[u,u,u,u,21] -; AVX512DQ-NEXT: vpternlogq $244, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm6, %ymm7 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm7 -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm5, %zmm7, %zmm4 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm6 = ymm3[u,u,u,u,u,5],zero,ymm3[u,u,u,u,u,6],zero,ymm3[u,u,u,u,u],zero,ymm3[23,u,u,u,u,u],zero,ymm3[24,u,u,u,u] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm3[2,3,0,1] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[u,u,u,u,u],zero,ymm7[5,u,u,u,u,u],zero,ymm7[6,u,u,u,u,u,23],zero,ymm7[u,u,u,u,u,24],zero,ymm7[u,u,u,u] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm8 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255] -; AVX512DQ-NEXT: vpternlogq $50, %ymm6, %ymm8, %ymm7 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm3[0,2,0,2] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = zero,zero,ymm3[0,8,u,u,u],zero,zero,ymm3[1,9,u,u,u],zero,zero,ymm3[18,26,u,u,u],zero,zero,ymm3[19,27,u,u,u],zero,zero,ymm3[20,28] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm7, %zmm3, %zmm3 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm6 = ymm2[u,u,u,5],zero,ymm2[u,u,u,u,u,6],zero,ymm2[u,u,u,u,u],zero,ymm2[23,u,u,u,u,u],zero,ymm2[24,u,u,u,u,u],zero -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm2[2,3,0,1] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[u,u,u],zero,ymm7[5,u,u,u,u,u],zero,ymm7[6,u,u,u,u,u,23],zero,ymm7[u,u,u,u,u,24],zero,ymm7[u,u,u,u,u,25] -; AVX512DQ-NEXT: vpternlogq $200, %ymm6, %ymm8, %ymm7 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm2[0,2,0,2] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[0,8],zero,zero,ymm2[u,u,u,1,9],zero,zero,ymm2[u,u,u,2,10],zero,zero,ymm2[u,u,u,19,27],zero,zero,ymm2[u,u,u,20,28],zero,zero -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm7, %zmm2, %zmm2 -; AVX512DQ-NEXT: vporq %zmm3, %zmm2, %zmm2 -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm3 = xmm1[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm3[0,0,1,0] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm6 = [255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255] -; AVX512DQ-NEXT: vpandn %ymm3, %ymm6, %ymm3 -; AVX512DQ-NEXT: vpshuflw {{.*#+}} xmm1 = xmm1[1,1,0,0,4,5,6,7] -; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[0,1,2,0] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,1,0] -; AVX512DQ-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm1 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm0[4],zero,ymm0[u,u,u,u,u,5],zero,ymm0[u,u,u,u,u,6],zero,ymm0[u,u,u,u,u],zero,ymm0[23,u,u,u,u,u],zero,ymm0[24,u,u] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm0[2,3,0,1] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = zero,ymm7[4,u,u,u,u,u],zero,ymm7[5,u,u,u,u,u],zero,ymm7[6,u,u,u,u,u,23],zero,ymm7[u,u,u,u,u,24],zero,ymm7[u,u] -; AVX512DQ-NEXT: vpternlogq $200, %ymm3, %ymm6, %ymm7 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,0,2] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,0,8],zero,ymm0[u,u,u,u,1,9],zero,ymm0[u,u,u,u,18,26],zero,ymm0[u,u,u,u,19,27],zero,ymm0[u,u,u,u] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm7, %zmm0, %zmm0 -; AVX512DQ-NEXT: vporq %zmm1, %zmm0, %zmm0 -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 -; AVX512DQ-NEXT: vmovdqa %xmm5, 96(%rax) -; AVX512DQ-NEXT: vmovdqa64 %zmm0, (%rax) -; AVX512DQ-NEXT: vmovdqa %ymm4, 64(%rax) +; AVX512DQ-NEXT: vpternlogq $244, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm9, %ymm7 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm8, %ymm7 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm5[8],xmm6[8],xmm5[9],xmm6[9],xmm5[10],xmm6[10],xmm5[11],xmm6[11],xmm5[12],xmm6[12],xmm5[13],xmm6[13],xmm5[14],xmm6[14],xmm5[15],xmm6[15] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[u,u],zero,zero,xmm5[12,13,u,u,u],zero,zero,xmm5[14,15,u,u,u] +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[u,u,12,13],zero,zero,xmm0[u,u,u,14,15],zero,zero,xmm0[u,u,u] +; AVX512DQ-NEXT: vpor %xmm5, %xmm0, %xmm0 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[10],zero,xmm1[u,u,u,u,13,12],zero,xmm1[u,u,u,u,15,14],zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm2 = zero,xmm2[13,u,u,u,u],zero,zero,xmm2[14,u,u,u,u],zero,zero,xmm2[15] +; AVX512DQ-NEXT: vpor %xmm2, %xmm1, %xmm1 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1 +; AVX512DQ-NEXT: vinserti32x4 $2, %xmm1, %zmm7, %zmm0 +; AVX512DQ-NEXT: vmovdqa %xmm1, 96(%rax) +; AVX512DQ-NEXT: vmovdqa %ymm0, 64(%rax) +; AVX512DQ-NEXT: vmovdqa64 %zmm11, (%rax) ; AVX512DQ-NEXT: vzeroupper ; AVX512DQ-NEXT: retq ; @@ -2280,70 +2275,69 @@ define void @store_i8_stride7_vf16(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP: # %bb.0: ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %xmm2 -; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %xmm3 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %xmm4 -; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %xmm5 -; AVX512DQ-FCP-NEXT: vmovdqa (%r8), %xmm1 -; AVX512DQ-FCP-NEXT: vmovdqa (%r10), %xmm0 -; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm5, %ymm4, %ymm6 -; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm7 -; AVX512DQ-FCP-NEXT: vinserti128 $1, (%r9), %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm1 -; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,u],zero,zero,xmm4[12,13,u,u,u],zero,zero,xmm4[14,15,u,u,u] -; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm2[8],xmm3[8],xmm2[9],xmm3[9],xmm2[10],xmm3[10],xmm2[11],xmm3[11],xmm2[12],xmm3[12],xmm2[13],xmm3[13],xmm2[14],xmm3[14],xmm2[15],xmm3[15] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm2 = xmm2[u,u,12,13],zero,zero,xmm2[u,u,u,14,15],zero,zero,xmm2[u,u,u] -; AVX512DQ-FCP-NEXT: vpor %xmm4, %xmm2, %xmm2 -; AVX512DQ-FCP-NEXT: vextracti128 $1, %ymm1, %xmm3 -; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm3[8],xmm1[8],xmm3[9],xmm1[9],xmm3[10],xmm1[10],xmm3[11],xmm1[11],xmm3[12],xmm1[12],xmm3[13],xmm1[13],xmm3[14],xmm1[14],xmm3[15],xmm1[15] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm3 = xmm3[10],zero,xmm3[u,u,u,u,13,12],zero,xmm3[u,u,u,u,15,14],zero -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm4 = zero,xmm0[13,u,u,u,u],zero,zero,xmm0[14,u,u,u,u],zero,zero,xmm0[15] -; AVX512DQ-FCP-NEXT: vpor %xmm4, %xmm3, %xmm3 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm3 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm7[3,1,1,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[1],zero,zero,ymm2[u,u,u,10,2],zero,zero,ymm2[u,u,u,11,3],zero,zero,ymm2[u,u,u,20,28],zero,zero,ymm2[u,u,u,21,29],zero,zero,ymm2[u] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm6[1,3,3,1] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm4 = zero,ymm4[1,9,u,u,u],zero,zero,ymm4[2,10,u,u,u],zero,zero,ymm4[3,19,u,u,u],zero,zero,ymm4[28,20,u,u,u],zero,zero,ymm4[29,21,u] -; AVX512DQ-FCP-NEXT: vpor %ymm2, %ymm4, %ymm2 -; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm4 = xmm0[0,1,2,3,4,5,5,6] -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [2,2,3,3,2,2,3,3] -; AVX512DQ-FCP-NEXT: # ymm5 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpermd %ymm4, %ymm5, %ymm4 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm1[1,3,1,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm5[u,u,u,1,9],zero,ymm5[u,u,u,u,2,10],zero,ymm5[u,u,u,u,19,27],zero,ymm5[u,u,u,u,20,28],zero,ymm5[u,u,u,u,21] -; AVX512DQ-FCP-NEXT: vpternlogq $244, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm5 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm5 -; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm3, %zmm5, %zmm2 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm6[0,2,0,2] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm4 = zero,zero,ymm4[0,8,u,u,u],zero,zero,ymm4[1,9,u,u,u],zero,zero,ymm4[18,26,u,u,u],zero,zero,ymm4[19,27,u,u,u],zero,zero,ymm4[20,28] -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [1,5,2,6,1,5,2,6] -; AVX512DQ-FCP-NEXT: # ymm5 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpermd %ymm6, %ymm5, %ymm6 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[u,u,u],zero,zero,ymm6[1,5,u,u,u],zero,zero,ymm6[2,6,u,u,u],zero,zero,ymm6[19,23,u,u,u],zero,zero,ymm6[24,28,u,u,u],zero -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm4, %zmm4 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm7[0,2,0,2] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[0,8],zero,zero,ymm6[u,u,u,1,9],zero,zero,ymm6[u,u,u,2,10],zero,zero,ymm6[u,u,u,19,27],zero,zero,ymm6[u,u,u,20,28],zero,zero -; AVX512DQ-FCP-NEXT: vpermd %ymm7, %ymm5, %ymm7 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[u,u,u,1,5],zero,zero,ymm7[u,u,u,2,6],zero,zero,ymm7[u,u,u,19,23],zero,zero,ymm7[u,u,u,24,28],zero,zero,ymm7[u,u,u,25] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm6, %zmm6 -; AVX512DQ-FCP-NEXT: vporq %zmm4, %zmm6, %zmm4 -; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} xmm6 = xmm0[1,1,0,0,4,5,6,7] -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm7 = [0,1,0,1,0,0,0,0] -; AVX512DQ-FCP-NEXT: vpermd %ymm6, %ymm7, %ymm6 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,0] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm6, %zmm0 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm1[0,2,0,2] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[u,u,u,u,0,8],zero,ymm6[u,u,u,u,1,9],zero,ymm6[u,u,u,u,18,26],zero,ymm6[u,u,u,u,19,27],zero,ymm6[u,u,u,u] -; AVX512DQ-FCP-NEXT: vpermd %ymm1, %ymm5, %ymm1 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[0,4],zero,ymm1[u,u,u,u,1,5],zero,ymm1[u,u,u,u,2,6],zero,ymm1[u,u,u,u,19,23],zero,ymm1[u,u,u,u,24,28],zero,ymm1[u] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm6, %zmm1 -; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 -; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm4, %zmm1 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm3, 96(%rax) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm1, (%rax) -; AVX512DQ-FCP-NEXT: vmovdqa %ymm2, 64(%rax) +; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %xmm1 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %xmm5 +; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %xmm6 +; AVX512DQ-FCP-NEXT: vmovdqa (%r8), %xmm3 +; AVX512DQ-FCP-NEXT: vmovdqa (%r9), %xmm4 +; AVX512DQ-FCP-NEXT: vmovdqa (%r10), %xmm2 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm7 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm6, %ymm5, %ymm8 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm4, %ymm3, %ymm9 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm8[0,2,0,2] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = zero,zero,ymm10[0,8,u,u,u],zero,zero,ymm10[1,9,u,u,u],zero,zero,ymm10[18,26,u,u,u],zero,zero,ymm10[19,27,u,u,u],zero,zero,ymm10[20,28] +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [1,5,2,6,1,5,2,6] +; AVX512DQ-FCP-NEXT: # ymm11 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpermd %ymm8, %ymm11, %ymm12 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm12[u,u,u],zero,zero,ymm12[1,5,u,u,u],zero,zero,ymm12[2,6,u,u,u],zero,zero,ymm12[19,23,u,u,u],zero,zero,ymm12[24,28,u,u,u],zero +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm10, %zmm10 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm7[0,2,0,2] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm12[0,8],zero,zero,ymm12[u,u,u,1,9],zero,zero,ymm12[u,u,u,2,10],zero,zero,ymm12[u,u,u,19,27],zero,zero,ymm12[u,u,u,20,28],zero,zero +; AVX512DQ-FCP-NEXT: vpermd %ymm7, %ymm11, %ymm13 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm13[u,u,u,1,5],zero,zero,ymm13[u,u,u,2,6],zero,zero,ymm13[u,u,u,19,23],zero,zero,ymm13[u,u,u,24,28],zero,zero,ymm13[u,u,u,25] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm12, %zmm12 +; AVX512DQ-FCP-NEXT: vporq %zmm10, %zmm12, %zmm10 +; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} xmm12 = xmm2[1,1,0,0,4,5,6,7] +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm13 = [0,1,0,1,0,0,0,0] +; AVX512DQ-FCP-NEXT: vpermd %ymm12, %ymm13, %ymm12 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm13 = xmm2[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[0,0,1,0] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm12, %zmm12 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm9[0,2,0,2] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm13[u,u,u,u,0,8],zero,ymm13[u,u,u,u,1,9],zero,ymm13[u,u,u,u,18,26],zero,ymm13[u,u,u,u,19,27],zero,ymm13[u,u,u,u] +; AVX512DQ-FCP-NEXT: vpermd %ymm9, %ymm11, %ymm11 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm11[0,4],zero,ymm11[u,u,u,u,1,5],zero,ymm11[u,u,u,u,2,6],zero,ymm11[u,u,u,u,19,23],zero,ymm11[u,u,u,u,24,28],zero,ymm11[u] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm13, %zmm11 +; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm12, %zmm11 +; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm11 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[3,1,1,3] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[1],zero,zero,ymm7[u,u,u,10,2],zero,zero,ymm7[u,u,u,11,3],zero,zero,ymm7[u,u,u,20,28],zero,zero,ymm7[u,u,u,21,29],zero,zero,ymm7[u] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[1,3,3,1] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm8 = zero,ymm8[1,9,u,u,u],zero,zero,ymm8[2,10,u,u,u],zero,zero,ymm8[3,19,u,u,u],zero,zero,ymm8[28,20,u,u,u],zero,zero,ymm8[29,21,u] +; AVX512DQ-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 +; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm8 = xmm2[0,1,2,3,4,5,5,6] +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [2,2,3,3,2,2,3,3] +; AVX512DQ-FCP-NEXT: # ymm10 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpermd %ymm8, %ymm10, %ymm8 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[1,3,1,3] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm9[u,u,u,1,9],zero,ymm9[u,u,u,u,2,10],zero,ymm9[u,u,u,u,19,27],zero,ymm9[u,u,u,u,20,28],zero,ymm9[u,u,u,u,21] +; AVX512DQ-FCP-NEXT: vpternlogq $244, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm8, %ymm9 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm7, %ymm9 +; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm5[8],xmm6[8],xmm5[9],xmm6[9],xmm5[10],xmm6[10],xmm5[11],xmm6[11],xmm5[12],xmm6[12],xmm5[13],xmm6[13],xmm5[14],xmm6[14],xmm5[15],xmm6[15] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[u,u],zero,zero,xmm5[12,13,u,u,u],zero,zero,xmm5[14,15,u,u,u] +; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[u,u,12,13],zero,zero,xmm0[u,u,u,14,15],zero,zero,xmm0[u,u,u] +; AVX512DQ-FCP-NEXT: vpor %xmm5, %xmm0, %xmm0 +; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[10],zero,xmm1[u,u,u,u,13,12],zero,xmm1[u,u,u,u,15,14],zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm2 = zero,xmm2[13,u,u,u,u],zero,zero,xmm2[14,u,u,u,u],zero,zero,xmm2[15] +; AVX512DQ-FCP-NEXT: vpor %xmm2, %xmm1, %xmm1 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1 +; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm9, %zmm0 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm1, 96(%rax) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm11, (%rax) +; AVX512DQ-FCP-NEXT: vmovdqa %ymm0, 64(%rax) ; AVX512DQ-FCP-NEXT: vzeroupper ; AVX512DQ-FCP-NEXT: retq ; diff --git a/llvm/test/CodeGen/X86/zero_extend_vector_inreg_of_broadcast.ll b/llvm/test/CodeGen/X86/zero_extend_vector_inreg_of_broadcast.ll index 11f422d67154..99e8cdb179c8 100644 --- a/llvm/test/CodeGen/X86/zero_extend_vector_inreg_of_broadcast.ll +++ b/llvm/test/CodeGen/X86/zero_extend_vector_inreg_of_broadcast.ll @@ -314,8 +314,8 @@ define void @vec64_i16_widen_to_i32_factor2_broadcast_to_v2i32_factor2(ptr %in.v ; ; AVX512F-LABEL: vec64_i16_widen_to_i32_factor2_broadcast_to_v2i32_factor2: ; AVX512F: # %bb.0: -; AVX512F-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512F-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512F-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512F-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512F-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,1,10,11,0,1,14,15,u,u,u,u,u,u,u,u] ; AVX512F-NEXT: vpaddb (%rdx), %ymm0, %ymm0 ; AVX512F-NEXT: vmovdqa %ymm0, (%rcx) @@ -324,8 +324,8 @@ define void @vec64_i16_widen_to_i32_factor2_broadcast_to_v2i32_factor2(ptr %in.v ; ; AVX512DQ-LABEL: vec64_i16_widen_to_i32_factor2_broadcast_to_v2i32_factor2: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512DQ-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,1,10,11,0,1,14,15,u,u,u,u,u,u,u,u] ; AVX512DQ-NEXT: vpaddb (%rdx), %ymm0, %ymm0 ; AVX512DQ-NEXT: vmovdqa %ymm0, (%rcx) @@ -981,7 +981,7 @@ define void @vec128_i32_widen_to_i64_factor2_broadcast_to_v2i64_factor2(ptr %in. ; AVX512F-NEXT: vpmovsxbd {{.*#+}} xmm0 = [0,5,0,7] ; AVX512F-NEXT: vmovdqa (%rdi), %ymm1 ; AVX512F-NEXT: vpaddb (%rsi), %ymm1, %ymm1 -; AVX512F-NEXT: vpermd %zmm1, %zmm0, %zmm0 +; AVX512F-NEXT: vpermd %ymm1, %ymm0, %ymm0 ; AVX512F-NEXT: vpaddb (%rdx), %ymm0, %ymm0 ; AVX512F-NEXT: vmovdqa %ymm0, (%rcx) ; AVX512F-NEXT: vzeroupper @@ -992,7 +992,7 @@ define void @vec128_i32_widen_to_i64_factor2_broadcast_to_v2i64_factor2(ptr %in. ; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} xmm0 = [0,5,0,7] ; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm1 ; AVX512DQ-NEXT: vpaddb (%rsi), %ymm1, %ymm1 -; AVX512DQ-NEXT: vpermd %zmm1, %zmm0, %zmm0 +; AVX512DQ-NEXT: vpermd %ymm1, %ymm0, %ymm0 ; AVX512DQ-NEXT: vpaddb (%rdx), %ymm0, %ymm0 ; AVX512DQ-NEXT: vmovdqa %ymm0, (%rcx) ; AVX512DQ-NEXT: vzeroupper @@ -4026,10 +4026,10 @@ define void @vec384_i16_widen_to_i64_factor4_broadcast_to_v6i64_factor6(ptr %in. ; ; AVX512F-FAST-LABEL: vec384_i16_widen_to_i64_factor4_broadcast_to_v6i64_factor6: ; AVX512F-FAST: # %bb.0: -; AVX512F-FAST-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512F-FAST-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512F-FAST-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512F-FAST-NEXT: vmovdqa 48(%rdi), %xmm1 ; AVX512F-FAST-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 +; AVX512F-FAST-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512F-FAST-NEXT: vpbroadcastq %xmm0, %ymm2 ; AVX512F-FAST-NEXT: vpblendw {{.*#+}} ymm1 = ymm2[0],ymm1[1,2,3],ymm2[4],ymm1[5,6,7],ymm2[8],ymm1[9,10,11],ymm2[12],ymm1[13,14,15] ; AVX512F-FAST-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm1 @@ -4062,10 +4062,10 @@ define void @vec384_i16_widen_to_i64_factor4_broadcast_to_v6i64_factor6(ptr %in. ; ; AVX512DQ-FAST-LABEL: vec384_i16_widen_to_i64_factor4_broadcast_to_v6i64_factor6: ; AVX512DQ-FAST: # %bb.0: -; AVX512DQ-FAST-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512DQ-FAST-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512DQ-FAST-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512DQ-FAST-NEXT: vmovdqa 48(%rdi), %xmm1 ; AVX512DQ-FAST-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 +; AVX512DQ-FAST-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512DQ-FAST-NEXT: vpbroadcastq %xmm0, %ymm2 ; AVX512DQ-FAST-NEXT: vpblendw {{.*#+}} ymm1 = ymm2[0],ymm1[1,2,3],ymm2[4],ymm1[5,6,7],ymm2[8],ymm1[9,10,11],ymm2[12],ymm1[13,14,15] ; AVX512DQ-FAST-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm1 @@ -4541,9 +4541,9 @@ define void @vec384_i16_widen_to_i192_factor12_broadcast_to_v2i192_factor2(ptr % ; ; AVX512F-LABEL: vec384_i16_widen_to_i192_factor12_broadcast_to_v2i192_factor2: ; AVX512F: # %bb.0: -; AVX512F-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512F-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512F-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512F-NEXT: vmovdqa 48(%rdi), %xmm1 +; AVX512F-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512F-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 ; AVX512F-NEXT: vpblendw {{.*#+}} xmm1 = xmm0[0],xmm1[1,2,3,4,5,6,7] ; AVX512F-NEXT: vpbroadcastw %xmm0, %ymm0 @@ -4559,9 +4559,9 @@ define void @vec384_i16_widen_to_i192_factor12_broadcast_to_v2i192_factor2(ptr % ; ; AVX512DQ-LABEL: vec384_i16_widen_to_i192_factor12_broadcast_to_v2i192_factor2: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512DQ-NEXT: vpaddb (%rsi), %ymm0, %ymm0 +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 ; AVX512DQ-NEXT: vmovdqa 48(%rdi), %xmm1 +; AVX512DQ-NEXT: vpaddb (%rsi), %xmm0, %xmm0 ; AVX512DQ-NEXT: vpaddb 48(%rsi), %xmm1, %xmm1 ; AVX512DQ-NEXT: vpblendw {{.*#+}} xmm1 = xmm0[0],xmm1[1,2,3,4,5,6,7] ; AVX512DQ-NEXT: vpbroadcastw %xmm0, %ymm0 -- GitLab From 78eac466095c205988ef1e2380033d042a169a3b Mon Sep 17 00:00:00 2001 From: Sergio Afonso Date: Fri, 12 Apr 2024 12:42:41 +0100 Subject: [PATCH 051/464] [Flang][OpenMP][Lower] Use clause operand structures (#86802) This patch updates Flang lowering to use the new set of OpenMP clause operand structures and their groupings into directive-specific sets of clause operands. It simplifies the passing of information from the clause processor and the creation of operations. The `DataSharingProcessor` is slightly modified to not hold delayed privatization state. Instead, optional arguments are added to `processStep1` which are only passed when delayed privatization is used. This enables using the clause operand structure for `private` and removes the need for the ad-hoc `DelayedPrivatizationInfo` structure. The processing of the `schedule` clause is updated to process the `chunk` modifier rather than requiring two separate calls to the `ClauseProcessor`. Lowering of a block-associated `ordered` construct is updated to emit a TODO error if the `simd` clause is specified, since it is not currently supported by the `ClauseProcessor` or later compilation stages. Removed processing of `schedule` from `omp.simdloop`, as it doesn't apply to `simd` constructs. --- flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 273 +++++---- flang/lib/Lower/OpenMP/ClauseProcessor.h | 109 ++-- .../lib/Lower/OpenMP/DataSharingProcessor.cpp | 38 +- flang/lib/Lower/OpenMP/DataSharingProcessor.h | 45 +- flang/lib/Lower/OpenMP/OpenMP.cpp | 536 +++++++----------- .../Dialect/OpenMP/OpenMPClauseOperands.h | 10 +- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 4 + mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 6 + 8 files changed, 459 insertions(+), 562 deletions(-) diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index fb24c8d1fe3e..ae0d8bd37228 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -162,14 +162,13 @@ getIfClauseOperand(Fortran::lower::AbstractConverter &converter, ifVal); } -static void -addUseDeviceClause(Fortran::lower::AbstractConverter &converter, - const omp::ObjectList &objects, - llvm::SmallVectorImpl &operands, - llvm::SmallVectorImpl &useDeviceTypes, - llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl - &useDeviceSymbols) { +static void addUseDeviceClause( + Fortran::lower::AbstractConverter &converter, + const omp::ObjectList &objects, + llvm::SmallVectorImpl &operands, + llvm::SmallVectorImpl &useDeviceTypes, + llvm::SmallVectorImpl &useDeviceLocs, + llvm::SmallVectorImpl &useDeviceSyms) { genObjectList(objects, converter, operands); for (mlir::Value &operand : operands) { checkMapType(operand.getLoc(), operand.getType()); @@ -177,25 +176,24 @@ addUseDeviceClause(Fortran::lower::AbstractConverter &converter, useDeviceLocs.push_back(operand.getLoc()); } for (const omp::Object &object : objects) - useDeviceSymbols.push_back(object.id()); + useDeviceSyms.push_back(object.id()); } static void convertLoopBounds(Fortran::lower::AbstractConverter &converter, mlir::Location loc, - llvm::SmallVectorImpl &lowerBound, - llvm::SmallVectorImpl &upperBound, - llvm::SmallVectorImpl &step, + mlir::omp::CollapseClauseOps &result, std::size_t loopVarTypeSize) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); // The types of lower bound, upper bound, and step are converted into the // type of the loop variable if necessary. mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize); - for (unsigned it = 0; it < (unsigned)lowerBound.size(); it++) { - lowerBound[it] = - firOpBuilder.createConvert(loc, loopVarType, lowerBound[it]); - upperBound[it] = - firOpBuilder.createConvert(loc, loopVarType, upperBound[it]); - step[it] = firOpBuilder.createConvert(loc, loopVarType, step[it]); + for (unsigned it = 0; it < (unsigned)result.loopLBVar.size(); it++) { + result.loopLBVar[it] = + firOpBuilder.createConvert(loc, loopVarType, result.loopLBVar[it]); + result.loopUBVar[it] = + firOpBuilder.createConvert(loc, loopVarType, result.loopUBVar[it]); + result.loopStepVar[it] = + firOpBuilder.createConvert(loc, loopVarType, result.loopStepVar[it]); } } @@ -205,9 +203,7 @@ static void convertLoopBounds(Fortran::lower::AbstractConverter &converter, bool ClauseProcessor::processCollapse( mlir::Location currentLocation, Fortran::lower::pft::Evaluation &eval, - llvm::SmallVectorImpl &lowerBound, - llvm::SmallVectorImpl &upperBound, - llvm::SmallVectorImpl &step, + mlir::omp::CollapseClauseOps &result, llvm::SmallVectorImpl &iv) const { bool found = false; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -238,15 +234,15 @@ bool ClauseProcessor::processCollapse( std::get_if(&loopControl->u); assert(bounds && "Expected bounds for worksharing do loop"); Fortran::lower::StatementContext stmtCtx; - lowerBound.push_back(fir::getBase(converter.genExprValue( + result.loopLBVar.push_back(fir::getBase(converter.genExprValue( *Fortran::semantics::GetExpr(bounds->lower), stmtCtx))); - upperBound.push_back(fir::getBase(converter.genExprValue( + result.loopUBVar.push_back(fir::getBase(converter.genExprValue( *Fortran::semantics::GetExpr(bounds->upper), stmtCtx))); if (bounds->step) { - step.push_back(fir::getBase(converter.genExprValue( + result.loopStepVar.push_back(fir::getBase(converter.genExprValue( *Fortran::semantics::GetExpr(bounds->step), stmtCtx))); } else { // If `step` is not present, assume it as `1`. - step.push_back(firOpBuilder.createIntegerConstant( + result.loopStepVar.push_back(firOpBuilder.createIntegerConstant( currentLocation, firOpBuilder.getIntegerType(32), 1)); } iv.push_back(bounds->name.thing.symbol); @@ -257,8 +253,7 @@ bool ClauseProcessor::processCollapse( &*std::next(doConstructEval->getNestedEvaluations().begin()); } while (collapseValue > 0); - convertLoopBounds(converter, currentLocation, lowerBound, upperBound, step, - loopVarTypeSize); + convertLoopBounds(converter, currentLocation, result, loopVarTypeSize); return found; } @@ -286,7 +281,7 @@ bool ClauseProcessor::processDefault() const { } bool ClauseProcessor::processDevice(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const { + mlir::omp::DeviceClauseOps &result) const { const Fortran::parser::CharBlock *source = nullptr; if (auto *clause = findUniqueClause(&source)) { mlir::Location clauseLocation = converter.genLocation(*source); @@ -298,25 +293,26 @@ bool ClauseProcessor::processDevice(Fortran::lower::StatementContext &stmtCtx, } } const auto &deviceExpr = std::get(clause->t); - result = fir::getBase(converter.genExprValue(deviceExpr, stmtCtx)); + result.deviceVar = + fir::getBase(converter.genExprValue(deviceExpr, stmtCtx)); return true; } return false; } bool ClauseProcessor::processDeviceType( - mlir::omp::DeclareTargetDeviceType &result) const { + mlir::omp::DeviceTypeClauseOps &result) const { if (auto *clause = findUniqueClause()) { // Case: declare target ... device_type(any | host | nohost) switch (clause->v) { case omp::clause::DeviceType::DeviceTypeDescription::Nohost: - result = mlir::omp::DeclareTargetDeviceType::nohost; + result.deviceType = mlir::omp::DeclareTargetDeviceType::nohost; break; case omp::clause::DeviceType::DeviceTypeDescription::Host: - result = mlir::omp::DeclareTargetDeviceType::host; + result.deviceType = mlir::omp::DeclareTargetDeviceType::host; break; case omp::clause::DeviceType::DeviceTypeDescription::Any: - result = mlir::omp::DeclareTargetDeviceType::any; + result.deviceType = mlir::omp::DeclareTargetDeviceType::any; break; } return true; @@ -325,7 +321,7 @@ bool ClauseProcessor::processDeviceType( } bool ClauseProcessor::processFinal(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const { + mlir::omp::FinalClauseOps &result) const { const Fortran::parser::CharBlock *source = nullptr; if (auto *clause = findUniqueClause(&source)) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -333,100 +329,108 @@ bool ClauseProcessor::processFinal(Fortran::lower::StatementContext &stmtCtx, mlir::Value finalVal = fir::getBase(converter.genExprValue(clause->v, stmtCtx)); - result = firOpBuilder.createConvert(clauseLocation, - firOpBuilder.getI1Type(), finalVal); + result.finalVar = firOpBuilder.createConvert( + clauseLocation, firOpBuilder.getI1Type(), finalVal); return true; } return false; } -bool ClauseProcessor::processHint(mlir::IntegerAttr &result) const { +bool ClauseProcessor::processHint(mlir::omp::HintClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); int64_t hintValue = *Fortran::evaluate::ToInt64(clause->v); - result = firOpBuilder.getI64IntegerAttr(hintValue); + result.hintAttr = firOpBuilder.getI64IntegerAttr(hintValue); return true; } return false; } -bool ClauseProcessor::processMergeable(mlir::UnitAttr &result) const { - return markClauseOccurrence(result); +bool ClauseProcessor::processMergeable( + mlir::omp::MergeableClauseOps &result) const { + return markClauseOccurrence(result.mergeableAttr); } -bool ClauseProcessor::processNowait(mlir::UnitAttr &result) const { - return markClauseOccurrence(result); +bool ClauseProcessor::processNowait(mlir::omp::NowaitClauseOps &result) const { + return markClauseOccurrence(result.nowaitAttr); } -bool ClauseProcessor::processNumTeams(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const { +bool ClauseProcessor::processNumTeams( + Fortran::lower::StatementContext &stmtCtx, + mlir::omp::NumTeamsClauseOps &result) const { // TODO Get lower and upper bounds for num_teams when parser is updated to // accept both. if (auto *clause = findUniqueClause()) { // auto lowerBound = std::get>(clause->t); auto &upperBound = std::get(clause->t); - result = fir::getBase(converter.genExprValue(upperBound, stmtCtx)); + result.numTeamsUpperVar = + fir::getBase(converter.genExprValue(upperBound, stmtCtx)); return true; } return false; } bool ClauseProcessor::processNumThreads( - Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { + Fortran::lower::StatementContext &stmtCtx, + mlir::omp::NumThreadsClauseOps &result) const { if (auto *clause = findUniqueClause()) { // OMPIRBuilder expects `NUM_THREADS` clause as a `Value`. - result = fir::getBase(converter.genExprValue(clause->v, stmtCtx)); + result.numThreadsVar = + fir::getBase(converter.genExprValue(clause->v, stmtCtx)); return true; } return false; } -bool ClauseProcessor::processOrdered(mlir::IntegerAttr &result) const { +bool ClauseProcessor::processOrdered( + mlir::omp::OrderedClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); int64_t orderedClauseValue = 0l; if (clause->v.has_value()) orderedClauseValue = *Fortran::evaluate::ToInt64(*clause->v); - result = firOpBuilder.getI64IntegerAttr(orderedClauseValue); + result.orderedAttr = firOpBuilder.getI64IntegerAttr(orderedClauseValue); return true; } return false; } -bool ClauseProcessor::processPriority(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const { +bool ClauseProcessor::processPriority( + Fortran::lower::StatementContext &stmtCtx, + mlir::omp::PriorityClauseOps &result) const { if (auto *clause = findUniqueClause()) { - result = fir::getBase(converter.genExprValue(clause->v, stmtCtx)); + result.priorityVar = + fir::getBase(converter.genExprValue(clause->v, stmtCtx)); return true; } return false; } bool ClauseProcessor::processProcBind( - mlir::omp::ClauseProcBindKindAttr &result) const { + mlir::omp::ProcBindClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - result = genProcBindKindAttr(firOpBuilder, *clause); + result.procBindKindAttr = genProcBindKindAttr(firOpBuilder, *clause); return true; } return false; } -bool ClauseProcessor::processSafelen(mlir::IntegerAttr &result) const { +bool ClauseProcessor::processSafelen( + mlir::omp::SafelenClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); const std::optional safelenVal = Fortran::evaluate::ToInt64(clause->v); - result = firOpBuilder.getI64IntegerAttr(*safelenVal); + result.safelenAttr = firOpBuilder.getI64IntegerAttr(*safelenVal); return true; } return false; } bool ClauseProcessor::processSchedule( - mlir::omp::ClauseScheduleKindAttr &valAttr, - mlir::omp::ScheduleModifierAttr &modifierAttr, - mlir::UnitAttr &simdModifierAttr) const { + Fortran::lower::StatementContext &stmtCtx, + mlir::omp::ScheduleClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::MLIRContext *context = firOpBuilder.getContext(); @@ -451,53 +455,51 @@ bool ClauseProcessor::processSchedule( break; } - mlir::omp::ScheduleModifier scheduleModifier = getScheduleModifier(*clause); + result.scheduleValAttr = + mlir::omp::ClauseScheduleKindAttr::get(context, scheduleKind); + mlir::omp::ScheduleModifier scheduleModifier = getScheduleModifier(*clause); if (scheduleModifier != mlir::omp::ScheduleModifier::none) - modifierAttr = + result.scheduleModAttr = mlir::omp::ScheduleModifierAttr::get(context, scheduleModifier); if (getSimdModifier(*clause) != mlir::omp::ScheduleModifier::none) - simdModifierAttr = firOpBuilder.getUnitAttr(); + result.scheduleSimdAttr = firOpBuilder.getUnitAttr(); - valAttr = mlir::omp::ClauseScheduleKindAttr::get(context, scheduleKind); - return true; - } - return false; -} - -bool ClauseProcessor::processScheduleChunk( - Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { - if (auto *clause = findUniqueClause()) { if (const auto &chunkExpr = std::get(clause->t)) - result = fir::getBase(converter.genExprValue(*chunkExpr, stmtCtx)); + result.scheduleChunkVar = + fir::getBase(converter.genExprValue(*chunkExpr, stmtCtx)); + return true; } return false; } -bool ClauseProcessor::processSimdlen(mlir::IntegerAttr &result) const { +bool ClauseProcessor::processSimdlen( + mlir::omp::SimdlenClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); const std::optional simdlenVal = Fortran::evaluate::ToInt64(clause->v); - result = firOpBuilder.getI64IntegerAttr(*simdlenVal); + result.simdlenAttr = firOpBuilder.getI64IntegerAttr(*simdlenVal); return true; } return false; } bool ClauseProcessor::processThreadLimit( - Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { + Fortran::lower::StatementContext &stmtCtx, + mlir::omp::ThreadLimitClauseOps &result) const { if (auto *clause = findUniqueClause()) { - result = fir::getBase(converter.genExprValue(clause->v, stmtCtx)); + result.threadLimitVar = + fir::getBase(converter.genExprValue(clause->v, stmtCtx)); return true; } return false; } -bool ClauseProcessor::processUntied(mlir::UnitAttr &result) const { - return markClauseOccurrence(result); +bool ClauseProcessor::processUntied(mlir::omp::UntiedClauseOps &result) const { + return markClauseOccurrence(result.untiedAttr); } //===----------------------------------------------------------------------===// @@ -505,13 +507,12 @@ bool ClauseProcessor::processUntied(mlir::UnitAttr &result) const { //===----------------------------------------------------------------------===// bool ClauseProcessor::processAllocate( - llvm::SmallVectorImpl &allocatorOperands, - llvm::SmallVectorImpl &allocateOperands) const { + mlir::omp::AllocateClauseOps &result) const { return findRepeatableClause( [&](const omp::clause::Allocate &clause, const Fortran::parser::CharBlock &) { - genAllocateClause(converter, clause, allocatorOperands, - allocateOperands); + genAllocateClause(converter, clause, result.allocatorVars, + result.allocateVars); }); } @@ -660,10 +661,9 @@ createCopyFunc(mlir::Location loc, Fortran::lower::AbstractConverter &converter, return funcOp; } -bool ClauseProcessor::processCopyPrivate( +bool ClauseProcessor::processCopyprivate( mlir::Location currentLocation, - llvm::SmallVectorImpl ©PrivateVars, - llvm::SmallVectorImpl ©PrivateFuncs) const { + mlir::omp::CopyprivateClauseOps &result) const { auto addCopyPrivateVar = [&](Fortran::semantics::Symbol *sym) { mlir::Value symVal = converter.getSymbolAddress(*sym); auto declOp = symVal.getDefiningOp(); @@ -690,10 +690,10 @@ bool ClauseProcessor::processCopyPrivate( cpVar = alloca; } - copyPrivateVars.push_back(cpVar); + result.copyprivateVars.push_back(cpVar); mlir::func::FuncOp funcOp = createCopyFunc(currentLocation, converter, cpVar.getType(), attrs); - copyPrivateFuncs.push_back(mlir::SymbolRefAttr::get(funcOp)); + result.copyprivateFuncs.push_back(mlir::SymbolRefAttr::get(funcOp)); }; bool hasCopyPrivate = findRepeatableClause( @@ -714,9 +714,7 @@ bool ClauseProcessor::processCopyPrivate( return hasCopyPrivate; } -bool ClauseProcessor::processDepend( - llvm::SmallVectorImpl &dependTypeOperands, - llvm::SmallVectorImpl &dependOperands) const { +bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); return findRepeatableClause( @@ -731,7 +729,7 @@ bool ClauseProcessor::processDepend( mlir::omp::ClauseTaskDependAttr dependTypeOperand = genDependKindAttr(firOpBuilder, kind); - dependTypeOperands.append(objects.size(), dependTypeOperand); + result.dependTypeAttrs.append(objects.size(), dependTypeOperand); for (const omp::Object &object : objects) { assert(object.ref() && "Expecting designator"); @@ -746,13 +744,13 @@ bool ClauseProcessor::processDepend( Fortran::semantics::Symbol *sym = object.id(); const mlir::Value variable = converter.getSymbolAddress(*sym); - dependOperands.push_back(variable); + result.dependVars.push_back(variable); } }); } bool ClauseProcessor::processHasDeviceAddr( - llvm::SmallVectorImpl &operands, + mlir::omp::HasDeviceAddrClauseOps &result, llvm::SmallVectorImpl &isDeviceTypes, llvm::SmallVectorImpl &isDeviceLocs, llvm::SmallVectorImpl &isDeviceSymbols) @@ -760,14 +758,14 @@ bool ClauseProcessor::processHasDeviceAddr( return findRepeatableClause( [&](const omp::clause::HasDeviceAddr &devAddrClause, const Fortran::parser::CharBlock &) { - addUseDeviceClause(converter, devAddrClause.v, operands, isDeviceTypes, - isDeviceLocs, isDeviceSymbols); + addUseDeviceClause(converter, devAddrClause.v, result.hasDeviceAddrVars, + isDeviceTypes, isDeviceLocs, isDeviceSymbols); }); } bool ClauseProcessor::processIf( omp::clause::If::DirectiveNameModifier directiveName, - mlir::Value &result) const { + mlir::omp::IfClauseOps &result) const { bool found = false; findRepeatableClause( [&](const omp::clause::If &clause, @@ -778,7 +776,7 @@ bool ClauseProcessor::processIf( // Assume that, at most, a single 'if' clause will be applicable to the // given directive. if (operand) { - result = operand; + result.ifVar = operand; found = true; } }); @@ -786,7 +784,7 @@ bool ClauseProcessor::processIf( } bool ClauseProcessor::processIsDevicePtr( - llvm::SmallVectorImpl &operands, + mlir::omp::IsDevicePtrClauseOps &result, llvm::SmallVectorImpl &isDeviceTypes, llvm::SmallVectorImpl &isDeviceLocs, llvm::SmallVectorImpl &isDeviceSymbols) @@ -794,8 +792,8 @@ bool ClauseProcessor::processIsDevicePtr( return findRepeatableClause( [&](const omp::clause::IsDevicePtr &devPtrClause, const Fortran::parser::CharBlock &) { - addUseDeviceClause(converter, devPtrClause.v, operands, isDeviceTypes, - isDeviceLocs, isDeviceSymbols); + addUseDeviceClause(converter, devPtrClause.v, result.isDevicePtrVars, + isDeviceTypes, isDeviceLocs, isDeviceSymbols); }); } @@ -835,12 +833,10 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, bool ClauseProcessor::processMap( mlir::Location currentLocation, const llvm::omp::Directive &directive, - Fortran::lower::StatementContext &stmtCtx, - llvm::SmallVectorImpl &mapOperands, - llvm::SmallVectorImpl *mapSymTypes, + Fortran::lower::StatementContext &stmtCtx, mlir::omp::MapClauseOps &result, + llvm::SmallVectorImpl *mapSyms, llvm::SmallVectorImpl *mapSymLocs, - llvm::SmallVectorImpl *mapSymbols) - const { + llvm::SmallVectorImpl *mapSymTypes) const { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); return findRepeatableClause( [&](const omp::clause::Map &clause, @@ -915,25 +911,23 @@ bool ClauseProcessor::processMap( mapTypeBits), mlir::omp::VariableCaptureKind::ByRef, symAddr.getType()); - mapOperands.push_back(mapOp); - if (mapSymTypes) - mapSymTypes->push_back(symAddr.getType()); + result.mapVars.push_back(mapOp); + + if (mapSyms) + mapSyms->push_back(object.id()); if (mapSymLocs) mapSymLocs->push_back(symAddr.getLoc()); - - if (mapSymbols) - mapSymbols->push_back(object.id()); + if (mapSymTypes) + mapSymTypes->push_back(symAddr.getType()); } }); } bool ClauseProcessor::processReduction( - mlir::Location currentLocation, - llvm::SmallVectorImpl &outReductionVars, - llvm::SmallVectorImpl &outReductionTypes, - llvm::SmallVectorImpl &outReductionDeclSymbols, - llvm::SmallVectorImpl - *outReductionSymbols) const { + mlir::Location currentLocation, mlir::omp::ReductionClauseOps &result, + llvm::SmallVectorImpl *outReductionTypes, + llvm::SmallVectorImpl *outReductionSyms) + const { return findRepeatableClause( [&](const omp::clause::Reduction &clause, const Fortran::parser::CharBlock &) { @@ -943,30 +937,31 @@ bool ClauseProcessor::processReduction( // whether to do the reduction byref. llvm::SmallVector reductionVars; llvm::SmallVector reductionDeclSymbols; - llvm::SmallVector reductionSymbols; + llvm::SmallVector reductionSyms; ReductionProcessor rp; rp.addDeclareReduction(currentLocation, converter, clause, reductionVars, reductionDeclSymbols, - outReductionSymbols ? &reductionSymbols - : nullptr); + outReductionSyms ? &reductionSyms : nullptr); // Copy local lists into the output. - llvm::copy(reductionVars, std::back_inserter(outReductionVars)); + llvm::copy(reductionVars, std::back_inserter(result.reductionVars)); llvm::copy(reductionDeclSymbols, - std::back_inserter(outReductionDeclSymbols)); - if (outReductionSymbols) - llvm::copy(reductionSymbols, - std::back_inserter(*outReductionSymbols)); - - outReductionTypes.reserve(outReductionTypes.size() + - reductionVars.size()); - llvm::transform(reductionVars, std::back_inserter(outReductionTypes), - [](mlir::Value v) { return v.getType(); }); + std::back_inserter(result.reductionDeclSymbols)); + + if (outReductionTypes) { + outReductionTypes->reserve(outReductionTypes->size() + + reductionVars.size()); + llvm::transform(reductionVars, std::back_inserter(*outReductionTypes), + [](mlir::Value v) { return v.getType(); }); + } + + if (outReductionSyms) + llvm::copy(reductionSyms, std::back_inserter(*outReductionSyms)); }); } bool ClauseProcessor::processSectionsReduction( - mlir::Location currentLocation) const { + mlir::Location currentLocation, mlir::omp::ReductionClauseOps &) const { return findRepeatableClause( [&](const omp::clause::Reduction &, const Fortran::parser::CharBlock &) { TODO(currentLocation, "OMPC_Reduction"); @@ -995,30 +990,30 @@ bool ClauseProcessor::processEnter( } bool ClauseProcessor::processUseDeviceAddr( - llvm::SmallVectorImpl &operands, + mlir::omp::UseDeviceClauseOps &result, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl &useDeviceSymbols) + llvm::SmallVectorImpl &useDeviceSyms) const { return findRepeatableClause( [&](const omp::clause::UseDeviceAddr &clause, const Fortran::parser::CharBlock &) { - addUseDeviceClause(converter, clause.v, operands, useDeviceTypes, - useDeviceLocs, useDeviceSymbols); + addUseDeviceClause(converter, clause.v, result.useDeviceAddrVars, + useDeviceTypes, useDeviceLocs, useDeviceSyms); }); } bool ClauseProcessor::processUseDevicePtr( - llvm::SmallVectorImpl &operands, + mlir::omp::UseDeviceClauseOps &result, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl &useDeviceSymbols) + llvm::SmallVectorImpl &useDeviceSyms) const { return findRepeatableClause( [&](const omp::clause::UseDevicePtr &clause, const Fortran::parser::CharBlock &) { - addUseDeviceClause(converter, clause.v, operands, useDeviceTypes, - useDeviceLocs, useDeviceSymbols); + addUseDeviceClause(converter, clause.v, result.useDevicePtrVars, + useDeviceTypes, useDeviceLocs, useDeviceSyms); }); } diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h index df8f4f5310fc..aa2c14b61e75 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.h +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h @@ -37,7 +37,7 @@ namespace omp { /// corresponding clause if it is present in the clause list. Otherwise, they /// will return `false` to signal that the clause was not found. /// -/// The intended use is of this class is to move clause processing outside of +/// The intended use of this class is to move clause processing outside of /// construct processing, since the same clauses can appear attached to /// different constructs and constructs can be combined, so that code /// duplication is minimized. @@ -56,61 +56,51 @@ public: // 'Unique' clauses: They can appear at most once in the clause list. bool processCollapse( mlir::Location currentLocation, Fortran::lower::pft::Evaluation &eval, - llvm::SmallVectorImpl &lowerBound, - llvm::SmallVectorImpl &upperBound, - llvm::SmallVectorImpl &step, + mlir::omp::CollapseClauseOps &result, llvm::SmallVectorImpl &iv) const; bool processDefault() const; bool processDevice(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const; - bool processDeviceType(mlir::omp::DeclareTargetDeviceType &result) const; + mlir::omp::DeviceClauseOps &result) const; + bool processDeviceType(mlir::omp::DeviceTypeClauseOps &result) const; bool processFinal(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const; + mlir::omp::FinalClauseOps &result) const; bool - processHasDeviceAddr(llvm::SmallVectorImpl &operands, + processHasDeviceAddr(mlir::omp::HasDeviceAddrClauseOps &result, llvm::SmallVectorImpl &isDeviceTypes, llvm::SmallVectorImpl &isDeviceLocs, llvm::SmallVectorImpl &isDeviceSymbols) const; - bool processHint(mlir::IntegerAttr &result) const; - bool processMergeable(mlir::UnitAttr &result) const; - bool processNowait(mlir::UnitAttr &result) const; + bool processHint(mlir::omp::HintClauseOps &result) const; + bool processMergeable(mlir::omp::MergeableClauseOps &result) const; + bool processNowait(mlir::omp::NowaitClauseOps &result) const; bool processNumTeams(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const; + mlir::omp::NumTeamsClauseOps &result) const; bool processNumThreads(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const; - bool processOrdered(mlir::IntegerAttr &result) const; + mlir::omp::NumThreadsClauseOps &result) const; + bool processOrdered(mlir::omp::OrderedClauseOps &result) const; bool processPriority(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const; - bool processProcBind(mlir::omp::ClauseProcBindKindAttr &result) const; - bool processSafelen(mlir::IntegerAttr &result) const; - bool processSchedule(mlir::omp::ClauseScheduleKindAttr &valAttr, - mlir::omp::ScheduleModifierAttr &modifierAttr, - mlir::UnitAttr &simdModifierAttr) const; - bool processScheduleChunk(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const; - bool processSimdlen(mlir::IntegerAttr &result) const; + mlir::omp::PriorityClauseOps &result) const; + bool processProcBind(mlir::omp::ProcBindClauseOps &result) const; + bool processSafelen(mlir::omp::SafelenClauseOps &result) const; + bool processSchedule(Fortran::lower::StatementContext &stmtCtx, + mlir::omp::ScheduleClauseOps &result) const; + bool processSimdlen(mlir::omp::SimdlenClauseOps &result) const; bool processThreadLimit(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const; - bool processUntied(mlir::UnitAttr &result) const; + mlir::omp::ThreadLimitClauseOps &result) const; + bool processUntied(mlir::omp::UntiedClauseOps &result) const; // 'Repeatable' clauses: They can appear multiple times in the clause list. - bool - processAllocate(llvm::SmallVectorImpl &allocatorOperands, - llvm::SmallVectorImpl &allocateOperands) const; + bool processAllocate(mlir::omp::AllocateClauseOps &result) const; bool processCopyin() const; - bool processCopyPrivate( - mlir::Location currentLocation, - llvm::SmallVectorImpl ©PrivateVars, - llvm::SmallVectorImpl ©PrivateFuncs) const; - bool processDepend(llvm::SmallVectorImpl &dependTypeOperands, - llvm::SmallVectorImpl &dependOperands) const; + bool processCopyprivate(mlir::Location currentLocation, + mlir::omp::CopyprivateClauseOps &result) const; + bool processDepend(mlir::omp::DependClauseOps &result) const; bool processEnter(llvm::SmallVectorImpl &result) const; bool processIf(omp::clause::If::DirectiveNameModifier directiveName, - mlir::Value &result) const; + mlir::omp::IfClauseOps &result) const; bool - processIsDevicePtr(llvm::SmallVectorImpl &operands, + processIsDevicePtr(mlir::omp::IsDevicePtrClauseOps &result, llvm::SmallVectorImpl &isDeviceTypes, llvm::SmallVectorImpl &isDeviceLocs, llvm::SmallVectorImpl @@ -119,43 +109,42 @@ public: processLink(llvm::SmallVectorImpl &result) const; // This method is used to process a map clause. - // The optional parameters - mapSymTypes, mapSymLocs & mapSymbols are used to + // The optional parameters - mapSymTypes, mapSymLocs & mapSyms are used to // store the original type, location and Fortran symbol for the map operands. // They may be used later on to create the block_arguments for some of the // target directives that require it. - bool processMap(mlir::Location currentLocation, - const llvm::omp::Directive &directive, - Fortran::lower::StatementContext &stmtCtx, - llvm::SmallVectorImpl &mapOperands, - llvm::SmallVectorImpl *mapSymTypes = nullptr, - llvm::SmallVectorImpl *mapSymLocs = nullptr, - llvm::SmallVectorImpl - *mapSymbols = nullptr) const; - bool - processReduction(mlir::Location currentLocation, - llvm::SmallVectorImpl &reductionVars, - llvm::SmallVectorImpl &reductionTypes, - llvm::SmallVectorImpl &reductionDeclSymbols, - llvm::SmallVectorImpl - *reductionSymbols = nullptr) const; - bool processSectionsReduction(mlir::Location currentLocation) const; + bool processMap( + mlir::Location currentLocation, const llvm::omp::Directive &directive, + Fortran::lower::StatementContext &stmtCtx, + mlir::omp::MapClauseOps &result, + llvm::SmallVectorImpl *mapSyms = + nullptr, + llvm::SmallVectorImpl *mapSymLocs = nullptr, + llvm::SmallVectorImpl *mapSymTypes = nullptr) const; + bool processReduction( + mlir::Location currentLocation, mlir::omp::ReductionClauseOps &result, + llvm::SmallVectorImpl *reductionTypes = nullptr, + llvm::SmallVectorImpl *reductionSyms = + nullptr) const; + bool processSectionsReduction(mlir::Location currentLocation, + mlir::omp::ReductionClauseOps &result) const; bool processTo(llvm::SmallVectorImpl &result) const; bool - processUseDeviceAddr(llvm::SmallVectorImpl &operands, + processUseDeviceAddr(mlir::omp::UseDeviceClauseOps &result, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, llvm::SmallVectorImpl - &useDeviceSymbols) const; + &useDeviceSyms) const; bool - processUseDevicePtr(llvm::SmallVectorImpl &operands, + processUseDevicePtr(mlir::omp::UseDeviceClauseOps &result, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, llvm::SmallVectorImpl - &useDeviceSymbols) const; + &useDeviceSyms) const; template bool processMotionClauses(Fortran::lower::StatementContext &stmtCtx, - llvm::SmallVectorImpl &mapOperands); + mlir::omp::MapClauseOps &result); // Call this method for these clauses that should be supported but are not // implemented yet. It triggers a compilation error if any of the given @@ -197,7 +186,7 @@ private: template bool ClauseProcessor::processMotionClauses( Fortran::lower::StatementContext &stmtCtx, - llvm::SmallVectorImpl &mapOperands) { + mlir::omp::MapClauseOps &result) { return findRepeatableClause( [&](const T &clause, const Fortran::parser::CharBlock &source) { mlir::Location clauseLocation = converter.genLocation(source); @@ -239,7 +228,7 @@ bool ClauseProcessor::processMotionClauses( mapTypeBits), mlir::omp::VariableCaptureKind::ByRef, symAddr.getType()); - mapOperands.push_back(mapOp); + result.mapVars.push_back(mapOp); } }); } diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index e114ab9f4548..5a42e6a6aa41 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -23,11 +23,13 @@ namespace Fortran { namespace lower { namespace omp { -void DataSharingProcessor::processStep1() { +void DataSharingProcessor::processStep1( + mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms) { collectSymbolsForPrivatization(); collectDefaultSymbols(); - privatize(); - defaultPrivatize(); + privatize(clauseOps, privateSyms); + defaultPrivatize(clauseOps, privateSyms); insertBarrier(); } @@ -299,14 +301,16 @@ void DataSharingProcessor::collectDefaultSymbols() { } } -void DataSharingProcessor::privatize() { +void DataSharingProcessor::privatize( + mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms) { for (const Fortran::semantics::Symbol *sym : privatizedSymbols) { if (const auto *commonDet = sym->detailsIf()) { for (const auto &mem : commonDet->objects()) - doPrivatize(&*mem); + doPrivatize(&*mem, clauseOps, privateSyms); } else - doPrivatize(sym); + doPrivatize(sym, clauseOps, privateSyms); } } @@ -323,7 +327,9 @@ void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) { } } -void DataSharingProcessor::defaultPrivatize() { +void DataSharingProcessor::defaultPrivatize( + mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms) { for (const Fortran::semantics::Symbol *sym : defaultSymbols) { if (!Fortran::semantics::IsProcedure(*sym) && !sym->GetUltimate().has() && @@ -331,11 +337,14 @@ void DataSharingProcessor::defaultPrivatize() { !symbolsInNestedRegions.contains(sym) && !symbolsInParentRegions.contains(sym) && !privatizedSymbols.contains(sym)) - doPrivatize(sym); + doPrivatize(sym, clauseOps, privateSyms); } } -void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) { +void DataSharingProcessor::doPrivatize( + const Fortran::semantics::Symbol *sym, + mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms) { if (!useDelayedPrivatization) { cloneSymbol(sym); copyFirstPrivateSymbol(sym); @@ -419,10 +428,13 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) { return result; }(); - delayedPrivatizationInfo.privatizers.push_back( - mlir::SymbolRefAttr::get(privatizerOp)); - delayedPrivatizationInfo.originalAddresses.push_back(hsb.getAddr()); - delayedPrivatizationInfo.symbols.push_back(sym); + if (clauseOps) { + clauseOps->privatizers.push_back(mlir::SymbolRefAttr::get(privatizerOp)); + clauseOps->privateVars.push_back(hsb.getAddr()); + } + + if (privateSyms) + privateSyms->push_back(sym); } } // namespace omp diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.h b/flang/lib/Lower/OpenMP/DataSharingProcessor.h index 1cbc825fd5e1..c11ee299c5d0 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.h +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.h @@ -19,28 +19,17 @@ #include "flang/Parser/parse-tree.h" #include "flang/Semantics/symbol.h" +namespace mlir { +namespace omp { +struct PrivateClauseOps; +} // namespace omp +} // namespace mlir + namespace Fortran { namespace lower { namespace omp { class DataSharingProcessor { -public: - /// Collects all the information needed for delayed privatization. This can be - /// used by ops with data-sharing clauses to properly generate their regions - /// (e.g. add region arguments) and map the original SSA values to their - /// corresponding OMP region operands. - struct DelayedPrivatizationInfo { - // The list of symbols referring to delayed privatizer ops (i.e. - // `omp.private` ops). - llvm::SmallVector privatizers; - // SSA values that correspond to "original" values being privatized. - // "Original" here means the SSA value outside the OpenMP region from which - // a clone is created inside the region. - llvm::SmallVector originalAddresses; - // Fortran symbols corresponding to the above SSA values. - llvm::SmallVector symbols; - }; - private: bool hasLastPrivateOp; mlir::OpBuilder::InsertPoint lastPrivIP; @@ -57,7 +46,6 @@ private: Fortran::lower::pft::Evaluation &eval; bool useDelayedPrivatization; Fortran::lower::SymMap *symTable; - DelayedPrivatizationInfo delayedPrivatizationInfo; bool needBarrier(); void collectSymbols(Fortran::semantics::Symbol::Flag flag); @@ -67,9 +55,16 @@ private: void collectSymbolsForPrivatization(); void insertBarrier(); void collectDefaultSymbols(); - void privatize(); - void defaultPrivatize(); - void doPrivatize(const Fortran::semantics::Symbol *sym); + void privatize( + mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms); + void defaultPrivatize( + mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms); + void doPrivatize( + const Fortran::semantics::Symbol *sym, + mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms); void copyLastPrivatize(mlir::Operation *op); void insertLastPrivateCompare(mlir::Operation *op); void cloneSymbol(const Fortran::semantics::Symbol *sym); @@ -103,17 +98,15 @@ public: // Step2 performs the copying for lastprivates and requires knowledge of the // MLIR operation to insert the last private update. Step2 adds // dealocation code as well. - void processStep1(); + void processStep1(mlir::omp::PrivateClauseOps *clauseOps = nullptr, + llvm::SmallVectorImpl + *privateSyms = nullptr); void processStep2(mlir::Operation *op, bool isLoop); void setLoopIV(mlir::Value iv) { assert(!loopIV && "Loop iteration variable already set"); loopIV = iv; } - - const DelayedPrivatizationInfo &getDelayedPrivatizationInfo() const { - return delayedPrivatizationInfo; - } }; } // namespace omp diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 50ad889052ab..3dcfe0fd775d 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -730,19 +730,25 @@ genMasterOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation) { return genOpWithBody( OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) - .setGenNested(genNested), - /*resultTypes=*/mlir::TypeRange()); + .setGenNested(genNested)); } static mlir::omp::OrderedRegionOp genOrderedRegionOp(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location currentLocation) { + mlir::Location currentLocation, + const Fortran::parser::OmpClauseList &clauseList) { + mlir::omp::OrderedRegionClauseOps clauseOps; + + ClauseProcessor cp(converter, semaCtx, clauseList); + cp.processTODO(currentLocation, + llvm::omp::Directive::OMPD_ordered); + return genOpWithBody( OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(genNested), - /*simd=*/false); + clauseOps); } static mlir::omp::ParallelOp @@ -753,77 +759,62 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, const Fortran::parser::OmpClauseList &clauseList, bool outerCombined = false) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; - mlir::Value ifClauseOperand, numThreadsClauseOperand; - mlir::omp::ClauseProcBindKindAttr procBindKindAttr; - llvm::SmallVector allocateOperands, allocatorOperands, - reductionVars; + mlir::omp::ParallelClauseOps clauseOps; + llvm::SmallVector privateSyms; llvm::SmallVector reductionTypes; - llvm::SmallVector reductionDeclSymbols; - llvm::SmallVector reductionSymbols; + llvm::SmallVector reductionSyms; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(llvm::omp::Directive::OMPD_parallel, ifClauseOperand); - cp.processNumThreads(stmtCtx, numThreadsClauseOperand); - cp.processProcBind(procBindKindAttr); + cp.processIf(llvm::omp::Directive::OMPD_parallel, clauseOps); + cp.processNumThreads(stmtCtx, clauseOps); + cp.processProcBind(clauseOps); cp.processDefault(); - cp.processAllocate(allocatorOperands, allocateOperands); + cp.processAllocate(clauseOps); + if (!outerCombined) - cp.processReduction(currentLocation, reductionVars, reductionTypes, - reductionDeclSymbols, &reductionSymbols); + cp.processReduction(currentLocation, clauseOps, &reductionTypes, + &reductionSyms); + + if (ReductionProcessor::doReductionByRef(clauseOps.reductionVars)) + clauseOps.reductionByRefAttr = firOpBuilder.getUnitAttr(); auto reductionCallback = [&](mlir::Operation *op) { - llvm::SmallVector locs(reductionVars.size(), + llvm::SmallVector locs(clauseOps.reductionVars.size(), currentLocation); - auto *block = converter.getFirOpBuilder().createBlock(&op->getRegion(0), {}, - reductionTypes, locs); + auto *block = + firOpBuilder.createBlock(&op->getRegion(0), {}, reductionTypes, locs); for (auto [arg, prv] : - llvm::zip_equal(reductionSymbols, block->getArguments())) { + llvm::zip_equal(reductionSyms, block->getArguments())) { converter.bindSymbol(*arg, prv); } - return reductionSymbols; + return reductionSyms; }; - mlir::UnitAttr byrefAttr; - if (ReductionProcessor::doReductionByRef(reductionVars)) - byrefAttr = converter.getFirOpBuilder().getUnitAttr(); - OpWithBodyGenInfo genInfo = OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(genNested) .setOuterCombined(outerCombined) .setClauses(&clauseList) - .setReductions(&reductionSymbols, &reductionTypes) + .setReductions(&reductionSyms, &reductionTypes) .setGenRegionEntryCb(reductionCallback); - if (!enableDelayedPrivatization) { - return genOpWithBody( - genInfo, - /*resultTypes=*/mlir::TypeRange(), ifClauseOperand, - numThreadsClauseOperand, allocateOperands, allocatorOperands, - reductionVars, - reductionDeclSymbols.empty() - ? nullptr - : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - reductionDeclSymbols), - procBindKindAttr, /*private_vars=*/llvm::SmallVector{}, - /*privatizers=*/nullptr, byrefAttr); - } + if (!enableDelayedPrivatization) + return genOpWithBody(genInfo, clauseOps); bool privatize = !outerCombined; DataSharingProcessor dsp(converter, semaCtx, clauseList, eval, /*useDelayedPrivatization=*/true, &symTable); if (privatize) - dsp.processStep1(); - - const auto &delayedPrivatizationInfo = dsp.getDelayedPrivatizationInfo(); + dsp.processStep1(&clauseOps, &privateSyms); auto genRegionEntryCB = [&](mlir::Operation *op) { auto parallelOp = llvm::cast(op); - llvm::SmallVector reductionLocs(reductionVars.size(), - currentLocation); + llvm::SmallVector reductionLocs( + clauseOps.reductionVars.size(), currentLocation); mlir::OperandRange privateVars = parallelOp.getPrivateVars(); mlir::Region ®ion = parallelOp.getRegion(); @@ -838,12 +829,12 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, llvm::transform(privateVars, std::back_inserter(privateVarLocs), [](mlir::Value v) { return v.getLoc(); }); - converter.getFirOpBuilder().createBlock(®ion, /*insertPt=*/{}, - privateVarTypes, privateVarLocs); + firOpBuilder.createBlock(®ion, /*insertPt=*/{}, privateVarTypes, + privateVarLocs); llvm::SmallVector allSymbols = - reductionSymbols; - allSymbols.append(delayedPrivatizationInfo.symbols); + reductionSyms; + allSymbols.append(privateSyms); for (auto [arg, prv] : llvm::zip_equal(allSymbols, region.getArguments())) { converter.bindSymbol(*arg, prv); } @@ -853,26 +844,7 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, // TODO Merge with the reduction CB. genInfo.setGenRegionEntryCb(genRegionEntryCB).setDataSharingProcessor(&dsp); - - llvm::SmallVector privatizers( - delayedPrivatizationInfo.privatizers.begin(), - delayedPrivatizationInfo.privatizers.end()); - - return genOpWithBody( - genInfo, - /*resultTypes=*/mlir::TypeRange(), ifClauseOperand, - numThreadsClauseOperand, allocateOperands, allocatorOperands, - reductionVars, - reductionDeclSymbols.empty() - ? nullptr - : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - reductionDeclSymbols), - procBindKindAttr, delayedPrivatizationInfo.originalAddresses, - delayedPrivatizationInfo.privatizers.empty() - ? nullptr - : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - privatizers), - byrefAttr); + return genOpWithBody(genInfo, clauseOps); } static mlir::omp::SectionOp @@ -896,28 +868,21 @@ genSingleOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, const Fortran::parser::OmpClauseList &beginClauseList, const Fortran::parser::OmpClauseList &endClauseList) { - llvm::SmallVector allocateOperands, allocatorOperands; - llvm::SmallVector copyPrivateVars; - llvm::SmallVector copyPrivateFuncs; - mlir::UnitAttr nowaitAttr; + mlir::omp::SingleClauseOps clauseOps; ClauseProcessor cp(converter, semaCtx, beginClauseList); - cp.processAllocate(allocatorOperands, allocateOperands); + cp.processAllocate(clauseOps); + // TODO Support delayed privatization. ClauseProcessor ecp(converter, semaCtx, endClauseList); - ecp.processNowait(nowaitAttr); - ecp.processCopyPrivate(currentLocation, copyPrivateVars, copyPrivateFuncs); + ecp.processNowait(clauseOps); + ecp.processCopyprivate(currentLocation, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(genNested) .setClauses(&beginClauseList), - allocateOperands, allocatorOperands, copyPrivateVars, - copyPrivateFuncs.empty() - ? nullptr - : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - copyPrivateFuncs), - nowaitAttr); + clauseOps); } static mlir::omp::TaskOp @@ -927,21 +892,19 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, const Fortran::parser::OmpClauseList &clauseList) { Fortran::lower::StatementContext stmtCtx; - mlir::Value ifClauseOperand, finalClauseOperand, priorityClauseOperand; - mlir::UnitAttr untiedAttr, mergeableAttr; - llvm::SmallVector dependTypeOperands; - llvm::SmallVector allocateOperands, allocatorOperands, - dependOperands; + mlir::omp::TaskClauseOps clauseOps; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(llvm::omp::Directive::OMPD_task, ifClauseOperand); - cp.processAllocate(allocatorOperands, allocateOperands); + cp.processIf(llvm::omp::Directive::OMPD_task, clauseOps); + cp.processAllocate(clauseOps); cp.processDefault(); - cp.processFinal(stmtCtx, finalClauseOperand); - cp.processUntied(untiedAttr); - cp.processMergeable(mergeableAttr); - cp.processPriority(stmtCtx, priorityClauseOperand); - cp.processDepend(dependTypeOperands, dependOperands); + cp.processFinal(stmtCtx, clauseOps); + cp.processUntied(clauseOps); + cp.processMergeable(clauseOps); + cp.processPriority(stmtCtx, clauseOps); + cp.processDepend(clauseOps); + // TODO Support delayed privatization. + cp.processTODO( currentLocation, llvm::omp::Directive::OMPD_task); @@ -949,14 +912,7 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(genNested) .setClauses(&clauseList), - ifClauseOperand, finalClauseOperand, untiedAttr, mergeableAttr, - /*in_reduction_vars=*/mlir::ValueRange(), - /*in_reductions=*/nullptr, priorityClauseOperand, - dependTypeOperands.empty() - ? nullptr - : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - dependTypeOperands), - dependOperands, allocateOperands, allocatorOperands); + clauseOps); } static mlir::omp::TaskgroupOp @@ -965,17 +921,18 @@ genTaskgroupOp(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, bool genNested, mlir::Location currentLocation, const Fortran::parser::OmpClauseList &clauseList) { - llvm::SmallVector allocateOperands, allocatorOperands; + mlir::omp::TaskgroupClauseOps clauseOps; + ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processAllocate(allocatorOperands, allocateOperands); + cp.processAllocate(clauseOps); cp.processTODO(currentLocation, llvm::omp::Directive::OMPD_taskgroup); + return genOpWithBody( OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(genNested) .setClauses(&clauseList), - /*task_reduction_vars=*/mlir::ValueRange(), - /*task_reductions=*/nullptr, allocateOperands, allocatorOperands); + clauseOps); } // This helper function implements the functionality of "promoting" @@ -996,8 +953,7 @@ genTaskgroupOp(Fortran::lower::AbstractConverter &converter, // clause. Support for such list items in a use_device_ptr clause // is deprecated." static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( - llvm::SmallVectorImpl &devicePtrOperands, - llvm::SmallVectorImpl &deviceAddrOperands, + mlir::omp::UseDeviceClauseOps &clauseOps, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, llvm::SmallVectorImpl @@ -1010,9 +966,10 @@ static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( // Iterate over our use_device_ptr list and shift all non-cptr arguments into // use_device_addr. - for (auto *it = devicePtrOperands.begin(); it != devicePtrOperands.end();) { + for (auto *it = clauseOps.useDevicePtrVars.begin(); + it != clauseOps.useDevicePtrVars.end();) { if (!fir::isa_builtin_cptr_type(fir::unwrapRefType(it->getType()))) { - deviceAddrOperands.push_back(*it); + clauseOps.useDeviceAddrVars.push_back(*it); // We have to shuffle the symbols around as well, to maintain // the correct Input -> BlockArg for use_device_ptr/use_device_addr. // NOTE: However, as map's do not seem to be included currently @@ -1020,11 +977,11 @@ static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( // future alterations. I believe the reason they are not currently // is that the BlockArg assign/lowering needs to be extended // to a greater set of types. - auto idx = std::distance(devicePtrOperands.begin(), it); + auto idx = std::distance(clauseOps.useDevicePtrVars.begin(), it); moveElementToBack(idx, useDeviceTypes); moveElementToBack(idx, useDeviceLocs); moveElementToBack(idx, useDeviceSymbols); - it = devicePtrOperands.erase(it); + it = clauseOps.useDevicePtrVars.erase(it); continue; } ++it; @@ -1038,20 +995,19 @@ genTargetDataOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, const Fortran::parser::OmpClauseList &clauseList) { Fortran::lower::StatementContext stmtCtx; - mlir::Value ifClauseOperand, deviceOperand; - llvm::SmallVector mapOperands, devicePtrOperands, - deviceAddrOperands; + mlir::omp::TargetDataClauseOps clauseOps; llvm::SmallVector useDeviceTypes; llvm::SmallVector useDeviceLocs; - llvm::SmallVector useDeviceSymbols; + llvm::SmallVector useDeviceSyms; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(llvm::omp::Directive::OMPD_target_data, ifClauseOperand); - cp.processDevice(stmtCtx, deviceOperand); - cp.processUseDevicePtr(devicePtrOperands, useDeviceTypes, useDeviceLocs, - useDeviceSymbols); - cp.processUseDeviceAddr(deviceAddrOperands, useDeviceTypes, useDeviceLocs, - useDeviceSymbols); + cp.processIf(llvm::omp::Directive::OMPD_target_data, clauseOps); + cp.processDevice(stmtCtx, clauseOps); + cp.processUseDevicePtr(clauseOps, useDeviceTypes, useDeviceLocs, + useDeviceSyms); + cp.processUseDeviceAddr(clauseOps, useDeviceTypes, useDeviceLocs, + useDeviceSyms); + // This function implements the deprecated functionality of use_device_ptr // that allows users to provide non-CPTR arguments to it with the caveat // that the compiler will treat them as use_device_addr. A lot of legacy @@ -1063,17 +1019,16 @@ genTargetDataOp(Fortran::lower::AbstractConverter &converter, // ordering. // TODO: Perhaps create a user provideable compiler option that will // re-introduce a hard-error rather than a warning in these cases. - promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( - devicePtrOperands, deviceAddrOperands, useDeviceTypes, useDeviceLocs, - useDeviceSymbols); + promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr(clauseOps, useDeviceTypes, + useDeviceLocs, useDeviceSyms); cp.processMap(currentLocation, llvm::omp::Directive::OMPD_target_data, - stmtCtx, mapOperands); + stmtCtx, clauseOps); auto dataOp = converter.getFirOpBuilder().create( - currentLocation, ifClauseOperand, deviceOperand, devicePtrOperands, - deviceAddrOperands, mapOperands); + currentLocation, clauseOps); + genBodyOfTargetDataOp(converter, semaCtx, eval, genNested, dataOp, - useDeviceTypes, useDeviceLocs, useDeviceSymbols, + useDeviceTypes, useDeviceLocs, useDeviceSyms, currentLocation); return dataOp; } @@ -1086,10 +1041,7 @@ static OpTy genTargetEnterExitDataUpdateOp( const Fortran::parser::OmpClauseList &clauseList) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; - mlir::Value ifClauseOperand, deviceOperand; - mlir::UnitAttr nowaitAttr; - llvm::SmallVector mapOperands, dependOperands; - llvm::SmallVector dependTypeOperands; + mlir::omp::TargetEnterExitUpdateDataClauseOps clauseOps; // GCC 9.3.0 emits a (probably) bogus warning about an unused variable. [[maybe_unused]] llvm::omp::Directive directive; @@ -1104,25 +1056,19 @@ static OpTy genTargetEnterExitDataUpdateOp( } ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(directive, ifClauseOperand); - cp.processDevice(stmtCtx, deviceOperand); - cp.processDepend(dependTypeOperands, dependOperands); - cp.processNowait(nowaitAttr); + cp.processIf(directive, clauseOps); + cp.processDevice(stmtCtx, clauseOps); + cp.processDepend(clauseOps); + cp.processNowait(clauseOps); if constexpr (std::is_same_v) { - cp.processMotionClauses(stmtCtx, mapOperands); - cp.processMotionClauses(stmtCtx, mapOperands); + cp.processMotionClauses(stmtCtx, clauseOps); + cp.processMotionClauses(stmtCtx, clauseOps); } else { - cp.processMap(currentLocation, directive, stmtCtx, mapOperands); + cp.processMap(currentLocation, directive, stmtCtx, clauseOps); } - return firOpBuilder.create( - currentLocation, ifClauseOperand, deviceOperand, - dependTypeOperands.empty() - ? nullptr - : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - dependTypeOperands), - dependOperands, nowaitAttr, mapOperands); + return firOpBuilder.create(currentLocation, clauseOps); } // This functions creates a block for the body of the targetOp's region. It adds @@ -1132,9 +1078,9 @@ genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, bool genNested, mlir::omp::TargetOp &targetOp, - llvm::ArrayRef mapSymTypes, + llvm::ArrayRef mapSyms, llvm::ArrayRef mapSymLocs, - llvm::ArrayRef mapSymbols, + llvm::ArrayRef mapSymTypes, const mlir::Location ¤tLocation) { assert(mapSymTypes.size() == mapSymLocs.size()); @@ -1163,7 +1109,7 @@ genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, }; // Bind the symbols to their corresponding block arguments. - for (auto [argIndex, argSymbol] : llvm::enumerate(mapSymbols)) { + for (auto [argIndex, argSymbol] : llvm::enumerate(mapSyms)) { const mlir::BlockArgument &arg = region.getArgument(argIndex); // Avoid capture of a reference to a structured binding. const Fortran::semantics::Symbol *sym = argSymbol; @@ -1287,31 +1233,25 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OmpClauseList &clauseList, llvm::omp::Directive directive, bool outerCombined = false) { Fortran::lower::StatementContext stmtCtx; - mlir::Value ifClauseOperand, deviceOperand, threadLimitOperand; - mlir::UnitAttr nowaitAttr; - llvm::SmallVector dependTypeOperands; - llvm::SmallVector mapOperands, dependOperands; - llvm::SmallVector mapSymTypes; - llvm::SmallVector mapSymLocs; - llvm::SmallVector mapSymbols; - llvm::SmallVector devicePtrOperands, deviceAddrOperands; - llvm::SmallVector devicePtrTypes, deviceAddrTypes; - llvm::SmallVector devicePtrLocs, deviceAddrLocs; - llvm::SmallVector devicePtrSymbols, - deviceAddrSymbols; + mlir::omp::TargetClauseOps clauseOps; + llvm::SmallVector mapTypes, devicePtrTypes, deviceAddrTypes; + llvm::SmallVector mapLocs, devicePtrLocs, deviceAddrLocs; + llvm::SmallVector mapSyms, devicePtrSyms, + deviceAddrSyms; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(llvm::omp::Directive::OMPD_target, ifClauseOperand); - cp.processDevice(stmtCtx, deviceOperand); - cp.processThreadLimit(stmtCtx, threadLimitOperand); - cp.processDepend(dependTypeOperands, dependOperands); - cp.processNowait(nowaitAttr); - cp.processMap(currentLocation, directive, stmtCtx, mapOperands, &mapSymTypes, - &mapSymLocs, &mapSymbols); - cp.processIsDevicePtr(devicePtrOperands, devicePtrTypes, devicePtrLocs, - devicePtrSymbols); - cp.processHasDeviceAddr(deviceAddrOperands, deviceAddrTypes, deviceAddrLocs, - deviceAddrSymbols); + cp.processIf(llvm::omp::Directive::OMPD_target, clauseOps); + cp.processDevice(stmtCtx, clauseOps); + cp.processThreadLimit(stmtCtx, clauseOps); + cp.processDepend(clauseOps); + cp.processNowait(clauseOps); + cp.processMap(currentLocation, directive, stmtCtx, clauseOps, &mapSyms, + &mapLocs, &mapTypes); + cp.processIsDevicePtr(clauseOps, devicePtrTypes, devicePtrLocs, + devicePtrSyms); + cp.processHasDeviceAddr(clauseOps, deviceAddrTypes, deviceAddrLocs, + deviceAddrSyms); + // TODO Support delayed privatization. cp.processTODO( - currentLocation, ifClauseOperand, deviceOperand, threadLimitOperand, - dependTypeOperands.empty() - ? nullptr - : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - dependTypeOperands), - dependOperands, nowaitAttr, devicePtrOperands, deviceAddrOperands, - mapOperands); + currentLocation, clauseOps); - genBodyOfTargetOp(converter, semaCtx, eval, genNested, targetOp, mapSymTypes, - mapSymLocs, mapSymbols, currentLocation); + genBodyOfTargetOp(converter, semaCtx, eval, genNested, targetOp, mapSyms, + mapLocs, mapTypes, currentLocation); return targetOp; } @@ -1426,17 +1360,16 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OmpClauseList &clauseList, bool outerCombined = false) { Fortran::lower::StatementContext stmtCtx; - mlir::Value numTeamsClauseOperand, ifClauseOperand, threadLimitClauseOperand; - llvm::SmallVector allocateOperands, allocatorOperands, - reductionVars; - llvm::SmallVector reductionDeclSymbols; + mlir::omp::TeamsClauseOps clauseOps; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(llvm::omp::Directive::OMPD_teams, ifClauseOperand); - cp.processAllocate(allocatorOperands, allocateOperands); + cp.processIf(llvm::omp::Directive::OMPD_teams, clauseOps); + cp.processAllocate(clauseOps); cp.processDefault(); - cp.processNumTeams(stmtCtx, numTeamsClauseOperand); - cp.processThreadLimit(stmtCtx, threadLimitClauseOperand); + cp.processNumTeams(stmtCtx, clauseOps); + cp.processThreadLimit(stmtCtx, clauseOps); + // TODO Support delayed privatization. + cp.processTODO(currentLocation, llvm::omp::Directive::OMPD_teams); @@ -1445,30 +1378,20 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter, .setGenNested(genNested) .setOuterCombined(outerCombined) .setClauses(&clauseList), - /*num_teams_lower=*/nullptr, numTeamsClauseOperand, ifClauseOperand, - threadLimitClauseOperand, allocateOperands, allocatorOperands, - reductionVars, - reductionDeclSymbols.empty() - ? nullptr - : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - reductionDeclSymbols)); + clauseOps); } /// Extract the list of function and variable symbols affected by the given /// 'declare target' directive and return the intended device type for them. -static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo( +static void getDeclareTargetInfo( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct, + mlir::omp::DeclareTargetClauseOps &clauseOps, llvm::SmallVectorImpl &symbolAndClause) { - - // The default capture type - mlir::omp::DeclareTargetDeviceType deviceType = - mlir::omp::DeclareTargetDeviceType::any; const auto &spec = std::get( declareTargetConstruct.t); - if (const auto *objectList{ Fortran::parser::Unwrap(spec.u)}) { ObjectList objects{makeObjects(*objectList, semaCtx)}; @@ -1489,12 +1412,10 @@ static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo( cp.processTo(symbolAndClause); cp.processEnter(symbolAndClause); cp.processLink(symbolAndClause); - cp.processDeviceType(deviceType); + cp.processDeviceType(clauseOps); cp.processTODO(converter.getCurrentLocation(), llvm::omp::Directive::OMPD_declare_target); } - - return deviceType; } static void collectDeferredDeclareTargets( @@ -1504,9 +1425,10 @@ static void collectDeferredDeclareTargets( const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct, llvm::SmallVectorImpl &deferredDeclareTarget) { + mlir::omp::DeclareTargetClauseOps clauseOps; llvm::SmallVector symbolAndClause; - mlir::omp::DeclareTargetDeviceType devType = getDeclareTargetInfo( - converter, semaCtx, eval, declareTargetConstruct, symbolAndClause); + getDeclareTargetInfo(converter, semaCtx, eval, declareTargetConstruct, + clauseOps, symbolAndClause); // Return the device type only if at least one of the targets for the // directive is a function or subroutine mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); @@ -1516,8 +1438,9 @@ static void collectDeferredDeclareTargets( std::get(symClause))); if (!op) { - deferredDeclareTarget.push_back( - {std::get<0>(symClause), devType, std::get<1>(symClause)}); + deferredDeclareTarget.push_back({std::get<0>(symClause), + clauseOps.deviceType, + std::get<1>(symClause)}); } } } @@ -1529,9 +1452,10 @@ getDeclareTargetFunctionDevice( Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct) { + mlir::omp::DeclareTargetClauseOps clauseOps; llvm::SmallVector symbolAndClause; - mlir::omp::DeclareTargetDeviceType deviceType = getDeclareTargetInfo( - converter, semaCtx, eval, declareTargetConstruct, symbolAndClause); + getDeclareTargetInfo(converter, semaCtx, eval, declareTargetConstruct, + clauseOps, symbolAndClause); // Return the device type only if at least one of the targets for the // directive is a function or subroutine @@ -1541,7 +1465,7 @@ getDeclareTargetFunctionDevice( std::get(symClause))); if (mlir::isa_and_nonnull(op)) - return deviceType; + return clauseOps.deviceType; } return std::nullopt; @@ -1571,12 +1495,14 @@ genOmpSimpleStandalone(Fortran::lower::AbstractConverter &converter, case llvm::omp::Directive::OMPD_barrier: firOpBuilder.create(currentLocation); break; - case llvm::omp::Directive::OMPD_taskwait: - ClauseProcessor(converter, semaCtx, opClauseList) - .processTODO( - currentLocation, llvm::omp::Directive::OMPD_taskwait); - firOpBuilder.create(currentLocation); + case llvm::omp::Directive::OMPD_taskwait: { + mlir::omp::TaskwaitClauseOps clauseOps; + ClauseProcessor cp(converter, semaCtx, opClauseList); + cp.processTODO( + currentLocation, llvm::omp::Directive::OMPD_taskwait); + firOpBuilder.create(currentLocation, clauseOps); break; + } case llvm::omp::Directive::OMPD_taskyield: firOpBuilder.create(currentLocation); break; @@ -1711,32 +1637,21 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter, dsp.processStep1(); Fortran::lower::StatementContext stmtCtx; - mlir::Value scheduleChunkClauseOperand, ifClauseOperand; - llvm::SmallVector lowerBound, upperBound, step, reductionVars; - llvm::SmallVector alignedVars, nontemporalVars; + mlir::omp::SimdLoopClauseOps clauseOps; llvm::SmallVector iv; - llvm::SmallVector reductionTypes; - llvm::SmallVector reductionDeclSymbols; - mlir::omp::ClauseOrderKindAttr orderClauseOperand; - mlir::IntegerAttr simdlenClauseOperand, safelenClauseOperand; ClauseProcessor cp(converter, semaCtx, loopOpClauseList); - cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv); - cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand); - cp.processReduction(loc, reductionVars, reductionTypes, reductionDeclSymbols); - cp.processIf(llvm::omp::Directive::OMPD_simd, ifClauseOperand); - cp.processSimdlen(simdlenClauseOperand); - cp.processSafelen(safelenClauseOperand); + cp.processCollapse(loc, eval, clauseOps, iv); + cp.processReduction(loc, clauseOps); + cp.processIf(llvm::omp::Directive::OMPD_simd, clauseOps); + cp.processSimdlen(clauseOps); + cp.processSafelen(clauseOps); + clauseOps.loopInclusiveAttr = firOpBuilder.getUnitAttr(); + // TODO Support delayed privatization. + cp.processTODO(loc, ompDirective); - mlir::TypeRange resultType; - auto simdLoopOp = firOpBuilder.create( - loc, resultType, lowerBound, upperBound, step, alignedVars, - /*alignment_values=*/nullptr, ifClauseOperand, nontemporalVars, - orderClauseOperand, simdlenClauseOperand, safelenClauseOperand, - /*inclusive=*/firOpBuilder.getUnitAttr()); - auto *nestedEval = getCollapsedLoopEval( eval, Fortran::lower::getCollapseValue(loopOpClauseList)); @@ -1744,11 +1659,12 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter, return genLoopVars(op, converter, loc, iv); }; - createBodyOfOp( - simdLoopOp, OpWithBodyGenInfo(converter, semaCtx, loc, *nestedEval) - .setClauses(&loopOpClauseList) - .setDataSharingProcessor(&dsp) - .setGenRegionEntryCb(ivCallback)); + genOpWithBody( + OpWithBodyGenInfo(converter, semaCtx, loc, *nestedEval) + .setClauses(&loopOpClauseList) + .setDataSharingProcessor(&dsp) + .setGenRegionEntryCb(ivCallback), + clauseOps); } static void createWsloop(Fortran::lower::AbstractConverter &converter, @@ -1763,77 +1679,50 @@ static void createWsloop(Fortran::lower::AbstractConverter &converter, dsp.processStep1(); Fortran::lower::StatementContext stmtCtx; - mlir::Value scheduleChunkClauseOperand; - llvm::SmallVector lowerBound, upperBound, step, reductionVars; - llvm::SmallVector linearVars, linearStepVars; + mlir::omp::WsloopClauseOps clauseOps; llvm::SmallVector iv; llvm::SmallVector reductionTypes; - llvm::SmallVector reductionDeclSymbols; - llvm::SmallVector reductionSymbols; - mlir::omp::ClauseOrderKindAttr orderClauseOperand; - mlir::omp::ClauseScheduleKindAttr scheduleValClauseOperand; - mlir::UnitAttr nowaitClauseOperand, byrefOperand, scheduleSimdClauseOperand; - mlir::IntegerAttr orderedClauseOperand; - mlir::omp::ScheduleModifierAttr scheduleModClauseOperand; + llvm::SmallVector reductionSyms; ClauseProcessor cp(converter, semaCtx, beginClauseList); - cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv); - cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand); - cp.processReduction(loc, reductionVars, reductionTypes, reductionDeclSymbols, - &reductionSymbols); - cp.processTODO(loc, ompDirective); - - if (ReductionProcessor::doReductionByRef(reductionVars)) - byrefOperand = firOpBuilder.getUnitAttr(); - - auto wsLoopOp = firOpBuilder.create( - loc, lowerBound, upperBound, step, linearVars, linearStepVars, - reductionVars, - reductionDeclSymbols.empty() - ? nullptr - : mlir::ArrayAttr::get(firOpBuilder.getContext(), - reductionDeclSymbols), - scheduleValClauseOperand, scheduleChunkClauseOperand, - /*schedule_modifiers=*/nullptr, - /*simd_modifier=*/nullptr, nowaitClauseOperand, byrefOperand, - orderedClauseOperand, orderClauseOperand, - /*inclusive=*/firOpBuilder.getUnitAttr()); - - // Handle attribute based clauses. - if (cp.processOrdered(orderedClauseOperand)) - wsLoopOp.setOrderedValAttr(orderedClauseOperand); - - if (cp.processSchedule(scheduleValClauseOperand, scheduleModClauseOperand, - scheduleSimdClauseOperand)) { - wsLoopOp.setScheduleValAttr(scheduleValClauseOperand); - wsLoopOp.setScheduleModifierAttr(scheduleModClauseOperand); - wsLoopOp.setSimdModifierAttr(scheduleSimdClauseOperand); - } + cp.processCollapse(loc, eval, clauseOps, iv); + cp.processSchedule(stmtCtx, clauseOps); + cp.processReduction(loc, clauseOps, &reductionTypes, &reductionSyms); + cp.processOrdered(clauseOps); + clauseOps.loopInclusiveAttr = firOpBuilder.getUnitAttr(); + // TODO Support delayed privatization. + + if (ReductionProcessor::doReductionByRef(clauseOps.reductionVars)) + clauseOps.reductionByRefAttr = firOpBuilder.getUnitAttr(); + + cp.processTODO(loc, + ompDirective); + // In FORTRAN `nowait` clause occur at the end of `omp do` directive. // i.e // !$omp do // <...> // !$omp end do nowait if (endClauseList) { - if (ClauseProcessor(converter, semaCtx, *endClauseList) - .processNowait(nowaitClauseOperand)) - wsLoopOp.setNowaitAttr(nowaitClauseOperand); + ClauseProcessor ecp(converter, semaCtx, *endClauseList); + ecp.processNowait(clauseOps); } auto *nestedEval = getCollapsedLoopEval( eval, Fortran::lower::getCollapseValue(beginClauseList)); auto ivCallback = [&](mlir::Operation *op) { - return genLoopAndReductionVars(op, converter, loc, iv, reductionSymbols, + return genLoopAndReductionVars(op, converter, loc, iv, reductionSyms, reductionTypes); }; - createBodyOfOp( - wsLoopOp, OpWithBodyGenInfo(converter, semaCtx, loc, *nestedEval) - .setClauses(&beginClauseList) - .setDataSharingProcessor(&dsp) - .setReductions(&reductionSymbols, &reductionTypes) - .setGenRegionEntryCb(ivCallback)); + genOpWithBody( + OpWithBodyGenInfo(converter, semaCtx, loc, *nestedEval) + .setClauses(&beginClauseList) + .setDataSharingProcessor(&dsp) + .setReductions(&reductionSyms, &reductionTypes) + .setGenRegionEntryCb(ivCallback), + clauseOps); } static void createSimdWsloop( @@ -1921,10 +1810,11 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct) { + mlir::omp::DeclareTargetClauseOps clauseOps; llvm::SmallVector symbolAndClause; mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); - mlir::omp::DeclareTargetDeviceType deviceType = getDeclareTargetInfo( - converter, semaCtx, eval, declareTargetConstruct, symbolAndClause); + getDeclareTargetInfo(converter, semaCtx, eval, declareTargetConstruct, + clauseOps, symbolAndClause); for (const DeclareTargetCapturePair &symClause : symbolAndClause) { mlir::Operation *op = mod.lookupSymbol(converter.mangleName( @@ -1938,7 +1828,8 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, markDeclareTarget( op, converter, - std::get(symClause), deviceType); + std::get(symClause), + clauseOps.deviceType); } } @@ -2072,7 +1963,8 @@ genOMP(Fortran::lower::AbstractConverter &converter, !std::get_if(&clause.u) && !std::get_if(&clause.u) && !std::get_if(&clause.u) && - !std::get_if(&clause.u)) { + !std::get_if(&clause.u) && + !std::get_if(&clause.u)) { TODO(clauseLocation, "OpenMP Block construct clause"); } } @@ -2092,7 +1984,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, break; case llvm::omp::Directive::OMPD_ordered: genOrderedRegionOp(converter, semaCtx, eval, /*genNested=*/true, - currentLocation); + currentLocation, beginClauseList); break; case llvm::omp::Directive::OMPD_parallel: genParallelOp(converter, symTable, semaCtx, eval, /*genNested=*/true, @@ -2183,7 +2075,6 @@ genOMP(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OpenMPCriticalConstruct &criticalConstruct) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location currentLocation = converter.getCurrentLocation(); - mlir::IntegerAttr hintClauseOp; std::string name; const Fortran::parser::OmpCriticalDirective &cd = std::get(criticalConstruct.t); @@ -2192,21 +2083,28 @@ genOMP(Fortran::lower::AbstractConverter &converter, std::get>(cd.t).value().ToString(); } - const auto &clauseList = std::get(cd.t); - ClauseProcessor(converter, semaCtx, clauseList).processHint(hintClauseOp); - mlir::omp::CriticalOp criticalOp = [&]() { if (name.empty()) { return firOpBuilder.create( currentLocation, mlir::FlatSymbolRefAttr()); } + mlir::ModuleOp module = firOpBuilder.getModule(); mlir::OpBuilder modBuilder(module.getBodyRegion()); auto global = module.lookupSymbol(name); - if (!global) - global = modBuilder.create( - currentLocation, - mlir::StringAttr::get(firOpBuilder.getContext(), name), hintClauseOp); + if (!global) { + mlir::omp::CriticalClauseOps clauseOps; + const auto &clauseList = std::get(cd.t); + + ClauseProcessor cp(converter, semaCtx, clauseList); + cp.processHint(clauseOps); + clauseOps.nameAttr = + mlir::StringAttr::get(firOpBuilder.getContext(), name); + + global = modBuilder.create(currentLocation, + clauseOps); + } + return firOpBuilder.create( currentLocation, mlir::FlatSymbolRefAttr::get(firOpBuilder.getContext(), global.getSymName())); @@ -2323,8 +2221,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPSectionsConstruct §ionsConstruct) { mlir::Location currentLocation = converter.getCurrentLocation(); - llvm::SmallVector allocateOperands, allocatorOperands; - mlir::UnitAttr nowaitClauseOperand; + mlir::omp::SectionsClauseOps clauseOps; const auto &beginSectionsDirective = std::get(sectionsConstruct.t); const auto §ionsClauseList = @@ -2333,8 +2230,9 @@ genOMP(Fortran::lower::AbstractConverter &converter, // Process clauses before optional omp.parallel, so that new variables are // allocated outside of the parallel region ClauseProcessor cp(converter, semaCtx, sectionsClauseList); - cp.processSectionsReduction(currentLocation); - cp.processAllocate(allocatorOperands, allocateOperands); + cp.processSectionsReduction(currentLocation, clauseOps); + cp.processAllocate(clauseOps); + // TODO Support delayed privatization. llvm::omp::Directive dir = std::get(beginSectionsDirective.t) @@ -2351,16 +2249,14 @@ genOMP(Fortran::lower::AbstractConverter &converter, const auto &endSectionsClauseList = std::get(endSectionsDirective.t); ClauseProcessor(converter, semaCtx, endSectionsClauseList) - .processNowait(nowaitClauseOperand); + .processNowait(clauseOps); } // SECTIONS construct genOpWithBody( OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(false), - /*reduction_vars=*/mlir::ValueRange(), - /*reductions=*/nullptr, allocateOperands, allocatorOperands, - nowaitClauseOperand); + clauseOps); const auto §ionBlocks = std::get(sectionsConstruct.t); diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h index 4ce7e47da046..304a9740d91e 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h @@ -81,7 +81,7 @@ struct GrainsizeClauseOps { Value grainsizeVar; }; -struct HasDeviceAddrOps { +struct HasDeviceAddrClauseOps { llvm::SmallVector hasDeviceAddrVars; }; struct HintClauseOps { @@ -97,7 +97,7 @@ struct InReductionClauseOps { llvm::SmallVector inReductionDeclSymbols; }; -struct IsDevicePtrOps { +struct IsDevicePtrClauseOps { llvm::SmallVector isDevicePtrVars; }; @@ -234,6 +234,8 @@ using DistributeClauseOps = detail::Clauses; +using LoopNestClauseOps = detail::Clauses; + // TODO `filter` clause. using MaskedClauseOps = detail::Clauses<>; @@ -261,8 +263,8 @@ using SingleClauseOps = detail::Clauses; using TargetDataClauseOps = detail::Clauses:$step, UnitAttr:$inclusive); + let builders = [ + OpBuilder<(ins CArg<"const LoopNestClauseOps &">:$clauses)> + ]; + let regions = (region AnyRegion:$region); let extraClassDeclaration = [{ diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index 4ab78bf331f8..35fb174046a3 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -1920,6 +1920,12 @@ void LoopNestOp::print(OpAsmPrinter &p) { p.printRegion(region, /*printEntryBlockArgs=*/false); } +void LoopNestOp::build(OpBuilder &builder, OperationState &state, + const LoopNestClauseOps &clauses) { + LoopNestOp::build(builder, state, clauses.loopLBVar, clauses.loopUBVar, + clauses.loopStepVar, clauses.loopInclusiveAttr); +} + LogicalResult LoopNestOp::verify() { if (getLowerBound().size() != getIVs().size()) return emitOpError() << "number of range arguments and IVs do not match"; -- GitLab From 33779b861d748ed18b8d4f9cbad3a84deaa95e9f Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Fri, 12 Apr 2024 07:41:43 -0400 Subject: [PATCH 052/464] Reword a diagnostic; NFC This diagnostic used to talk about complex integer types but is issued for use of the increment or decrement operators on any complex type, not just integral ones. The diagnostic also had zero test coverage, so new coverage is added along with the rewording. --- .../clang/Basic/DiagnosticSemaKinds.td | 4 ++-- clang/lib/Sema/SemaExpr.cpp | 4 ++-- clang/test/Sema/complex-inc-dec.c | 24 +++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 clang/test/Sema/complex-inc-dec.c diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 180e913155d6..774d2b53a382 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7588,8 +7588,8 @@ def ext_gnu_ptr_func_arith : Extension< InGroup; def err_readonly_message_assignment : Error< "assigning to 'readonly' return result of an Objective-C message not allowed">; -def ext_integer_increment_complex : Extension< - "ISO C does not support '++'/'--' on complex integer type %0">; +def ext_increment_complex : Extension< + "'%select{--|++}0' on an object of complex type is a Clang extension">; def ext_integer_complement_complex : Extension< "ISO C does not support '~' for complex conjugation of %0">; def err_nosetter_property_assignment : Error< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 18284e0c3e98..b294d2bd9f53 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14859,8 +14859,8 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, return QualType(); } else if (ResType->isAnyComplexType()) { // C99 does not support ++/-- on complex types, we allow as an extension. - S.Diag(OpLoc, diag::ext_integer_increment_complex) - << ResType << Op->getSourceRange(); + S.Diag(OpLoc, diag::ext_increment_complex) + << IsInc << Op->getSourceRange(); } else if (ResType->isPlaceholderType()) { ExprResult PR = S.CheckPlaceholderExpr(Op); if (PR.isInvalid()) return QualType(); diff --git a/clang/test/Sema/complex-inc-dec.c b/clang/test/Sema/complex-inc-dec.c new file mode 100644 index 000000000000..ebc23c36f40c --- /dev/null +++ b/clang/test/Sema/complex-inc-dec.c @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -verify -pedantic -std=c99 %s + +void func(void) { + _Complex float cf; + _Complex double cd; + _Complex long double cld; + + ++cf; // expected-warning {{'++' on an object of complex type is a Clang extension}} + ++cd; // expected-warning {{'++' on an object of complex type is a Clang extension}} + ++cld; // expected-warning {{'++' on an object of complex type is a Clang extension}} + + --cf; // expected-warning {{'--' on an object of complex type is a Clang extension}} + --cd; // expected-warning {{'--' on an object of complex type is a Clang extension}} + --cld; // expected-warning {{'--' on an object of complex type is a Clang extension}} + + cf++; // expected-warning {{'++' on an object of complex type is a Clang extension}} + cd++; // expected-warning {{'++' on an object of complex type is a Clang extension}} + cld++; // expected-warning {{'++' on an object of complex type is a Clang extension}} + + cf--; // expected-warning {{'--' on an object of complex type is a Clang extension}} + cd--; // expected-warning {{'--' on an object of complex type is a Clang extension}} + cld--; // expected-warning {{'--' on an object of complex type is a Clang extension}} +} + -- GitLab From 5ebeaf211551f9410e17b1134126daadd8b163ac Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Fri, 12 Apr 2024 16:02:57 +0400 Subject: [PATCH 053/464] [clang] Add tests for some CWG 5xx issues (#87909) This patch covers [CWG393](https://cplusplus.github.io/CWG/issues/393.html) "Pointer to array of unknown bound in template argument list in parameter", [CWG528](https://cplusplus.github.io/CWG/issues/528.html) "Why are incomplete class types not allowed with `typeid`?", [CWG550](https://cplusplus.github.io/CWG/issues/550.html) "Pointer to array of unknown bound in parameter declarations", [CWG553](https://cplusplus.github.io/CWG/issues/553.html) "Problems with friend allocation and deallocation functions", [CWG555](https://cplusplus.github.io/CWG/issues/555.html) "Pseudo-destructor name lookup", [CWG560](https://cplusplus.github.io/CWG/issues/560.html) "Use of the `typename` keyword in return types". CWG393 is on this list, because CWG550 is marked as a duplicate of CWG393. Test for CWG553 has been already written, but it was missing a status comment. As a drive-by fix, I'm adding missing status comments to CWG1584 and CWG1903 as well. CWG555 used CWG466 test, and also a variation of that test to test references. CWG466 is now testing non-reference non-pointer case. CWG560 showcases again that converting warnings to errors in DR tests via `-pedantic-errors` doesn't make things more clear. By default that test is accepted with an extension warning since we implemented [P0634R3](https://wg21.link/p0634r3) "Down with `typename`!" in Clang 16. --- clang/test/CXX/drs/dr15xx.cpp | 2 +- clang/test/CXX/drs/dr19xx.cpp | 2 +- clang/test/CXX/drs/dr3xx.cpp | 19 ++++++++ clang/test/CXX/drs/dr4xx.cpp | 60 +++++++++++------------ clang/test/CXX/drs/dr5xx.cpp | 89 +++++++++++++++++++++++++++++++++++ clang/www/cxx_dr_status.html | 16 +++---- 6 files changed, 149 insertions(+), 39 deletions(-) diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp index 195c0fa610d5..6e3ad41c748f 100644 --- a/clang/test/CXX/drs/dr15xx.cpp +++ b/clang/test/CXX/drs/dr15xx.cpp @@ -555,7 +555,7 @@ auto DR1579_lambda_invalid = []() -> GenericMoveOnly { #endif } // end namespace dr1579 -namespace dr1584 { +namespace dr1584 { // dr1584: 7 drafting 2015-05 #if __cplusplus >= 201103L // Deducing function types from cv-qualified types template void f(const T *); // #dr1584-f diff --git a/clang/test/CXX/drs/dr19xx.cpp b/clang/test/CXX/drs/dr19xx.cpp index 716b1476831e..f8c1581f0854 100644 --- a/clang/test/CXX/drs/dr19xx.cpp +++ b/clang/test/CXX/drs/dr19xx.cpp @@ -34,7 +34,7 @@ namespace dr1902 { // dr1902: 3.7 #endif } -namespace dr1903 { +namespace dr1903 { // dr1903: 2.7 namespace A { struct a {}; int a; diff --git a/clang/test/CXX/drs/dr3xx.cpp b/clang/test/CXX/drs/dr3xx.cpp index 483ebf7a08aa..d5cfebccf813 100644 --- a/clang/test/CXX/drs/dr3xx.cpp +++ b/clang/test/CXX/drs/dr3xx.cpp @@ -1568,6 +1568,25 @@ namespace dr391 { // dr391: 2.8 c++11 } // dr392 is in dr392.cpp + +namespace dr393 { // dr393: 2.7 +template +struct S {}; + +void f1(S); +void f2(S); +void g(int(*S::*)[]); + +template +void sp_assert_convertible( T* ) {} + +template +void h() { + T (*p) [] = (U(*)[])0; + sp_assert_convertible( (U(*)[])0 ); +} +} // namespace dr393 + // dr394: na namespace dr395 { // dr395: 3.0 diff --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp index 34dd638c1d9b..9b7a9777202f 100644 --- a/clang/test/CXX/drs/dr4xx.cpp +++ b/clang/test/CXX/drs/dr4xx.cpp @@ -2,8 +2,9 @@ // RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++11 %s -verify=expected,cxx98-14,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++14 %s -verify=expected,cxx98-14,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++17 %s -verify=expected,since-cxx17,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++20 %s -verify=expected,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++23 %s -verify=expected,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++20 %s -verify=expected,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++23 %s -verify=expected,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %clang_cc1 -std=c++2c %s -verify=expected,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // FIXME: __SIZE_TYPE__ expands to 'long long' on some targets. __extension__ typedef __SIZE_TYPE__ size_t; @@ -949,33 +950,34 @@ namespace dr460 { // dr460: yes // dr465: na namespace dr466 { // dr466: 2.8 - typedef int I; - typedef const int CI; - typedef volatile int VI; - void f(int *a, CI *b, VI *c) { - a->~I(); - a->~CI(); - a->~VI(); - a->I::~I(); - a->CI::~CI(); - a->VI::~VI(); - - a->CI::~VI(); // allowed by changes to [expr.id.prim.qual]/2 introduced in P1131R2 - - b->~I(); - b->~CI(); - b->~VI(); - b->I::~I(); - b->CI::~CI(); - b->VI::~VI(); - - c->~I(); - c->~CI(); - c->~VI(); - c->I::~I(); - c->CI::~CI(); - c->VI::~VI(); - } +typedef int I; +typedef const int CI; +typedef volatile int VI; +void g(int a, CI b, VI c) { +// since-cxx20-warning@-1 {{volatile-qualified parameter type 'VI' (aka 'volatile int') is deprecated}} + a.~I(); + a.~CI(); + a.~VI(); + a.I::~I(); + a.CI::~CI(); + a.VI::~VI(); + + a.CI::~VI(); // allowed by changes to [expr.id.prim.qual]/2 introduced in P1131R2 + + b.~I(); + b.~CI(); + b.~VI(); + b.I::~I(); + b.CI::~CI(); + b.VI::~VI(); + + c.~I(); + c.~CI(); + c.~VI(); + c.I::~I(); + c.CI::~CI(); + c.VI::~VI(); +} } namespace dr467 { // dr467: yes diff --git a/clang/test/CXX/drs/dr5xx.cpp b/clang/test/CXX/drs/dr5xx.cpp index 0ea306a04116..d473f4827455 100644 --- a/clang/test/CXX/drs/dr5xx.cpp +++ b/clang/test/CXX/drs/dr5xx.cpp @@ -18,6 +18,10 @@ namespace std { void *operator new(size_t, std::align_val_t); // #dr5xx-global-operator-new-aligned #endif +namespace std { + struct type_info; +} + namespace dr500 { // dr500: dup 372 class D; class A { @@ -265,6 +269,18 @@ namespace dr527 { // dr527: na int ax = a.x, bx = b.x, cx = c.x, dx = d.x, ex = E::e->x, fx = F::f->x; } +namespace dr528 { // dr528: 2.7 + +struct S; // #dr528-S + +void f() { + typeid(S); + // expected-error@-1 {{'typeid' of incomplete type 'S'}} + // expected-note@#dr528-S {{forward declaration of 'dr528::S'}} +} + +} // namespace dr528 + namespace dr530 { // dr530: yes template struct S { enum { N = 1 }; }; template struct T { enum { N = 1 }; }; @@ -618,6 +634,8 @@ namespace dr548 { // dr548: dup 482 template void dr548::f(); } +// dr550: dup 393 + namespace dr551 { // dr551: yes c++11 // FIXME: This obviously should apply in C++98 mode too. template void f() {} @@ -641,6 +659,7 @@ namespace dr552 { // dr552: yes X x; } +// dr553: 2.7 struct dr553_class { friend void *operator new(size_t, dr553_class); }; @@ -661,6 +680,62 @@ namespace dr553 { } // dr554: na + +namespace dr555 { // dr555: 2.8 +typedef int I; +typedef const int CI; +typedef volatile int VI; +void f(int *a, CI *b, VI *c) { + a->~I(); + a->~CI(); + a->~VI(); + a->I::~I(); + a->CI::~CI(); + a->VI::~VI(); + + a->CI::~VI(); // allowed by changes to [expr.id.prim.qual]/2 introduced in P1131R2 + + b->~I(); + b->~CI(); + b->~VI(); + b->I::~I(); + b->CI::~CI(); + b->VI::~VI(); + + c->~I(); + c->~CI(); + c->~VI(); + c->I::~I(); + c->CI::~CI(); + c->VI::~VI(); +} + +void g(int &a, CI &b, VI &c) { + a.~I(); + a.~CI(); + a.~VI(); + a.I::~I(); + a.CI::~CI(); + a.VI::~VI(); + + a.CI::~VI(); // allowed by changes to [expr.id.prim.qual]/2 introduced in P1131R2 + + b.~I(); + b.~CI(); + b.~VI(); + b.I::~I(); + b.CI::~CI(); + b.VI::~VI(); + + c.~I(); + c.~CI(); + c.~VI(); + c.I::~I(); + c.CI::~CI(); + c.VI::~VI(); +} +} // namespace dr555 + // dr556: na namespace dr557 { // dr557: 3.1 @@ -689,6 +764,20 @@ namespace dr558 { // dr558: 2.9 template struct dr559 { typedef int T; dr559::T u; }; // dr559: yes +namespace dr560 { // dr560: 16 + +template +struct Outer { + struct Inner { + Inner* self(); + }; +}; +template +Outer::Inner* Outer::Inner::self() { return this; } +// cxx98-17-error@-1 {{missing 'typename' prior to dependent type name Outer::Inner; implicit 'typename' is a C++20 extension}} + +} // namespace dr560 + namespace dr561 { // dr561: yes template void f(int); template void g(T t) { diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 6daa5ad2d131..83b71e7c122d 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -2398,7 +2398,7 @@ of class templates 393 CD4 Pointer to array of unknown bound in template argument list in parameter - Unknown + Clang 2.7 394 @@ -3208,7 +3208,7 @@ of class templates 528 NAD Why are incomplete class types not allowed with typeid? - Unknown + Clang 2.7 529 @@ -3342,7 +3342,7 @@ and POD class 550 dup Pointer to array of unknown bound in parameter declarations - Unknown + Duplicate of 393 551 @@ -3360,7 +3360,7 @@ and POD class 553 NAD Problems with friend allocation and deallocation functions - Unknown + Clang 2.7 554 @@ -3372,7 +3372,7 @@ and POD class 555 CD5 Pseudo-destructor name lookup - Unknown + Clang 2.8 556 @@ -3402,7 +3402,7 @@ and POD class 560 NAD Use of the typename keyword in return types - Unknown + Clang 16 561 @@ -9312,7 +9312,7 @@ and POD class 1584 drafting Deducing function types from cv-qualified types - Not resolved + Not Resolved* 1585 @@ -11226,7 +11226,7 @@ and POD class 1903 CD4 What declarations are introduced by a non-member using-declaration? - Unknown + Clang 2.7 1904 -- GitLab From ab037c4ff3452a680efb758ccacb6ee210ce333b Mon Sep 17 00:00:00 2001 From: SahilPatidar Date: Fri, 12 Apr 2024 17:34:54 +0530 Subject: [PATCH 054/464] [DAG] computeKnownBits - add ISD::ABDU/ISD::ABDS handling #84905 (#88253) Resolve #84905 --- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 12 ++ llvm/test/CodeGen/AArch64/abd-combine.ll | 12 +- .../CodeGen/AArch64/arm64-neon-aba-abd.ll | 157 ++++++++++++++++++ 3 files changed, 174 insertions(+), 7 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index e002cf1d1de3..ddb12a101e02 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3397,6 +3397,18 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts, Known = KnownBits::mulhs(Known, Known2); break; } + case ISD::ABDU: { + Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); + Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); + Known = KnownBits::abdu(Known, Known2); + break; + } + case ISD::ABDS: { + Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); + Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); + Known = KnownBits::abds(Known, Known2); + break; + } case ISD::UMUL_LOHI: { assert((Op.getResNo() == 0 || Op.getResNo() == 1) && "Unknown result"); Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); diff --git a/llvm/test/CodeGen/AArch64/abd-combine.ll b/llvm/test/CodeGen/AArch64/abd-combine.ll index cc29a59288c7..e48680f4be98 100644 --- a/llvm/test/CodeGen/AArch64/abd-combine.ll +++ b/llvm/test/CodeGen/AArch64/abd-combine.ll @@ -530,13 +530,11 @@ define <8 x i16> @abds_i_reassoc(<8 x i16> %src1) { define <1 x i64> @recursive() { ; CHECK-LABEL: recursive: ; CHECK: // %bb.0: -; CHECK-NEXT: movi v0.2d, #0xffffffffffffffff -; CHECK-NEXT: movi v1.8b, #1 -; CHECK-NEXT: uabd v2.8b, v1.8b, v0.8b -; CHECK-NEXT: uabdl v0.8h, v1.8b, v0.8b -; CHECK-NEXT: dup v1.8b, v2.b[0] -; CHECK-NEXT: saddlp v0.1d, v0.2s -; CHECK-NEXT: orr v0.8b, v1.8b, v0.8b +; CHECK-NEXT: movi v0.8b, #254 +; CHECK-NEXT: ushll v1.8h, v0.8b, #0 +; CHECK-NEXT: dup v0.8b, v0.b[0] +; CHECK-NEXT: saddlp v1.1d, v1.2s +; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b ; CHECK-NEXT: ret %1 = tail call <8 x i8> @llvm.aarch64.neon.umax.v8i8(<8 x i8> zeroinitializer, <8 x i8> ) %2 = tail call <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8> %1, <8 x i8> ) diff --git a/llvm/test/CodeGen/AArch64/arm64-neon-aba-abd.ll b/llvm/test/CodeGen/AArch64/arm64-neon-aba-abd.ll index a13eac9b0a5e..cc9732b83e10 100644 --- a/llvm/test/CodeGen/AArch64/arm64-neon-aba-abd.ll +++ b/llvm/test/CodeGen/AArch64/arm64-neon-aba-abd.ll @@ -291,3 +291,160 @@ define <2 x double> @test_fabd_v2f64(<2 x double> %lhs, <2 x double> %rhs) { %abd = call <2 x double> @llvm.aarch64.neon.fabd.v2f64(<2 x double> %lhs, <2 x double> %rhs) ret <2 x double> %abd } + +define <8 x i16> @test_uabd_knownbits_vec8i16(<8 x i16> %lhs, <8 x i16> %rhs) { +; CHECK-LABEL: test_uabd_knownbits_vec8i16: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v2.8h, #15 +; CHECK-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-NEXT: and v1.16b, v1.16b, v2.16b +; CHECK-NEXT: uabd v0.8h, v0.8h, v1.8h +; CHECK-NEXT: rev64 v0.8h, v0.8h +; CHECK-NEXT: ext v0.16b, v0.16b, v0.16b, #8 +; CHECK-NEXT: ret + %and1 = and <8 x i16> %lhs, + %and2 = and <8 x i16> %rhs, + %uabd = call <8 x i16> @llvm.aarch64.neon.uabd.v8i16(<8 x i16> %and1, <8 x i16> %and2) + %suff = shufflevector <8 x i16> %uabd, <8 x i16> undef, <8 x i32> + %res = and <8 x i16> %suff, + ret <8 x i16> %res +} + +define <4 x i32> @knownbits_uabd_mask_and_shuffle_lshr(<4 x i32> %a0, <4 x i32> %a1) { +; CHECK-LABEL: knownbits_uabd_mask_and_shuffle_lshr: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: ushr v0.4s, v0.4s, #17 +; CHECK-NEXT: ret + %1 = and <4 x i32> %a0, + %2 = and <4 x i32> %a1, + %3 = call <4 x i32> @llvm.aarch64.neon.uabd.v4i32(<4 x i32> %1, <4 x i32> %2) + %4 = shufflevector <4 x i32> %3, <4 x i32> undef, <4 x i32> + %5 = lshr <4 x i32> %4, + ret <4 x i32> %5 +} + +define <4 x i32> @knownbits_mask_and_shuffle_lshr(<4 x i32> %a0, <4 x i32> %a1) { +; CHECK-LABEL: knownbits_mask_and_shuffle_lshr: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: ret + %1 = and <4 x i32> %a0, + %2 = and <4 x i32> %a1, + %3 = call <4 x i32> @llvm.aarch64.neon.uabd.v4i32(<4 x i32> %1, <4 x i32> %2) + %4 = shufflevector <4 x i32> %3, <4 x i32> undef, <4 x i32> + %5 = lshr <4 x i32> %4, + ret <4 x i32> %5 +} + +define <4 x i32> @test_sabd_knownbits_vec4i32(<4 x i32> %lhs, <4 x i32> %rhs) { +; CHECK-LABEL: test_sabd_knownbits_vec4i32: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI31_0 +; CHECK-NEXT: adrp x9, .LCPI31_1 +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI31_0] +; CHECK-NEXT: ldr q3, [x9, :lo12:.LCPI31_1] +; CHECK-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-NEXT: and v1.16b, v1.16b, v3.16b +; CHECK-NEXT: sabd v0.4s, v0.4s, v1.4s +; CHECK-NEXT: movi v1.2d, #0x0000ff000000ff +; CHECK-NEXT: mov v0.s[1], v0.s[0] +; CHECK-NEXT: trn2 v0.4s, v0.4s, v0.4s +; CHECK-NEXT: and v0.16b, v0.16b, v1.16b +; CHECK-NEXT: ret + %and1 = and <4 x i32> %lhs, + %and2 = and <4 x i32> %rhs, + %abd = call <4 x i32> @llvm.aarch64.neon.sabd.v4i32(<4 x i32> %and1, <4 x i32> %and2) + %s = shufflevector <4 x i32> %abd, <4 x i32> undef, <4 x i32> + %4 = and <4 x i32> %s, + ret <4 x i32> %4 +} + +define <4 x i32> @knownbits_sabd_and_mask(<4 x i32> %a0, <4 x i32> %a1) { +; CHECK-LABEL: knownbits_sabd_and_mask: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI32_0 +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI32_0] +; CHECK-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-NEXT: and v1.16b, v1.16b, v2.16b +; CHECK-NEXT: sabd v0.4s, v0.4s, v1.4s +; CHECK-NEXT: zip2 v0.4s, v0.4s, v0.4s +; CHECK-NEXT: ret + %1 = and <4 x i32> %a0, + %2 = and <4 x i32> %a1, + %3 = call <4 x i32> @llvm.aarch64.neon.sabd.v4i32(<4 x i32> %1, <4 x i32> %2) + %4 = shufflevector <4 x i32> %3, <4 x i32> undef, <4 x i32> + ret <4 x i32> %4 +} + +define <4 x i32> @knownbits_sabd_and_or_mask(<4 x i32> %a0, <4 x i32> %a1) { +; CHECK-LABEL: knownbits_sabd_and_or_mask: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: ret + %1 = and <4 x i32> %a0, + %2 = or <4 x i32> %1, + %3 = and <4 x i32> %a1, + %4 = or <4 x i32> %3, + %5 = call <4 x i32> @llvm.aarch64.neon.uabd.v4i32(<4 x i32> %2, <4 x i32> %4) + %6 = shufflevector <4 x i32> %5, <4 x i32> undef, <4 x i32> + ret <4 x i32> %6 +} + +define <4 x i32> @knownbits_sabd_and_xor_mask(<4 x i32> %a0, <4 x i32> %a1) { +; CHECK-LABEL: knownbits_sabd_and_xor_mask: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI34_0 +; CHECK-NEXT: movi v3.2d, #0x00ffff0000ffff +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI34_0] +; CHECK-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-NEXT: and v1.16b, v1.16b, v2.16b +; CHECK-NEXT: eor v0.16b, v0.16b, v3.16b +; CHECK-NEXT: eor v1.16b, v1.16b, v3.16b +; CHECK-NEXT: sabd v0.4s, v0.4s, v1.4s +; CHECK-NEXT: zip2 v0.4s, v0.4s, v0.4s +; CHECK-NEXT: ret + %1 = and <4 x i32> %a0, + %2 = xor <4 x i32> %1, + %3 = and <4 x i32> %a1, + %4 = xor <4 x i32> %3, + %5 = call <4 x i32> @llvm.aarch64.neon.sabd.v4i32(<4 x i32> %2, <4 x i32> %4) + %6 = shufflevector <4 x i32> %5, <4 x i32> undef, <4 x i32> + ret <4 x i32> %6 +} + +define <4 x i32> @knownbits_sabd_and_shl_mask(<4 x i32> %a0, <4 x i32> %a1) { +; CHECK-LABEL: knownbits_sabd_and_shl_mask: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: ret + %1 = and <4 x i32> %a0, + %2 = shl <4 x i32> %1, + %3 = and <4 x i32> %a1, + %4 = shl <4 x i32> %3, + %5 = call <4 x i32> @llvm.aarch64.neon.sabd.v4i32(<4 x i32> %2, <4 x i32> %4) + %6 = shufflevector <4 x i32> %5, <4 x i32> undef, <4 x i32> + ret <4 x i32> %6 +} + +define <4 x i32> @knownbits_sabd_and_mul_mask(<4 x i32> %a0, <4 x i32> %a1) { +; CHECK-LABEL: knownbits_sabd_and_mul_mask: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI36_0 +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI36_0] +; CHECK-NEXT: and v3.16b, v0.16b, v2.16b +; CHECK-NEXT: and v2.16b, v1.16b, v2.16b +; CHECK-NEXT: mul v0.4s, v0.4s, v3.4s +; CHECK-NEXT: mul v1.4s, v1.4s, v2.4s +; CHECK-NEXT: sabd v0.4s, v0.4s, v1.4s +; CHECK-NEXT: mov v0.s[1], v0.s[0] +; CHECK-NEXT: trn2 v0.4s, v0.4s, v0.4s +; CHECK-NEXT: ret + %1 = and <4 x i32> %a0, + %2 = mul <4 x i32> %a0, %1 + %3 = and <4 x i32> %a1, + %4 = mul <4 x i32> %a1, %3 + %5 = call <4 x i32> @llvm.aarch64.neon.sabd.v4i32(<4 x i32> %2, <4 x i32> %4) + %6 = shufflevector <4 x i32> %5, <4 x i32> undef, <4 x i32> + ret <4 x i32> %6 +} -- GitLab From 6ec467297db272d5ae8f76e695296bd4945dedc8 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 12 Apr 2024 08:34:43 -0400 Subject: [PATCH 055/464] [BOLT][NFC] Adjust misleading comment & formatting (#88409) This originally dealt with tbss, but now handles any bss-like section. So the comment is inaccurate. Also, the `{}` on the messaging seem unnecessary. --- bolt/lib/Rewrite/RewriteInstance.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index eea66454b289..cbbe7d00d35d 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -4300,7 +4300,7 @@ RewriteInstance::getOutputSections(ELFObjectFile *File, for (auto &SectionKV : OutputSections) { ELFShdrTy &Section = SectionKV.second; - // Ignore TLS sections as they don't take any space in the file. + // Ignore NOBITS sections as they don't take any space in the file. if (Section.sh_type == ELF::SHT_NOBITS) continue; @@ -4308,10 +4308,9 @@ RewriteInstance::getOutputSections(ELFObjectFile *File, // placed in different loadable segments. if (PrevSection && PrevSection->sh_offset + PrevSection->sh_size > Section.sh_offset) { - if (opts::Verbosity > 1) { + if (opts::Verbosity > 1) BC->outs() << "BOLT-INFO: adjusting size for section " << PrevBinSec->getOutputName() << '\n'; - } PrevSection->sh_size = Section.sh_offset - PrevSection->sh_offset; } -- GitLab From f220d26eb1ab5b588215acf538ca82bb3c8798cc Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Fri, 12 Apr 2024 13:43:48 +0100 Subject: [PATCH 056/464] [flang][runtime] Add ACCESS library procedure (#88395) This is a GNU extension: https://gcc.gnu.org/onlinedocs/gfortran/ACCESS.html Used in SALMON: https://salmon-tddft.jp/download.html Unfortunately the intrinsic takes a file path to operate on so there isn't an easy way to make the test robust. The unit test expects to be able to create, set read write and execute permissions, and delete files called `std::filesystem::temp_directory_path() / .` The test will fail if a file already exists with that name. I have not implemented the intrinsic on Windows because this is wrapping a POSIX system call and Windows doesn't support all of the permission bits tested by the intrinsic. I don't have a Windows machine easily available to check if Gfortran implements this intrinsic on Windows. --- flang/docs/Intrinsics.md | 8 + flang/include/flang/Runtime/extensions.h | 7 + flang/runtime/extensions.cpp | 73 +++++ flang/unittests/Runtime/AccessTest.cpp | 390 +++++++++++++++++++++++ flang/unittests/Runtime/CMakeLists.txt | 1 + 5 files changed, 479 insertions(+) create mode 100644 flang/unittests/Runtime/AccessTest.cpp diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md index ccb93e104dab..848619cb65d9 100644 --- a/flang/docs/Intrinsics.md +++ b/flang/docs/Intrinsics.md @@ -657,6 +657,14 @@ CALL CO_REDUCE CALL CO_SUM ``` +### Inquiry Functions +ACCESS (GNU extension) is not supported on Windows. Otherwise: +``` +CHARACTER(LEN=*) :: path = 'path/to/file' +IF (ACCESS(path, 'rwx')) & + ... +``` + ## Non-standard intrinsics ### PGI ``` diff --git a/flang/include/flang/Runtime/extensions.h b/flang/include/flang/Runtime/extensions.h index 7d0952206fc1..fef651f3b2ee 100644 --- a/flang/include/flang/Runtime/extensions.h +++ b/flang/include/flang/Runtime/extensions.h @@ -44,5 +44,12 @@ std::int64_t RTNAME(Signal)(std::int64_t number, void (*handler)(int)); // GNU extension subroutine SLEEP(SECONDS) void RTNAME(Sleep)(std::int64_t seconds); +// GNU extension function ACCESS(NAME, MODE) +// TODO: not supported on Windows +#ifndef _WIN32 +std::int64_t FORTRAN_PROCEDURE_NAME(access)(const char *name, + std::int64_t nameLength, const char *mode, std::int64_t modeLength); +#endif + } // extern "C" #endif // FORTRAN_RUNTIME_EXTENSIONS_H_ diff --git a/flang/runtime/extensions.cpp b/flang/runtime/extensions.cpp index 3ac98000335d..12498b502ae1 100644 --- a/flang/runtime/extensions.cpp +++ b/flang/runtime/extensions.cpp @@ -17,6 +17,7 @@ #include "flang/Runtime/entry-names.h" #include "flang/Runtime/io-api.h" #include +#include #include #include #include @@ -138,5 +139,77 @@ void RTNAME(Sleep)(std::int64_t seconds) { std::this_thread::sleep_for(std::chrono::seconds(seconds)); } +// TODO: not supported on Windows +#ifndef _WIN32 +std::int64_t FORTRAN_PROCEDURE_NAME(access)(const char *name, + std::int64_t nameLength, const char *mode, std::int64_t modeLength) { + std::int64_t ret{-1}; + if (nameLength <= 0 || modeLength <= 0 || !name || !mode) { + return ret; + } + + // ensure name is null terminated + char *newName{nullptr}; + if (name[nameLength - 1] != '\0') { + newName = static_cast(std::malloc(nameLength + 1)); + std::memcpy(newName, name, nameLength); + newName[nameLength] = '\0'; + name = newName; + } + + // calculate mode + bool read{false}; + bool write{false}; + bool execute{false}; + bool exists{false}; + int imode{0}; + + for (std::int64_t i = 0; i < modeLength; ++i) { + switch (mode[i]) { + case 'r': + read = true; + break; + case 'w': + write = true; + break; + case 'x': + execute = true; + break; + case ' ': + exists = true; + break; + default: + // invalid mode + goto cleanup; + } + } + if (!read && !write && !execute && !exists) { + // invalid mode + goto cleanup; + } + + if (!read && !write && !execute) { + imode = F_OK; + } else { + if (read) { + imode |= R_OK; + } + if (write) { + imode |= W_OK; + } + if (execute) { + imode |= X_OK; + } + } + ret = access(name, imode); + +cleanup: + if (newName) { + free(newName); + } + return ret; +} +#endif + } // namespace Fortran::runtime } // extern "C" diff --git a/flang/unittests/Runtime/AccessTest.cpp b/flang/unittests/Runtime/AccessTest.cpp new file mode 100644 index 000000000000..5c8a634192d9 --- /dev/null +++ b/flang/unittests/Runtime/AccessTest.cpp @@ -0,0 +1,390 @@ +//===-- flang/unittests/Runtime/AccessTest.cpp ----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// TODO: ACCESS is not yet implemented on Windows +#ifndef _WIN32 + +#include "CrashHandlerFixture.h" +#include "gtest/gtest.h" +#include "flang/Runtime/extensions.h" + +#include +#include +#include +#include +#include + +namespace { + +struct AccessTests : public CrashHandlerFixture {}; + +struct AccessType { + bool read{false}; + bool write{false}; + bool execute{false}; + bool exists{false}; +}; + +} // namespace + +static std::string addPIDSuffix(const char *name) { + std::stringstream ss; + ss << name; + ss << '.'; + + ss << getpid(); + + return ss.str(); +} + +static std::filesystem::path createTemporaryFile( + const char *name, const AccessType &accessType) { + std::filesystem::path path{ + std::filesystem::temp_directory_path() / addPIDSuffix(name)}; + + // O_CREAT | O_EXCL enforces that this file is newly created by this call. + // This feels risky. If we don't have permission to create files in the + // temporary directory or if the files already exist, the test will fail. + // But we can't use std::tmpfile() because we need a path to the file and + // to control the filesystem permissions + mode_t mode{0}; + if (accessType.read) { + mode |= S_IRUSR; + } + if (accessType.write) { + mode |= S_IWUSR; + } + if (accessType.execute) { + mode |= S_IXUSR; + } + + int file = open(path.c_str(), O_CREAT | O_EXCL, mode); + if (file == -1) { + return {}; + } + + close(file); + + return path; +} + +static std::int64_t callAccess( + const std::filesystem::path &path, const AccessType &accessType) { + const char *cpath{path.c_str()}; + std::int64_t pathlen = std::strlen(cpath); + + std::string mode; + if (accessType.read) { + mode += 'r'; + } + if (accessType.write) { + mode += 'w'; + } + if (accessType.execute) { + mode += 'x'; + } + if (accessType.exists) { + mode += ' '; + } + + const char *cmode = mode.c_str(); + std::int64_t modelen = std::strlen(cmode); + + return FORTRAN_PROCEDURE_NAME(access)(cpath, pathlen, cmode, modelen); +} + +TEST(AccessTests, TestExists) { + AccessType accessType; + accessType.exists = true; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_EQ(res, 0); +} + +TEST(AccessTests, TestNotExists) { + std::filesystem::path nonExistant{addPIDSuffix(__func__)}; + ASSERT_FALSE(std::filesystem::exists(nonExistant)); + + AccessType accessType; + accessType.exists = true; + std::int64_t res = callAccess(nonExistant, accessType); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestRead) { + AccessType accessType; + accessType.read = true; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_EQ(res, 0); +} + +TEST(AccessTests, TestNotRead) { + AccessType accessType; + accessType.read = false; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.read = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestWrite) { + AccessType accessType; + accessType.write = true; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_EQ(res, 0); +} + +TEST(AccessTests, TestNotWrite) { + AccessType accessType; + accessType.write = false; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.write = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestReadWrite) { + AccessType accessType; + accessType.read = true; + accessType.write = true; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_EQ(res, 0); +} + +TEST(AccessTests, TestNotReadWrite0) { + AccessType accessType; + accessType.read = false; + accessType.write = false; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.read = true; + accessType.write = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestNotReadWrite1) { + AccessType accessType; + accessType.read = true; + accessType.write = false; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.read = true; + accessType.write = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestNotReadWrite2) { + AccessType accessType; + accessType.read = false; + accessType.write = true; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.read = true; + accessType.write = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestExecute) { + AccessType accessType; + accessType.execute = true; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_EQ(res, 0); +} + +TEST(AccessTests, TestNotExecute) { + AccessType accessType; + accessType.execute = false; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.execute = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestRWX) { + AccessType accessType; + accessType.read = true; + accessType.write = true; + accessType.execute = true; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_EQ(res, 0); +} + +TEST(AccessTests, TestNotRWX0) { + AccessType accessType; + accessType.read = false; + accessType.write = false; + accessType.execute = false; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.read = true; + accessType.write = true; + accessType.execute = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestNotRWX1) { + AccessType accessType; + accessType.read = true; + accessType.write = false; + accessType.execute = false; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.read = true; + accessType.write = true; + accessType.execute = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestNotRWX2) { + AccessType accessType; + accessType.read = true; + accessType.write = true; + accessType.execute = false; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.read = true; + accessType.write = true; + accessType.execute = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestNotRWX3) { + AccessType accessType; + accessType.read = true; + accessType.write = false; + accessType.execute = true; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.read = true; + accessType.write = true; + accessType.execute = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +TEST(AccessTests, TestNotRWX4) { + AccessType accessType; + accessType.read = false; + accessType.write = true; + accessType.execute = true; + + std::filesystem::path path = createTemporaryFile(__func__, accessType); + ASSERT_FALSE(path.empty()); + + accessType.read = true; + accessType.write = true; + accessType.execute = true; + std::int64_t res = callAccess(path, accessType); + + std::filesystem::remove(path); + + ASSERT_NE(res, 0); +} + +#endif // !_WIN32 diff --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt index 23f02aa75124..f7caacad3a59 100644 --- a/flang/unittests/Runtime/CMakeLists.txt +++ b/flang/unittests/Runtime/CMakeLists.txt @@ -1,4 +1,5 @@ add_flang_unittest(FlangRuntimeTests + AccessTest.cpp Allocatable.cpp ArrayConstructor.cpp BufferTest.cpp -- GitLab From 7e7468c9ed4e29fe8327525923fd8ab0169b1c07 Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Fri, 12 Apr 2024 13:50:39 +0100 Subject: [PATCH 057/464] Revert "[flang][runtime] Add ACCESS library procedure" (#88507) Reverts llvm/llvm-project#88395 This broke the powerpc buildbot. That build doesn't support using `std::filesystem` in flang unit tests. --- flang/docs/Intrinsics.md | 8 - flang/include/flang/Runtime/extensions.h | 7 - flang/runtime/extensions.cpp | 73 ----- flang/unittests/Runtime/AccessTest.cpp | 390 ----------------------- flang/unittests/Runtime/CMakeLists.txt | 1 - 5 files changed, 479 deletions(-) delete mode 100644 flang/unittests/Runtime/AccessTest.cpp diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md index 848619cb65d9..ccb93e104dab 100644 --- a/flang/docs/Intrinsics.md +++ b/flang/docs/Intrinsics.md @@ -657,14 +657,6 @@ CALL CO_REDUCE CALL CO_SUM ``` -### Inquiry Functions -ACCESS (GNU extension) is not supported on Windows. Otherwise: -``` -CHARACTER(LEN=*) :: path = 'path/to/file' -IF (ACCESS(path, 'rwx')) & - ... -``` - ## Non-standard intrinsics ### PGI ``` diff --git a/flang/include/flang/Runtime/extensions.h b/flang/include/flang/Runtime/extensions.h index fef651f3b2ee..7d0952206fc1 100644 --- a/flang/include/flang/Runtime/extensions.h +++ b/flang/include/flang/Runtime/extensions.h @@ -44,12 +44,5 @@ std::int64_t RTNAME(Signal)(std::int64_t number, void (*handler)(int)); // GNU extension subroutine SLEEP(SECONDS) void RTNAME(Sleep)(std::int64_t seconds); -// GNU extension function ACCESS(NAME, MODE) -// TODO: not supported on Windows -#ifndef _WIN32 -std::int64_t FORTRAN_PROCEDURE_NAME(access)(const char *name, - std::int64_t nameLength, const char *mode, std::int64_t modeLength); -#endif - } // extern "C" #endif // FORTRAN_RUNTIME_EXTENSIONS_H_ diff --git a/flang/runtime/extensions.cpp b/flang/runtime/extensions.cpp index 12498b502ae1..3ac98000335d 100644 --- a/flang/runtime/extensions.cpp +++ b/flang/runtime/extensions.cpp @@ -17,7 +17,6 @@ #include "flang/Runtime/entry-names.h" #include "flang/Runtime/io-api.h" #include -#include #include #include #include @@ -139,77 +138,5 @@ void RTNAME(Sleep)(std::int64_t seconds) { std::this_thread::sleep_for(std::chrono::seconds(seconds)); } -// TODO: not supported on Windows -#ifndef _WIN32 -std::int64_t FORTRAN_PROCEDURE_NAME(access)(const char *name, - std::int64_t nameLength, const char *mode, std::int64_t modeLength) { - std::int64_t ret{-1}; - if (nameLength <= 0 || modeLength <= 0 || !name || !mode) { - return ret; - } - - // ensure name is null terminated - char *newName{nullptr}; - if (name[nameLength - 1] != '\0') { - newName = static_cast(std::malloc(nameLength + 1)); - std::memcpy(newName, name, nameLength); - newName[nameLength] = '\0'; - name = newName; - } - - // calculate mode - bool read{false}; - bool write{false}; - bool execute{false}; - bool exists{false}; - int imode{0}; - - for (std::int64_t i = 0; i < modeLength; ++i) { - switch (mode[i]) { - case 'r': - read = true; - break; - case 'w': - write = true; - break; - case 'x': - execute = true; - break; - case ' ': - exists = true; - break; - default: - // invalid mode - goto cleanup; - } - } - if (!read && !write && !execute && !exists) { - // invalid mode - goto cleanup; - } - - if (!read && !write && !execute) { - imode = F_OK; - } else { - if (read) { - imode |= R_OK; - } - if (write) { - imode |= W_OK; - } - if (execute) { - imode |= X_OK; - } - } - ret = access(name, imode); - -cleanup: - if (newName) { - free(newName); - } - return ret; -} -#endif - } // namespace Fortran::runtime } // extern "C" diff --git a/flang/unittests/Runtime/AccessTest.cpp b/flang/unittests/Runtime/AccessTest.cpp deleted file mode 100644 index 5c8a634192d9..000000000000 --- a/flang/unittests/Runtime/AccessTest.cpp +++ /dev/null @@ -1,390 +0,0 @@ -//===-- flang/unittests/Runtime/AccessTest.cpp ----------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -// TODO: ACCESS is not yet implemented on Windows -#ifndef _WIN32 - -#include "CrashHandlerFixture.h" -#include "gtest/gtest.h" -#include "flang/Runtime/extensions.h" - -#include -#include -#include -#include -#include - -namespace { - -struct AccessTests : public CrashHandlerFixture {}; - -struct AccessType { - bool read{false}; - bool write{false}; - bool execute{false}; - bool exists{false}; -}; - -} // namespace - -static std::string addPIDSuffix(const char *name) { - std::stringstream ss; - ss << name; - ss << '.'; - - ss << getpid(); - - return ss.str(); -} - -static std::filesystem::path createTemporaryFile( - const char *name, const AccessType &accessType) { - std::filesystem::path path{ - std::filesystem::temp_directory_path() / addPIDSuffix(name)}; - - // O_CREAT | O_EXCL enforces that this file is newly created by this call. - // This feels risky. If we don't have permission to create files in the - // temporary directory or if the files already exist, the test will fail. - // But we can't use std::tmpfile() because we need a path to the file and - // to control the filesystem permissions - mode_t mode{0}; - if (accessType.read) { - mode |= S_IRUSR; - } - if (accessType.write) { - mode |= S_IWUSR; - } - if (accessType.execute) { - mode |= S_IXUSR; - } - - int file = open(path.c_str(), O_CREAT | O_EXCL, mode); - if (file == -1) { - return {}; - } - - close(file); - - return path; -} - -static std::int64_t callAccess( - const std::filesystem::path &path, const AccessType &accessType) { - const char *cpath{path.c_str()}; - std::int64_t pathlen = std::strlen(cpath); - - std::string mode; - if (accessType.read) { - mode += 'r'; - } - if (accessType.write) { - mode += 'w'; - } - if (accessType.execute) { - mode += 'x'; - } - if (accessType.exists) { - mode += ' '; - } - - const char *cmode = mode.c_str(); - std::int64_t modelen = std::strlen(cmode); - - return FORTRAN_PROCEDURE_NAME(access)(cpath, pathlen, cmode, modelen); -} - -TEST(AccessTests, TestExists) { - AccessType accessType; - accessType.exists = true; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_EQ(res, 0); -} - -TEST(AccessTests, TestNotExists) { - std::filesystem::path nonExistant{addPIDSuffix(__func__)}; - ASSERT_FALSE(std::filesystem::exists(nonExistant)); - - AccessType accessType; - accessType.exists = true; - std::int64_t res = callAccess(nonExistant, accessType); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestRead) { - AccessType accessType; - accessType.read = true; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_EQ(res, 0); -} - -TEST(AccessTests, TestNotRead) { - AccessType accessType; - accessType.read = false; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.read = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestWrite) { - AccessType accessType; - accessType.write = true; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_EQ(res, 0); -} - -TEST(AccessTests, TestNotWrite) { - AccessType accessType; - accessType.write = false; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.write = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestReadWrite) { - AccessType accessType; - accessType.read = true; - accessType.write = true; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_EQ(res, 0); -} - -TEST(AccessTests, TestNotReadWrite0) { - AccessType accessType; - accessType.read = false; - accessType.write = false; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.read = true; - accessType.write = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestNotReadWrite1) { - AccessType accessType; - accessType.read = true; - accessType.write = false; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.read = true; - accessType.write = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestNotReadWrite2) { - AccessType accessType; - accessType.read = false; - accessType.write = true; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.read = true; - accessType.write = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestExecute) { - AccessType accessType; - accessType.execute = true; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_EQ(res, 0); -} - -TEST(AccessTests, TestNotExecute) { - AccessType accessType; - accessType.execute = false; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.execute = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestRWX) { - AccessType accessType; - accessType.read = true; - accessType.write = true; - accessType.execute = true; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_EQ(res, 0); -} - -TEST(AccessTests, TestNotRWX0) { - AccessType accessType; - accessType.read = false; - accessType.write = false; - accessType.execute = false; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.read = true; - accessType.write = true; - accessType.execute = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestNotRWX1) { - AccessType accessType; - accessType.read = true; - accessType.write = false; - accessType.execute = false; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.read = true; - accessType.write = true; - accessType.execute = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestNotRWX2) { - AccessType accessType; - accessType.read = true; - accessType.write = true; - accessType.execute = false; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.read = true; - accessType.write = true; - accessType.execute = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestNotRWX3) { - AccessType accessType; - accessType.read = true; - accessType.write = false; - accessType.execute = true; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.read = true; - accessType.write = true; - accessType.execute = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -TEST(AccessTests, TestNotRWX4) { - AccessType accessType; - accessType.read = false; - accessType.write = true; - accessType.execute = true; - - std::filesystem::path path = createTemporaryFile(__func__, accessType); - ASSERT_FALSE(path.empty()); - - accessType.read = true; - accessType.write = true; - accessType.execute = true; - std::int64_t res = callAccess(path, accessType); - - std::filesystem::remove(path); - - ASSERT_NE(res, 0); -} - -#endif // !_WIN32 diff --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt index f7caacad3a59..23f02aa75124 100644 --- a/flang/unittests/Runtime/CMakeLists.txt +++ b/flang/unittests/Runtime/CMakeLists.txt @@ -1,5 +1,4 @@ add_flang_unittest(FlangRuntimeTests - AccessTest.cpp Allocatable.cpp ArrayConstructor.cpp BufferTest.cpp -- GitLab From ea3d0db130b9a6c4678c11dd8bc48e5630624b62 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Fri, 12 Apr 2024 13:51:41 +0100 Subject: [PATCH 058/464] [VectorCombine] foldShuffleOfCastops - ensure we can scale shuffle masks between bitcasted vector types Don't just assert that the src/dst vector element counts are multiples of one another - in general IR this can actually happen. Reported by @mikaelholmen --- llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 6 ++++++ .../VectorCombine/X86/shuffle-of-casts.ll | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index 44cba60013af..653e0ff7a3ec 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -1483,6 +1483,12 @@ bool VectorCombine::foldShuffleOfCastops(Instruction &I) { assert((NumDstElts == NumSrcElts || Opcode == Instruction::BitCast) && "Only bitcasts expected to alter src/dst element counts"); + // Check for bitcasting of unscalable vector types. + // e.g. <32 x i40> -> <40 x i32> + if (NumDstElts != NumSrcElts && (NumSrcElts % NumDstElts) != 0 && + (NumDstElts % NumSrcElts) != 0) + return false; + SmallVector NewMask; if (NumSrcElts >= NumDstElts) { // The bitcast is from wide to narrow/equal elements. The shuffle mask can diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-casts.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-casts.ll index 4f8cfea146ea..7d9f7e390b9c 100644 --- a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-casts.ll +++ b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-casts.ll @@ -239,6 +239,21 @@ define <16 x i16> @revpair_bitcast_v4i32_v16i16(<4 x i32> %a0, <4 x i32> %a1) { ret <16 x i16> %r } +; negative - bitcasts (unscalable element counts) + +define <4 x i32> @shuffle_bitcast_v32i40_v4i32(<32 x i40> %a0, <32 x i40> %a1) { +; CHECK-LABEL: @shuffle_bitcast_v32i40_v4i32( +; CHECK-NEXT: [[X0:%.*]] = bitcast <32 x i40> [[A0:%.*]] to <40 x i32> +; CHECK-NEXT: [[X1:%.*]] = bitcast <32 x i40> [[A1:%.*]] to <40 x i32> +; CHECK-NEXT: [[R:%.*]] = shufflevector <40 x i32> [[X0]], <40 x i32> [[X1]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[R]] +; + %x0 = bitcast <32 x i40> %a0 to <40 x i32> + %x1 = bitcast <32 x i40> %a1 to <40 x i32> + %r = shufflevector <40 x i32> %x0, <40 x i32> %x1, <4 x i32> + ret <4 x i32> %r +} + ; negative - src type mismatch define <8 x i32> @concat_sext_v4i8_v4i16_v8i32(<4 x i8> %a0, <4 x i16> %a1) { -- GitLab From 3fa830804e1b90d38d0a62084b5b65e70c83c345 Mon Sep 17 00:00:00 2001 From: Brandon Wu Date: Fri, 12 Apr 2024 21:11:45 +0800 Subject: [PATCH 059/464] Revert "[RISCV] RISCV vector calling convention (2/2) (#79096)" (#88511) This reverts commit 29e8bfc13c6078ed07e6474e8c9634c42aa2f6f4. This patch didn't handle vector return type correctly. --- .../Target/RISCV/GISel/RISCVCallLowering.cpp | 55 +++--- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 180 ++++-------------- llvm/lib/Target/RISCV/RISCVISelLowering.h | 56 +----- llvm/test/CodeGen/RISCV/rvv/calling-conv.ll | 87 --------- .../RISCV/rvv/vector-deinterleave-load.ll | 6 +- .../CodeGen/RISCV/rvv/vector-deinterleave.ll | 19 +- 6 files changed, 83 insertions(+), 320 deletions(-) diff --git a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp index 8af4bc658409..45e19cdea300 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp @@ -34,15 +34,14 @@ private: // Whether this is assigning args for a return. bool IsRet; - RVVArgDispatcher &RVVDispatcher; + // true if assignArg has been called for a mask argument, false otherwise. + bool AssignedFirstMaskArg = false; public: RISCVOutgoingValueAssigner( - RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet, - RVVArgDispatcher &RVVDispatcher) + RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet) : CallLowering::OutgoingValueAssigner(nullptr), - RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet), - RVVDispatcher(RVVDispatcher) {} + RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {} bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, @@ -52,9 +51,16 @@ public: const DataLayout &DL = MF.getDataLayout(); const RISCVSubtarget &Subtarget = MF.getSubtarget(); + std::optional FirstMaskArgument; + if (Subtarget.hasVInstructions() && !AssignedFirstMaskArg && + ValVT.isVector() && ValVT.getVectorElementType() == MVT::i1) { + FirstMaskArgument = ValNo; + AssignedFirstMaskArg = true; + } + if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT, LocInfo, Flags, State, Info.IsFixed, IsRet, Info.Ty, - *Subtarget.getTargetLowering(), RVVDispatcher)) + *Subtarget.getTargetLowering(), FirstMaskArgument)) return true; StackSize = State.getStackSize(); @@ -175,15 +181,14 @@ private: // Whether this is assigning args from a return. bool IsRet; - RVVArgDispatcher &RVVDispatcher; + // true if assignArg has been called for a mask argument, false otherwise. + bool AssignedFirstMaskArg = false; public: RISCVIncomingValueAssigner( - RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet, - RVVArgDispatcher &RVVDispatcher) + RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet) : CallLowering::IncomingValueAssigner(nullptr), - RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet), - RVVDispatcher(RVVDispatcher) {} + RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {} bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, @@ -196,9 +201,16 @@ public: if (LocVT.isScalableVector()) MF.getInfo()->setIsVectorCall(); + std::optional FirstMaskArgument; + if (Subtarget.hasVInstructions() && !AssignedFirstMaskArg && + ValVT.isVector() && ValVT.getVectorElementType() == MVT::i1) { + FirstMaskArgument = ValNo; + AssignedFirstMaskArg = true; + } + if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT, LocInfo, Flags, State, /*IsFixed=*/true, IsRet, Info.Ty, - *Subtarget.getTargetLowering(), RVVDispatcher)) + *Subtarget.getTargetLowering(), FirstMaskArgument)) return true; StackSize = State.getStackSize(); @@ -408,11 +420,9 @@ bool RISCVCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, SmallVector SplitRetInfos; splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC); - RVVArgDispatcher Dispatcher{&MF, getTLI(), - F.getReturnType()}; RISCVOutgoingValueAssigner Assigner( CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV, - /*IsRet=*/true, Dispatcher); + /*IsRet=*/true); RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret); return determineAndHandleAssignments(Handler, Assigner, SplitRetInfos, MIRBuilder, CC, F.isVarArg()); @@ -521,7 +531,6 @@ bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, CallingConv::ID CC = F.getCallingConv(); SmallVector SplitArgInfos; - SmallVector TypeList; unsigned Index = 0; for (auto &Arg : F.args()) { // Construct the ArgInfo object from destination register and argument type. @@ -533,15 +542,12 @@ bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, // correspondingly and appended to SplitArgInfos. splitToValueTypes(AInfo, SplitArgInfos, DL, CC); - TypeList.push_back(Arg.getType()); - ++Index; } - RVVArgDispatcher Dispatcher{&MF, getTLI(), TypeList}; RISCVIncomingValueAssigner Assigner( CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV, - /*IsRet=*/false, Dispatcher); + /*IsRet=*/false); RISCVFormalArgHandler Handler(MIRBuilder, MF.getRegInfo()); SmallVector ArgLocs; @@ -579,13 +585,11 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, SmallVector SplitArgInfos; SmallVector Outs; - SmallVector TypeList; for (auto &AInfo : Info.OrigArgs) { // Handle any required unmerging of split value types from a given VReg into // physical registers. ArgInfo objects are constructed correspondingly and // appended to SplitArgInfos. splitToValueTypes(AInfo, SplitArgInfos, DL, CC); - TypeList.push_back(AInfo.Ty); } // TODO: Support tail calls. @@ -603,10 +607,9 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); - RVVArgDispatcher ArgDispatcher{&MF, getTLI(), TypeList}; RISCVOutgoingValueAssigner ArgAssigner( CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV, - /*IsRet=*/false, ArgDispatcher); + /*IsRet=*/false); RISCVOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), Call); if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos, MIRBuilder, CC, Info.IsVarArg)) @@ -634,11 +637,9 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, SmallVector SplitRetInfos; splitToValueTypes(Info.OrigRet, SplitRetInfos, DL, CC); - RVVArgDispatcher RetDispatcher{&MF, getTLI(), - F.getReturnType()}; RISCVIncomingValueAssigner RetAssigner( CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV, - /*IsRet=*/true, RetDispatcher); + /*IsRet=*/true); RISCVCallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Call); if (!determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos, MIRBuilder, CC, Info.IsVarArg)) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 3e7bc8c2367d..5a572002091f 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -22,7 +22,6 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/VectorUtils.h" -#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -18079,12 +18078,33 @@ static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1, return false; } +static unsigned allocateRVVReg(MVT ValVT, unsigned ValNo, + std::optional FirstMaskArgument, + CCState &State, const RISCVTargetLowering &TLI) { + const TargetRegisterClass *RC = TLI.getRegClassFor(ValVT); + if (RC == &RISCV::VRRegClass) { + // Assign the first mask argument to V0. + // This is an interim calling convention and it may be changed in the + // future. + if (FirstMaskArgument && ValNo == *FirstMaskArgument) + return State.AllocateReg(RISCV::V0); + return State.AllocateReg(ArgVRs); + } + if (RC == &RISCV::VRM2RegClass) + return State.AllocateReg(ArgVRM2s); + if (RC == &RISCV::VRM4RegClass) + return State.AllocateReg(ArgVRM4s); + if (RC == &RISCV::VRM8RegClass) + return State.AllocateReg(ArgVRM8s); + llvm_unreachable("Unhandled register class for ValueType"); +} + // Implements the RISC-V calling convention. Returns true upon failure. bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - RVVArgDispatcher &RVVDispatcher) { + std::optional FirstMaskArgument) { unsigned XLen = DL.getLargestLegalIntTypeSizeInBits(); assert(XLen == 32 || XLen == 64); MVT XLenVT = XLen == 32 ? MVT::i32 : MVT::i64; @@ -18253,7 +18273,7 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, else if (ValVT == MVT::f64 && !UseGPRForF64) Reg = State.AllocateReg(ArgFPR64s); else if (ValVT.isVector()) { - Reg = RVVDispatcher.getNextPhysReg(); + Reg = allocateRVVReg(ValVT, ValNo, FirstMaskArgument, State, TLI); if (!Reg) { // For return values, the vector must be passed fully via registers or // via the stack. @@ -18339,13 +18359,9 @@ void RISCVTargetLowering::analyzeInputArgs( unsigned NumArgs = Ins.size(); FunctionType *FType = MF.getFunction().getFunctionType(); - SmallVector TypeList; - if (IsRet) - TypeList.push_back(MF.getFunction().getReturnType()); - else - for (const Argument &Arg : MF.getFunction().args()) - TypeList.push_back(Arg.getType()); - RVVArgDispatcher Dispatcher{&MF, this, TypeList}; + std::optional FirstMaskArgument; + if (Subtarget.hasVInstructions()) + FirstMaskArgument = preAssignMask(Ins); for (unsigned i = 0; i != NumArgs; ++i) { MVT ArgVT = Ins[i].VT; @@ -18360,7 +18376,7 @@ void RISCVTargetLowering::analyzeInputArgs( RISCVABI::ABI ABI = MF.getSubtarget().getTargetABI(); if (Fn(MF.getDataLayout(), ABI, i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo, /*IsFixed=*/true, IsRet, ArgTy, *this, - Dispatcher)) { + FirstMaskArgument)) { LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type " << ArgVT << '\n'); llvm_unreachable(nullptr); @@ -18374,13 +18390,9 @@ void RISCVTargetLowering::analyzeOutputArgs( CallLoweringInfo *CLI, RISCVCCAssignFn Fn) const { unsigned NumArgs = Outs.size(); - SmallVector TypeList; - if (IsRet) - TypeList.push_back(MF.getFunction().getReturnType()); - else if (CLI) - for (const TargetLowering::ArgListEntry &Arg : CLI->getArgs()) - TypeList.push_back(Arg.Ty); - RVVArgDispatcher Dispatcher{&MF, this, TypeList}; + std::optional FirstMaskArgument; + if (Subtarget.hasVInstructions()) + FirstMaskArgument = preAssignMask(Outs); for (unsigned i = 0; i != NumArgs; i++) { MVT ArgVT = Outs[i].VT; @@ -18390,7 +18402,7 @@ void RISCVTargetLowering::analyzeOutputArgs( RISCVABI::ABI ABI = MF.getSubtarget().getTargetABI(); if (Fn(MF.getDataLayout(), ABI, i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo, Outs[i].IsFixed, IsRet, OrigTy, *this, - Dispatcher)) { + FirstMaskArgument)) { LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type " << ArgVT << "\n"); llvm_unreachable(nullptr); @@ -18571,7 +18583,7 @@ bool RISCV::CC_RISCV_FastCC(const DataLayout &DL, RISCVABI::ABI ABI, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - RVVArgDispatcher &RVVDispatcher) { + std::optional FirstMaskArgument) { if (LocVT == MVT::i32 || LocVT == MVT::i64) { if (unsigned Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) { State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); @@ -18649,14 +18661,13 @@ bool RISCV::CC_RISCV_FastCC(const DataLayout &DL, RISCVABI::ABI ABI, } if (LocVT.isVector()) { - MCPhysReg AllocatedVReg = RVVDispatcher.getNextPhysReg(); - if (AllocatedVReg) { + if (unsigned Reg = + allocateRVVReg(ValVT, ValNo, FirstMaskArgument, State, TLI)) { // Fixed-length vectors are located in the corresponding scalable-vector // container types. if (ValVT.isFixedLengthVector()) LocVT = TLI.getContainerForFixedLengthVector(LocVT); - State.addLoc( - CCValAssign::getReg(ValNo, ValVT, AllocatedVReg, LocVT, LocInfo)); + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); } else { // Try and pass the address via a "fast" GPR. if (unsigned GPRReg = State.AllocateReg(getFastCCArgGPRs(ABI))) { @@ -19284,15 +19295,17 @@ bool RISCVTargetLowering::CanLowerReturn( SmallVector RVLocs; CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); - RVVArgDispatcher Dispatcher{&MF, this, MF.getFunction().getReturnType()}; + std::optional FirstMaskArgument; + if (Subtarget.hasVInstructions()) + FirstMaskArgument = preAssignMask(Outs); for (unsigned i = 0, e = Outs.size(); i != e; ++i) { MVT VT = Outs[i].VT; ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; RISCVABI::ABI ABI = MF.getSubtarget().getTargetABI(); if (RISCV::CC_RISCV(MF.getDataLayout(), ABI, i, VT, VT, CCValAssign::Full, - ArgFlags, CCInfo, /*IsFixed=*/true, /*IsRet=*/true, - nullptr, *this, Dispatcher)) + ArgFlags, CCInfo, /*IsFixed=*/true, /*IsRet=*/true, nullptr, + *this, FirstMaskArgument)) return false; } return true; @@ -21089,119 +21102,6 @@ unsigned RISCVTargetLowering::getMinimumJumpTableEntries() const { return Subtarget.getMinimumJumpTableEntries(); } -void RVVArgDispatcher::constructArgInfos(ArrayRef TypeList) { - const DataLayout &DL = MF->getDataLayout(); - const Function &F = MF->getFunction(); - LLVMContext &Context = F.getContext(); - - bool FirstVMaskAssigned = false; - for (Type *Ty : TypeList) { - StructType *STy = dyn_cast(Ty); - if (STy && STy->containsHomogeneousScalableVectorTypes()) { - Type *ElemTy = STy->getTypeAtIndex(0U); - EVT VT = TLI->getValueType(DL, ElemTy); - MVT RegisterVT = - TLI->getRegisterTypeForCallingConv(Context, F.getCallingConv(), VT); - - RVVArgInfos.push_back({STy->getNumElements(), RegisterVT, false}); - } else { - SmallVector ValueVTs; - ComputeValueVTs(*TLI, DL, Ty, ValueVTs); - - for (unsigned Value = 0, NumValues = ValueVTs.size(); Value != NumValues; - ++Value) { - EVT VT = ValueVTs[Value]; - MVT RegisterVT = - TLI->getRegisterTypeForCallingConv(Context, F.getCallingConv(), VT); - unsigned NumRegs = - TLI->getNumRegistersForCallingConv(Context, F.getCallingConv(), VT); - - // Skip non-RVV register type - if (!RegisterVT.isVector()) - continue; - - if (RegisterVT.isFixedLengthVector()) - RegisterVT = TLI->getContainerForFixedLengthVector(RegisterVT); - - if (!FirstVMaskAssigned && - RegisterVT.getVectorElementType() == MVT::i1) { - RVVArgInfos.push_back({1, RegisterVT, true}); - FirstVMaskAssigned = true; - --NumRegs; - } - - RVVArgInfos.insert(RVVArgInfos.end(), NumRegs, {1, RegisterVT, false}); - } - } - } -} - -void RVVArgDispatcher::allocatePhysReg(unsigned NF, unsigned LMul, - unsigned StartReg) { - assert((StartReg % LMul) == 0 && - "Start register number should be multiple of lmul"); - const MCPhysReg *VRArrays; - switch (LMul) { - default: - report_fatal_error("Invalid lmul"); - case 1: - VRArrays = ArgVRs; - break; - case 2: - VRArrays = ArgVRM2s; - break; - case 4: - VRArrays = ArgVRM4s; - break; - case 8: - VRArrays = ArgVRM8s; - break; - } - - for (unsigned i = 0; i < NF; ++i) - if (StartReg) - AllocatedPhysRegs.push_back(VRArrays[(StartReg - 8) / LMul + i]); - else - AllocatedPhysRegs.push_back(MCPhysReg()); -} - -/// This function determines if each RVV argument is passed by register, if the -/// argument can be assigned to a VR, then give it a specific register. -/// Otherwise, assign the argument to 0 which is a invalid MCPhysReg. -void RVVArgDispatcher::compute() { - uint32_t AssignedMap = 0; - auto allocate = [&](const RVVArgInfo &ArgInfo) { - // Allocate first vector mask argument to V0. - if (ArgInfo.FirstVMask) { - AllocatedPhysRegs.push_back(RISCV::V0); - return; - } - - unsigned RegsNeeded = divideCeil( - ArgInfo.VT.getSizeInBits().getKnownMinValue(), RISCV::RVVBitsPerBlock); - unsigned TotalRegsNeeded = ArgInfo.NF * RegsNeeded; - for (unsigned StartReg = 0; StartReg + TotalRegsNeeded <= NumArgVRs; - StartReg += RegsNeeded) { - uint32_t Map = ((1 << TotalRegsNeeded) - 1) << StartReg; - if ((AssignedMap & Map) == 0) { - allocatePhysReg(ArgInfo.NF, RegsNeeded, StartReg + 8); - AssignedMap |= Map; - return; - } - } - - allocatePhysReg(ArgInfo.NF, RegsNeeded, 0); - }; - - for (unsigned i = 0; i < RVVArgInfos.size(); ++i) - allocate(RVVArgInfos[i]); -} - -MCPhysReg RVVArgDispatcher::getNextPhysReg() { - assert(CurIdx < AllocatedPhysRegs.size() && "Index out of range"); - return AllocatedPhysRegs[CurIdx++]; -} - namespace llvm::RISCVVIntrinsicsTable { #define GET_RISCVVIntrinsicsTable_IMPL diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index c28552354bf4..ace5b3fd2b95 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -24,7 +24,6 @@ namespace llvm { class InstructionCost; class RISCVSubtarget; struct RISCVRegisterInfo; -class RVVArgDispatcher; namespace RISCVISD { // clang-format off @@ -876,7 +875,7 @@ public: ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - RVVArgDispatcher &RVVDispatcher); + std::optional FirstMaskArgument); private: void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, @@ -1016,68 +1015,19 @@ private: unsigned getMinimumJumpTableEntries() const override; }; -/// As per the spec, the rules for passing vector arguments are as follows: -/// -/// 1. For the first vector mask argument, use v0 to pass it. -/// 2. For vector data arguments or rest vector mask arguments, starting from -/// the v8 register, if a vector register group between v8-v23 that has not been -/// allocated can be found and the first register number is a multiple of LMUL, -/// then allocate this vector register group to the argument and mark these -/// registers as allocated. Otherwise, pass it by reference and are replaced in -/// the argument list with the address. -/// 3. For tuple vector data arguments, starting from the v8 register, if -/// NFIELDS consecutive vector register groups between v8-v23 that have not been -/// allocated can be found and the first register number is a multiple of LMUL, -/// then allocate these vector register groups to the argument and mark these -/// registers as allocated. Otherwise, pass it by reference and are replaced in -/// the argument list with the address. -class RVVArgDispatcher { -public: - static constexpr unsigned NumArgVRs = 16; - - struct RVVArgInfo { - unsigned NF; - MVT VT; - bool FirstVMask = false; - }; - - RVVArgDispatcher(const MachineFunction *MF, const RISCVTargetLowering *TLI, - ArrayRef TypeList) - : MF(MF), TLI(TLI) { - constructArgInfos(TypeList); - compute(); - } - - MCPhysReg getNextPhysReg(); - -private: - SmallVector RVVArgInfos; - SmallVector AllocatedPhysRegs; - - const MachineFunction *MF = nullptr; - const RISCVTargetLowering *TLI = nullptr; - - unsigned CurIdx = 0; - - void constructArgInfos(ArrayRef TypeList); - void compute(); - void allocatePhysReg(unsigned NF = 1, unsigned LMul = 1, - unsigned StartReg = 0); -}; - namespace RISCV { bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - RVVArgDispatcher &RVVDispatcher); + std::optional FirstMaskArgument); bool CC_RISCV_FastCC(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - RVVArgDispatcher &RVVDispatcher); + std::optional FirstMaskArgument); bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, diff --git a/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll b/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll index 90edb994ce82..78e8700a9fef 100644 --- a/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll +++ b/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll @@ -162,90 +162,3 @@ define void @caller_tuple_argument({, } %x) } declare void @callee_tuple_argument({, }) - -; %0 -> v8 -; %1 -> v9 -define @case1( %0, %1) { -; CHECK-LABEL: case1: -; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vadd.vv v8, v8, v9 -; CHECK-NEXT: ret - %a = add %0, %1 - ret %a -} - -; %0 -> v8 -; %1 -> v10-v11 -; %2 -> v9 -define @case2_1( %0, %1, %2) { -; CHECK-LABEL: case2_1: -; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vadd.vv v8, v8, v9 -; CHECK-NEXT: ret - %a = add %0, %2 - ret %a -} -define @case2_2( %0, %1, %2) { -; CHECK-LABEL: case2_2: -; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vadd.vv v8, v10, v10 -; CHECK-NEXT: ret - %a = add %1, %1 - ret %a -} - -; %0 -> v8 -; %1 -> {v10-v11, v12-v13} -; %2 -> v9 -define @case3_1( %0, {, } %1, %2) { -; CHECK-LABEL: case3_1: -; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vadd.vv v8, v8, v9 -; CHECK-NEXT: ret - %add = add %0, %2 - ret %add -} -define @case3_2( %0, {, } %1, %2) { -; CHECK-LABEL: case3_2: -; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vadd.vv v8, v10, v12 -; CHECK-NEXT: ret - %a = extractvalue { , } %1, 0 - %b = extractvalue { , } %1, 1 - %add = add %a, %b - ret %add -} - -; %0 -> v8 -; %1 -> {by-ref, by-ref} -; %2 -> v9 -define @case4_1( %0, {, } %1, %2) { -; CHECK-LABEL: case4_1: -; CHECK: # %bb.0: -; CHECK-NEXT: csrr a1, vlenb -; CHECK-NEXT: slli a1, a1, 3 -; CHECK-NEXT: add a1, a0, a1 -; CHECK-NEXT: vl8re64.v v8, (a1) -; CHECK-NEXT: vl8re64.v v16, (a0) -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vadd.vv v8, v16, v8 -; CHECK-NEXT: ret - %a = extractvalue { , } %1, 0 - %b = extractvalue { , } %1, 1 - %add = add %a, %b - ret %add -} -define @case4_2( %0, {, } %1, %2) { -; CHECK-LABEL: case4_2: -; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vadd.vv v8, v8, v9 -; CHECK-NEXT: ret - %add = add %0, %2 - ret %add -} diff --git a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll index 6a712080fda7..a320aecc6fce 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll @@ -18,10 +18,10 @@ define {, } @vector_deinterleave_load_nxv16i ; CHECK-NEXT: vmerge.vim v14, v10, 1, v0 ; CHECK-NEXT: vmv1r.v v0, v8 ; CHECK-NEXT: vmerge.vim v12, v10, 1, v0 -; CHECK-NEXT: vnsrl.wi v10, v12, 0 -; CHECK-NEXT: vmsne.vi v8, v10, 0 +; CHECK-NEXT: vnsrl.wi v8, v12, 0 +; CHECK-NEXT: vmsne.vi v0, v8, 0 ; CHECK-NEXT: vnsrl.wi v10, v12, 8 -; CHECK-NEXT: vmsne.vi v9, v10, 0 +; CHECK-NEXT: vmsne.vi v8, v10, 0 ; CHECK-NEXT: ret %vec = load , ptr %p %retval = call {, } @llvm.experimental.vector.deinterleave2.nxv32i1( %vec) diff --git a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll index d98597fabcd9..ef4baf34d23f 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll @@ -8,18 +8,18 @@ define {, } @vector_deinterleave_nxv16i1_nxv ; CHECK-LABEL: vector_deinterleave_nxv16i1_nxv32i1: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma -; CHECK-NEXT: vmv.v.i v8, 0 -; CHECK-NEXT: vmerge.vim v12, v8, 1, v0 +; CHECK-NEXT: vmv.v.i v10, 0 +; CHECK-NEXT: vmerge.vim v8, v10, 1, v0 ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: srli a0, a0, 2 ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vslidedown.vx v0, v0, a0 ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma -; CHECK-NEXT: vmerge.vim v14, v8, 1, v0 -; CHECK-NEXT: vnsrl.wi v10, v12, 0 -; CHECK-NEXT: vmsne.vi v8, v10, 0 -; CHECK-NEXT: vnsrl.wi v10, v12, 8 -; CHECK-NEXT: vmsne.vi v9, v10, 0 +; CHECK-NEXT: vmerge.vim v10, v10, 1, v0 +; CHECK-NEXT: vnsrl.wi v12, v8, 0 +; CHECK-NEXT: vmsne.vi v0, v12, 0 +; CHECK-NEXT: vnsrl.wi v12, v8, 8 +; CHECK-NEXT: vmsne.vi v8, v12, 0 ; CHECK-NEXT: ret %retval = call {, } @llvm.experimental.vector.deinterleave2.nxv32i1( %vec) ret {, } %retval @@ -102,13 +102,12 @@ define {, } @vector_deinterleave_nxv64i1_nxv ; CHECK-NEXT: vsetvli a0, zero, e8, m4, ta, ma ; CHECK-NEXT: vnsrl.wi v28, v8, 0 ; CHECK-NEXT: vsetvli a0, zero, e8, m8, ta, ma -; CHECK-NEXT: vmsne.vi v7, v24, 0 +; CHECK-NEXT: vmsne.vi v0, v24, 0 ; CHECK-NEXT: vsetvli a0, zero, e8, m4, ta, ma ; CHECK-NEXT: vnsrl.wi v24, v16, 8 ; CHECK-NEXT: vnsrl.wi v28, v8, 8 ; CHECK-NEXT: vsetvli a0, zero, e8, m8, ta, ma -; CHECK-NEXT: vmsne.vi v9, v24, 0 -; CHECK-NEXT: vmv1r.v v8, v7 +; CHECK-NEXT: vmsne.vi v8, v24, 0 ; CHECK-NEXT: ret %retval = call {, } @llvm.experimental.vector.deinterleave2.nxv128i1( %vec) ret {, } %retval -- GitLab From b4df0da9e8421c8026bd09980b8a6acd7a6ce8c9 Mon Sep 17 00:00:00 2001 From: Shilei Tian Date: Fri, 12 Apr 2024 09:34:46 -0400 Subject: [PATCH 060/464] [AMDGPU] Fix a potential wrong return value indicating whether a pass modifies a function (#88197) When the alloca is too big for vectorization, the function could have already been modified in previous iteration of the `for` loop. --- llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp | 2 +- llvm/test/CodeGen/AMDGPU/half-alloca-promotion.ll | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AMDGPU/half-alloca-promotion.ll diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp index 6f3cdf54dcee..c0846b123d18 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp @@ -336,7 +336,7 @@ bool AMDGPUPromoteAllocaImpl::run(Function &F, bool PromoteToLDS) { if (AllocaCost > VectorizationBudget) { LLVM_DEBUG(dbgs() << " Alloca too big for vectorization: " << *AI << "\n"); - return false; + return Changed; } if (tryPromoteAllocaToVector(*AI)) { diff --git a/llvm/test/CodeGen/AMDGPU/half-alloca-promotion.ll b/llvm/test/CodeGen/AMDGPU/half-alloca-promotion.ll new file mode 100644 index 000000000000..cfec49f3652f --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/half-alloca-promotion.ll @@ -0,0 +1,11 @@ +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes="amdgpu-promote-alloca-to-vector" -o - %s +; We don't really need to check anything here because with expensive check, this +; test case crashes. The correctness of the pass is beyond the scope. + +define fastcc void @foo() { +entry: + %det = alloca [4 x i32], align 16, addrspace(5) + %trkltPosTmpYZ = alloca [2 x float], align 4, addrspace(5) + %trkltCovTmp = alloca [3 x float], align 4, addrspace(5) + ret void +} -- GitLab From 2a5ba4fb895931b7dc86f4304b0e64153a1175d4 Mon Sep 17 00:00:00 2001 From: Xiaoyang Liu Date: Fri, 12 Apr 2024 10:04:21 -0400 Subject: [PATCH 061/464] [libc++] LWG3643: Missing `constexpr` in `std::counted_iterator` (#87901) This pull request implements LWG3643: Missing constexpr in std::counted_iterator. Specifically, one overload of std::counted_operator::operator++ was not marked as constexpr, despite being eligible for it after the introduction of try-block support in constexpr functions in C++20. --- libcxx/docs/Status/Cxx23Issues.csv | 2 +- libcxx/include/__iterator/counted_iterator.h | 2 +- .../counted.iterator/increment.pass.cpp | 45 +++++++++---------- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index a212d56685c0..fa82e67ac7db 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -150,7 +150,7 @@ "`3619 `__","Specification of ``vformat_to`` contains ill-formed ``formatted_size`` calls","February 2022","|Nothing to do|","","|format|" "`3621 `__","Remove feature-test macro ``__cpp_lib_monadic_optional`` ","February 2022","|Complete|","15.0" "`3632 `__","``unique_ptr`` ""Mandates: This constructor is not selected by class template argument deduction""","February 2022","|Nothing to do|","" -"`3643 `__","Missing ``constexpr`` in ``std::counted_iterator`` ","February 2022","","","|ranges|" +"`3643 `__","Missing ``constexpr`` in ``std::counted_iterator`` ","February 2022","|Complete|","19.0","|ranges|" "`3648 `__","``format`` should not print ``bool`` with ``'c'`` ","February 2022","|Complete|","15.0","|format|" "`3649 `__","[fund.ts.v2] Reinstate and bump ``__cpp_lib_experimental_memory_resource`` feature test macro","February 2022","","" "`3650 `__","Are ``std::basic_string`` 's ``iterator`` and ``const_iterator`` constexpr iterators?","February 2022","|Nothing to do|","" diff --git a/libcxx/include/__iterator/counted_iterator.h b/libcxx/include/__iterator/counted_iterator.h index 008c52fa87ce..ea2832e3b978 100644 --- a/libcxx/include/__iterator/counted_iterator.h +++ b/libcxx/include/__iterator/counted_iterator.h @@ -129,7 +129,7 @@ public: return *this; } - _LIBCPP_HIDE_FROM_ABI decltype(auto) operator++(int) { + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator++(int) { _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator already at or past end."); --__count_; # ifndef _LIBCPP_HAS_NO_EXCEPTIONS diff --git a/libcxx/test/std/iterators/predef.iterators/counted.iterator/increment.pass.cpp b/libcxx/test/std/iterators/predef.iterators/counted.iterator/increment.pass.cpp index 66d90a418744..2fea2561ebf7 100644 --- a/libcxx/test/std/iterators/predef.iterators/counted.iterator/increment.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/counted.iterator/increment.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // constexpr counted_iterator& operator++(); -// decltype(auto) operator++(int); +// constexpr decltype(auto) operator++(int); // constexpr counted_iterator operator++(int) // requires forward_iterator; @@ -62,6 +62,26 @@ concept PlusEnabled = requires(Iter& iter) { constexpr bool test() { int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + { + using Counted = std::counted_iterator; + std::counted_iterator iter(InputOrOutputArchetype{buffer}, 8); + + iter++; + assert((++iter).base().ptr == buffer + 2); + + ASSERT_SAME_TYPE(decltype(iter++), void); + ASSERT_SAME_TYPE(decltype(++iter), Counted&); + } + { + using Counted = std::counted_iterator>; + std::counted_iterator iter(cpp20_input_iterator{buffer}, 8); + + iter++; + assert(++iter == Counted(cpp20_input_iterator{buffer + 2}, 6)); + + ASSERT_SAME_TYPE(decltype(iter++), void); + ASSERT_SAME_TYPE(decltype(++iter), Counted&); + } { using Counted = std::counted_iterator>; std::counted_iterator iter(forward_iterator{buffer}, 8); @@ -95,29 +115,8 @@ int main(int, char**) { test(); static_assert(test()); - int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - - { - using Counted = std::counted_iterator; - std::counted_iterator iter(InputOrOutputArchetype{buffer}, 8); - - iter++; - assert((++iter).base().ptr == buffer + 2); - - ASSERT_SAME_TYPE(decltype(iter++), void); - ASSERT_SAME_TYPE(decltype(++iter), Counted&); - } - { - using Counted = std::counted_iterator>; - std::counted_iterator iter(cpp20_input_iterator{buffer}, 8); - - iter++; - assert(++iter == Counted(cpp20_input_iterator{buffer + 2}, 6)); - - ASSERT_SAME_TYPE(decltype(iter++), void); - ASSERT_SAME_TYPE(decltype(++iter), Counted&); - } #ifndef TEST_HAS_NO_EXCEPTIONS + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; { using Counted = std::counted_iterator>; std::counted_iterator iter(ThrowsOnInc{buffer}, 8); -- GitLab From 5fa58e28f34f4b5b41dd2869212ac917fb42b2e3 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Thu, 4 Apr 2024 06:55:47 -0700 Subject: [PATCH 062/464] [RISCV] Split PseudoVFADD, PseudoVFSUB, and PseudoVFRSUB by SEW Co-authored-by: Wang Pengcheng --- .../Target/RISCV/RISCVInstrInfoVPseudos.td | 26 ++++++++++--------- .../Target/RISCV/RISCVInstrInfoVSDPatterns.td | 6 ++--- .../Target/RISCV/RISCVInstrInfoVVLPatterns.td | 6 ++--- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 16 +++++++++--- llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td | 16 +++++++++--- llvm/lib/Target/RISCV/RISCVScheduleV.td | 16 ++++++------ 6 files changed, 52 insertions(+), 34 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index cf9a31c23a06..ebe8a29fdfa8 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -2917,16 +2917,17 @@ multiclass VPseudoVMAX_VV_VF { multiclass VPseudoVALU_VV_VF_RM { foreach m = MxListF in { - defm "" : VPseudoBinaryFV_VV_RM, - SchedBinary<"WriteVFALUV", "ReadVFALUV", "ReadVFALUV", m.MX, - forceMergeOpRead=true>; + foreach e = SchedSEWSet.val in + defm "" : VPseudoBinaryFV_VV_RM, + SchedBinary<"WriteVFALUV", "ReadVFALUV", "ReadVFALUV", m.MX, e, + forceMergeOpRead=true>; } foreach f = FPList in { foreach m = f.MxList in { - defm "" : VPseudoBinaryV_VF_RM, + defm "" : VPseudoBinaryV_VF_RM, SchedBinary<"WriteVFALUF", "ReadVFALUV", "ReadVFALUF", m.MX, - forceMergeOpRead=true>; + f.SEW, forceMergeOpRead=true>; } } } @@ -2934,9 +2935,9 @@ multiclass VPseudoVALU_VV_VF_RM { multiclass VPseudoVALU_VF_RM { foreach f = FPList in { foreach m = f.MxList in { - defm "" : VPseudoBinaryV_VF_RM, + defm "" : VPseudoBinaryV_VF_RM, SchedBinary<"WriteVFALUF", "ReadVFALUV", "ReadVFALUF", m.MX, - forceMergeOpRead=true>; + f.SEW, forceMergeOpRead=true>; } } } @@ -7061,11 +7062,12 @@ defm : VPatBinaryV_WV_WX_WI_RM<"int_riscv_vnclip", "PseudoVNCLIP", //===----------------------------------------------------------------------===// // 13.2. Vector Single-Width Floating-Point Add/Subtract Instructions //===----------------------------------------------------------------------===// -defm : VPatBinaryV_VV_VX_RM<"int_riscv_vfadd", "PseudoVFADD", - AllFloatVectors>; -defm : VPatBinaryV_VV_VX_RM<"int_riscv_vfsub", "PseudoVFSUB", - AllFloatVectors>; -defm : VPatBinaryV_VX_RM<"int_riscv_vfrsub", "PseudoVFRSUB", AllFloatVectors>; +defm : VPatBinaryV_VV_VX_RM<"int_riscv_vfadd", "PseudoVFADD", AllFloatVectors, + isSEWAware = 1>; +defm : VPatBinaryV_VV_VX_RM<"int_riscv_vfsub", "PseudoVFSUB", AllFloatVectors, + isSEWAware = 1>; +defm : VPatBinaryV_VX_RM<"int_riscv_vfrsub", "PseudoVFRSUB", AllFloatVectors, + isSEWAware = 1>; //===----------------------------------------------------------------------===// // 13.3. Vector Widening Floating-Point Add/Subtract Instructions diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td index da761ae85670..0d5cd93984af 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td @@ -1204,9 +1204,9 @@ foreach mti = AllMasks in { // 13. Vector Floating-Point Instructions // 13.2. Vector Single-Width Floating-Point Add/Subtract Instructions -defm : VPatBinaryFPSDNode_VV_VF_RM; -defm : VPatBinaryFPSDNode_VV_VF_RM; -defm : VPatBinaryFPSDNode_R_VF_RM; +defm : VPatBinaryFPSDNode_VV_VF_RM; +defm : VPatBinaryFPSDNode_VV_VF_RM; +defm : VPatBinaryFPSDNode_R_VF_RM; // 13.3. Vector Widening Floating-Point Add/Subtract Instructions defm : VPatWidenBinaryFPSDNode_VV_VF_WV_WF_RM; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td index b721dcd98988..befe8d07e575 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td @@ -2425,9 +2425,9 @@ foreach vtiToWti = AllWidenableIntVectors in // 13. Vector Floating-Point Instructions // 13.2. Vector Single-Width Floating-Point Add/Subtract Instructions -defm : VPatBinaryFPVL_VV_VF_RM; -defm : VPatBinaryFPVL_VV_VF_RM; -defm : VPatBinaryFPVL_R_VF_RM; +defm : VPatBinaryFPVL_VV_VF_RM; +defm : VPatBinaryFPVL_VV_VF_RM; +defm : VPatBinaryFPVL_R_VF_RM; // 13.3. Vector Widening Floating-Point Add/Subtract Instructions defm : VPatBinaryFPWVL_VV_VF_WV_WF_RM; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index 54a13889ee69..f14766c98439 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -732,12 +732,20 @@ foreach mx = SchedMxListW in { } // 13. Vector Floating-Point Instructions +foreach mx = SchedMxListF in { + foreach sew = SchedSEWSet.val in { + defvar Cycles = SiFive7GetCyclesDefault.c; + defvar IsWorstCase = SiFive7IsWorstCaseMXSEW.c; + let Latency = 8, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVFALUV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFALUF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + } + } +} foreach mx = SchedMxList in { defvar Cycles = SiFive7GetCyclesDefault.c; defvar IsWorstCase = SiFive7IsWorstCaseMX.c; let Latency = 8, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { - defm "" : LMULWriteResMX<"WriteVFALUV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFALUF", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulF", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulAddV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; @@ -1137,8 +1145,8 @@ defm "" : LMULReadAdvanceW<"ReadVNClipV", 0>; defm "" : LMULReadAdvanceW<"ReadVNClipX", 0>; // 14. Vector Floating-Point Instructions -defm "" : LMULReadAdvance<"ReadVFALUV", 0>; -defm "" : LMULReadAdvance<"ReadVFALUF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFALUV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFALUF", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWALUV", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWALUF", 0>; defm "" : LMULReadAdvance<"ReadVFMulV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td index 54016959d348..4d81bafdf88b 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td @@ -486,12 +486,20 @@ foreach mx = SchedMxList in { } // 13. Vector Floating-Point Instructions +foreach mx = SchedMxListF in { + foreach sew = SchedSEWSet.val in { + defvar LMulLat = SiFiveP600GetLMulCycles.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVFALUV", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFALUF", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + } + } +} foreach mx = SchedMxList in { defvar LMulLat = SiFiveP600GetLMulCycles.c; defvar IsWorstCase = SiFiveP600IsWorstCaseMX.c; let Latency = 6, ReleaseAtCycles = [LMulLat] in { - defm "" : LMULWriteResMX<"WriteVFALUV", [SiFiveP600VectorArith], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFALUF", [SiFiveP600VectorArith], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulV", [SiFiveP600VectorArith], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulF", [SiFiveP600VectorArith], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulAddV", [SiFiveP600VectorArith], mx, IsWorstCase>; @@ -925,8 +933,8 @@ defm "" : LMULReadAdvanceW<"ReadVNClipV", 0>; defm "" : LMULReadAdvanceW<"ReadVNClipX", 0>; // 14. Vector Floating-Point Instructions -defm "" : LMULReadAdvance<"ReadVFALUV", 0>; -defm "" : LMULReadAdvance<"ReadVFALUF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFALUV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFALUF", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWALUV", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWALUF", 0>; defm "" : LMULReadAdvance<"ReadVFMulV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td index 379622d4ca83..9b9c72e0767a 100644 --- a/llvm/lib/Target/RISCV/RISCVScheduleV.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td @@ -397,8 +397,8 @@ defm "" : LMULSchedWritesW<"WriteVNClipI">; // 13. Vector Floating-Point Instructions // 13.2. Vector Single-Width Floating-Point Add/Subtract Instructions -defm "" : LMULSchedWrites<"WriteVFALUV">; -defm "" : LMULSchedWrites<"WriteVFALUF">; +defm "" : LMULSEWSchedWritesF<"WriteVFALUV">; +defm "" : LMULSEWSchedWritesF<"WriteVFALUF">; // 13.3. Vector Widening Floating-Point Add/Subtract Instructions defm "" : LMULSchedWritesFW<"WriteVFWALUV">; defm "" : LMULSchedWritesFW<"WriteVFWALUF">; @@ -622,8 +622,8 @@ defm "" : LMULSchedReadsW<"ReadVNClipX">; // 13. Vector Floating-Point Instructions // 13.2. Vector Single-Width Floating-Point Add/Subtract Instructions -defm "" : LMULSchedReads<"ReadVFALUV">; -defm "" : LMULSchedReads<"ReadVFALUF">; +defm "" : LMULSEWSchedReadsF<"ReadVFALUV">; +defm "" : LMULSEWSchedReadsF<"ReadVFALUF">; // 13.3. Vector Widening Floating-Point Add/Subtract Instructions defm "" : LMULSchedReadsFW<"ReadVFWALUV">; defm "" : LMULSchedReadsFW<"ReadVFWALUF">; @@ -868,8 +868,8 @@ defm "" : LMULWriteResW<"WriteVNClipX", []>; defm "" : LMULWriteResW<"WriteVNClipI", []>; // 13. Vector Floating-Point Instructions -defm "" : LMULWriteRes<"WriteVFALUV", []>; -defm "" : LMULWriteRes<"WriteVFALUF", []>; +defm "" : LMULSEWWriteResF<"WriteVFALUV", []>; +defm "" : LMULSEWWriteResF<"WriteVFALUF", []>; defm "" : LMULWriteResFW<"WriteVFWALUV", []>; defm "" : LMULWriteResFW<"WriteVFWALUF", []>; defm "" : LMULWriteRes<"WriteVFMulV", []>; @@ -1024,8 +1024,8 @@ defm "" : LMULReadAdvanceW<"ReadVNClipV", 0>; defm "" : LMULReadAdvanceW<"ReadVNClipX", 0>; // 13. Vector Floating-Point Instructions -defm "" : LMULReadAdvance<"ReadVFALUV", 0>; -defm "" : LMULReadAdvance<"ReadVFALUF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFALUV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFALUF", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWALUV", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWALUF", 0>; defm "" : LMULReadAdvance<"ReadVFMulV", 0>; -- GitLab From aece68269c8cb28e16dc5c4ec9aabecb807a0438 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Thu, 4 Apr 2024 08:38:32 -0700 Subject: [PATCH 063/464] [RISCV] Split PseudoVFWADD, PseudoVFWSUB, and PseudoVFWMUL by SEW Co-authored-by: Wang Pengcheng --- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 46 ++++++- .../Target/RISCV/RISCVInstrInfoVPseudos.td | 121 ++++++++++-------- .../Target/RISCV/RISCVInstrInfoVSDPatterns.td | 12 +- .../Target/RISCV/RISCVInstrInfoVVLPatterns.td | 43 ++++--- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 24 ++-- llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td | 24 ++-- llvm/lib/Target/RISCV/RISCVScheduleV.td | 44 ++++--- 7 files changed, 203 insertions(+), 111 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index d78f5bd9dedf..3b76e7158ffd 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -3038,14 +3038,13 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI, #define CASE_WIDEOP_OPCODE_LMULS(OP) \ CASE_WIDEOP_OPCODE_COMMON(OP, MF8): \ case CASE_WIDEOP_OPCODE_LMULS_MF4(OP) -// clang-format on #define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL) \ case RISCV::PseudoV##OP##_##LMUL##_TIED: \ NewOpc = RISCV::PseudoV##OP##_##LMUL; \ break; -#define CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP) \ +#define CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP) \ CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4) \ CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2) \ CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1) \ @@ -3056,6 +3055,41 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI, CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8) \ CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP) +// FP Widening Ops may by SEW aware. Create SEW aware cases for these cases. +#define CASE_FP_WIDEOP_OPCODE_COMMON(OP, LMUL, SEW) \ + RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED + +#define CASE_FP_WIDEOP_OPCODE_LMULS_MF4(OP) \ + CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \ + case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \ + case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E32): \ + case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \ + case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E32): \ + case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \ + case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E32): \ + case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16): \ + case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E32) \ + +#define CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL, SEW) \ + case RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED: \ + NewOpc = RISCV::PseudoV##OP##_##LMUL##_##SEW; \ + break; + +#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E32) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E32) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E32) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E32) \ + +#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS(OP) \ + CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP) +// clang-format on + MachineInstr *RISCVInstrInfo::convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const { @@ -3063,8 +3097,8 @@ MachineInstr *RISCVInstrInfo::convertToThreeAddress(MachineInstr &MI, switch (MI.getOpcode()) { default: return nullptr; - case CASE_WIDEOP_OPCODE_LMULS_MF4(FWADD_WV): - case CASE_WIDEOP_OPCODE_LMULS_MF4(FWSUB_WV): { + case CASE_FP_WIDEOP_OPCODE_LMULS_MF4(FWADD_WV): + case CASE_FP_WIDEOP_OPCODE_LMULS_MF4(FWSUB_WV): { assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags) && MI.getNumExplicitOperands() == 7 && "Expect 7 explicit operands rd, rs2, rs1, rm, vl, sew, policy"); @@ -3077,8 +3111,8 @@ MachineInstr *RISCVInstrInfo::convertToThreeAddress(MachineInstr &MI, switch (MI.getOpcode()) { default: llvm_unreachable("Unexpected opcode"); - CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(FWADD_WV) - CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(FWSUB_WV) + CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_MF4(FWADD_WV) + CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_MF4(FWSUB_WV) } // clang-format on diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index ebe8a29fdfa8..1097eb4fb643 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -2213,11 +2213,13 @@ multiclass VPseudoTiedBinaryRoundingMode { + defvar suffix = !if(sew, "_" # MInfo.MX # "_E" # sew, "_" # MInfo.MX); let VLMul = MInfo.value in { - def "_" # MInfo.MX # "_TIED": + def suffix # "_TIED": VPseudoTiedBinaryNoMaskRoundingMode; - def "_" # MInfo.MX # "_MASK_TIED" : + def suffix # "_MASK_TIED" : VPseudoTiedBinaryMaskRoundingMode, RISCVMaskedPseudo; } @@ -2334,9 +2336,9 @@ multiclass VPseudoBinaryW_VV { "@earlyclobber $rd", TargetConstraintType=3>; } -multiclass VPseudoBinaryW_VV_RM { +multiclass VPseudoBinaryW_VV_RM { defm _VV : VPseudoBinaryRoundingMode; } @@ -2356,10 +2358,10 @@ multiclass VPseudoBinaryW_VF { "@earlyclobber $rd">; } -multiclass VPseudoBinaryW_VF_RM { +multiclass VPseudoBinaryW_VF_RM { defm "_V" # f.FX : VPseudoBinaryRoundingMode; } @@ -2371,11 +2373,13 @@ multiclass VPseudoBinaryW_WV { "@earlyclobber $rd", TargetConstraintType=3>; } -multiclass VPseudoBinaryW_WV_RM { +multiclass VPseudoBinaryW_WV_RM { defm _WV : VPseudoBinaryRoundingMode; + "@earlyclobber $rd", sew, UsesVXRM = 0, + TargetConstraintType = 3>; defm _WV : VPseudoTiedBinaryRoundingMode; + "@earlyclobber $rd", sew, + TargetConstraintType = 3>; } multiclass VPseudoBinaryW_WX { @@ -2387,11 +2391,11 @@ multiclass VPseudoBinaryW_WF; } -multiclass VPseudoBinaryW_WF_RM { +multiclass VPseudoBinaryW_WF_RM { defm "_W" # f.FX : VPseudoBinaryRoundingMode; } @@ -2979,16 +2983,17 @@ multiclass VPseudoVWMUL_VV_VX { multiclass VPseudoVWMUL_VV_VF_RM { foreach m = MxListFW in { - defm "" : VPseudoBinaryW_VV_RM, + foreach e = SchedSEWSet.val in + defm "" : VPseudoBinaryW_VV_RM, SchedBinary<"WriteVFWMulV", "ReadVFWMulV", "ReadVFWMulV", m.MX, - forceMergeOpRead=true>; + e, forceMergeOpRead=true>; } foreach f = FPListW in { foreach m = f.MxListFW in { - defm "" : VPseudoBinaryW_VF_RM, + defm "" : VPseudoBinaryW_VF_RM, SchedBinary<"WriteVFWMulF", "ReadVFWMulV", "ReadVFWMulF", m.MX, - forceMergeOpRead=true>; + f.SEW, forceMergeOpRead=true>; } } } @@ -3007,31 +3012,33 @@ multiclass VPseudoVWALU_WV_WX { multiclass VPseudoVFWALU_VV_VF_RM { foreach m = MxListFW in { - defm "" : VPseudoBinaryW_VV_RM, - SchedBinary<"WriteVFWALUV", "ReadVFWALUV", "ReadVFWALUV", m.MX, - forceMergeOpRead=true>; + foreach e = SchedSEWSet.val in + defm "" : VPseudoBinaryW_VV_RM, + SchedBinary<"WriteVFWALUV", "ReadVFWALUV", "ReadVFWALUV", m.MX, + e, forceMergeOpRead=true>; } foreach f = FPListW in { foreach m = f.MxListFW in { - defm "" : VPseudoBinaryW_VF_RM, + defm "" : VPseudoBinaryW_VF_RM, SchedBinary<"WriteVFWALUF", "ReadVFWALUV", "ReadVFWALUF", m.MX, - forceMergeOpRead=true>; + f.SEW, forceMergeOpRead=true>; } } } multiclass VPseudoVFWALU_WV_WF_RM { foreach m = MxListFW in { - defm "" : VPseudoBinaryW_WV_RM, - SchedBinary<"WriteVFWALUV", "ReadVFWALUV", "ReadVFWALUV", m.MX, - forceMergeOpRead=true>; + foreach e = SchedSEWSet.val in + defm "" : VPseudoBinaryW_WV_RM, + SchedBinary<"WriteVFWALUV", "ReadVFWALUV", "ReadVFWALUV", m.MX, + e, forceMergeOpRead=true>; } foreach f = FPListW in { foreach m = f.MxListFW in { - defm "" : VPseudoBinaryW_WF_RM, + defm "" : VPseudoBinaryW_WF_RM, SchedBinary<"WriteVFWALUF", "ReadVFWALUV", "ReadVFWALUF", m.MX, - forceMergeOpRead=true>; + f.SEW, forceMergeOpRead=true>; } } } @@ -5028,13 +5035,16 @@ multiclass VPatBinaryW_VV vtilist> { + list vtilist, bit isSEWAware = 0> { foreach VtiToWti = vtilist in { defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; + defvar name = !if(isSEWAware, + instruction # "_VV_" # Vti.LMul.MX # "_E" # Vti.SEW, + instruction # "_VV_" # Vti.LMul.MX); let Predicates = !listconcat(GetVTypePredicates.Predicates, GetVTypePredicates.Predicates) in - defm : VPatBinaryRoundingMode; @@ -5057,14 +5067,17 @@ multiclass VPatBinaryW_VX vtilist> { + list vtilist, bit isSEWAware = 0> { foreach VtiToWti = vtilist in { defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; defvar kind = "V"#Vti.ScalarSuffix; + defvar name = !if(isSEWAware, + instruction#"_"#kind#"_"#Vti.LMul.MX # "_E" # Vti.SEW, + instruction#"_"#kind#"_"#Vti.LMul.MX); let Predicates = !listconcat(GetVTypePredicates.Predicates, GetVTypePredicates.Predicates) in - defm : VPatBinaryRoundingMode; @@ -5101,27 +5114,30 @@ multiclass VPatBinaryW_WV vtilist> { + list vtilist, bit isSEWAware = 0> { foreach VtiToWti = vtilist in { defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; + defvar name = !if(isSEWAware, + instruction # "_WV_" # Vti.LMul.MX # "_E" # Vti.SEW, + instruction # "_WV_" # Vti.LMul.MX); let Predicates = !listconcat(GetVTypePredicates.Predicates, GetVTypePredicates.Predicates) in { - def : VPatTiedBinaryNoMaskRoundingMode; - def : VPatBinaryNoMaskTURoundingMode; let AddedComplexity = 1 in { - def : VPatTiedBinaryNoMaskTURoundingMode; - def : VPatTiedBinaryMaskRoundingMode; } - def : VPatBinaryMaskTARoundingMode; @@ -5145,14 +5161,17 @@ multiclass VPatBinaryW_WX vtilist> { + list vtilist, bit isSEWAware = 0> { foreach VtiToWti = vtilist in { defvar Vti = VtiToWti.Vti; defvar Wti = VtiToWti.Wti; defvar kind = "W"#Vti.ScalarSuffix; + defvar name = !if(isSEWAware, + instruction#"_"#kind#"_"#Vti.LMul.MX#"_E"#Vti.SEW, + instruction#"_"#kind#"_"#Vti.LMul.MX); let Predicates = !listconcat(GetVTypePredicates.Predicates, GetVTypePredicates.Predicates) in - defm : VPatBinaryRoundingMode; @@ -5417,20 +5436,22 @@ multiclass VPatBinaryW_VV_VX, VPatBinaryW_VX; -multiclass VPatBinaryW_VV_VX_RM vtilist> - : VPatBinaryW_VV_RM, - VPatBinaryW_VX_RM; +multiclass + VPatBinaryW_VV_VX_RM vtilist, bit isSEWAware = 0> + : VPatBinaryW_VV_RM, + VPatBinaryW_VX_RM; multiclass VPatBinaryW_WV_WX vtilist> : VPatBinaryW_WV, VPatBinaryW_WX; -multiclass VPatBinaryW_WV_WX_RM vtilist> - : VPatBinaryW_WV_RM, - VPatBinaryW_WX_RM; +multiclass + VPatBinaryW_WV_WX_RM vtilist, bit isSEWAware = 0> + : VPatBinaryW_WV_RM, + VPatBinaryW_WX_RM; multiclass VPatBinaryV_WV_WX_WI vtilist> @@ -7073,13 +7094,13 @@ defm : VPatBinaryV_VX_RM<"int_riscv_vfrsub", "PseudoVFRSUB", AllFloatVectors, // 13.3. Vector Widening Floating-Point Add/Subtract Instructions //===----------------------------------------------------------------------===// defm : VPatBinaryW_VV_VX_RM<"int_riscv_vfwadd", "PseudoVFWADD", - AllWidenableFloatVectors>; + AllWidenableFloatVectors, isSEWAware=1>; defm : VPatBinaryW_VV_VX_RM<"int_riscv_vfwsub", "PseudoVFWSUB", - AllWidenableFloatVectors>; + AllWidenableFloatVectors, isSEWAware=1>; defm : VPatBinaryW_WV_WX_RM<"int_riscv_vfwadd_w", "PseudoVFWADD", - AllWidenableFloatVectors>; + AllWidenableFloatVectors, isSEWAware=1>; defm : VPatBinaryW_WV_WX_RM<"int_riscv_vfwsub_w", "PseudoVFWSUB", - AllWidenableFloatVectors>; + AllWidenableFloatVectors, isSEWAware=1>; //===----------------------------------------------------------------------===// // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions @@ -7095,7 +7116,7 @@ defm : VPatBinaryV_VX_RM<"int_riscv_vfrdiv", "PseudoVFRDIV", // 13.5. Vector Widening Floating-Point Multiply //===----------------------------------------------------------------------===// defm : VPatBinaryW_VV_VX_RM<"int_riscv_vfwmul", "PseudoVFWMUL", - AllWidenableFloatVectors>; + AllWidenableFloatVectors, isSEWAware=1>; //===----------------------------------------------------------------------===// // 13.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td index 0d5cd93984af..37acd9667a54 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td @@ -621,7 +621,7 @@ multiclass VPatWidenBinaryFPSDNode_VV_VF_RM (wti.Vector (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs1), (vti.Mask true_mask), (XLenVT srcvalue)))), - (!cast(instruction_name#"_VV_"#vti.LMul.MX) + (!cast(instruction_name#"_VV_"#vti.LMul.MX#"_E"#vti.SEW) (wti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs2, vti.RegClass:$rs1, // Value to indicate no rounding mode change in @@ -634,7 +634,7 @@ multiclass VPatWidenBinaryFPSDNode_VV_VF_RM (wti.Vector (riscv_fpextend_vl_oneuse (vti.Vector (SplatFPOp (vti.Scalar vti.ScalarRegClass:$rs1))), (vti.Mask true_mask), (XLenVT srcvalue)))), - (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX#"_E"#vti.SEW) (wti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs2, vti.ScalarRegClass:$rs1, // Value to indicate no rounding mode change in @@ -645,7 +645,7 @@ multiclass VPatWidenBinaryFPSDNode_VV_VF_RM (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue))), (wti.Vector (SplatFPOp (fpext_oneuse (vti.Scalar vti.ScalarRegClass:$rs1))))), - (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX#"_E"#vti.SEW) (wti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs2, vti.ScalarRegClass:$rs1, // Value to indicate no rounding mode change in @@ -666,7 +666,7 @@ multiclass VPatWidenBinaryFPSDNode_WV_WF_RM (wti.Vector (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs1), (vti.Mask true_mask), (XLenVT srcvalue)))), - (!cast(instruction_name#"_WV_"#vti.LMul.MX#"_TIED") + (!cast(instruction_name#"_WV_"#vti.LMul.MX#"_E"#vti.SEW#"_TIED") wti.RegClass:$rs2, vti.RegClass:$rs1, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -677,7 +677,7 @@ multiclass VPatWidenBinaryFPSDNode_WV_WF_RM (wti.Vector (riscv_fpextend_vl_oneuse (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)), (vti.Mask true_mask), (XLenVT srcvalue)))), - (!cast(instruction_name#"_W"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_W"#vti.ScalarSuffix#"_"#vti.LMul.MX#"_E"#vti.SEW) (wti.Vector (IMPLICIT_DEF)), wti.RegClass:$rs2, vti.ScalarRegClass:$rs1, // Value to indicate no rounding mode change in @@ -686,7 +686,7 @@ multiclass VPatWidenBinaryFPSDNode_WV_WF_RM vti.AVL, vti.Log2SEW, TA_MA)>; def : Pat<(op (wti.Vector wti.RegClass:$rs2), (wti.Vector (SplatFPOp (fpext_oneuse (vti.Scalar vti.ScalarRegClass:$rs1))))), - (!cast(instruction_name#"_W"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_W"#vti.ScalarSuffix#"_"#vti.LMul.MX#"_E"#vti.SEW) (wti.Vector (IMPLICIT_DEF)), wti.RegClass:$rs2, vti.ScalarRegClass:$rs1, // Value to indicate no rounding mode change in diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td index befe8d07e575..d2f575459e32 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td @@ -725,23 +725,27 @@ multiclass VPatTiedBinaryNoMaskVL_V_RM { + VReg op2_reg_class, + bit isSEWAware = 0> { + defvar name = !if(isSEWAware, + instruction_name#"_"#suffix#"_"#vlmul.MX#"_E"#!shl(1, log2sew)#"_TIED", + instruction_name#"_"#suffix#"_"#vlmul.MX#"_TIED"); def : Pat<(result_type (vop (result_type result_reg_class:$rs1), (op2_type op2_reg_class:$rs2), srcvalue, true_mask, VLOpFrag)), - (!cast(instruction_name#"_"#suffix#"_"# vlmul.MX#"_TIED") + (!cast(name) result_reg_class:$rs1, op2_reg_class:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR FRM_DYN, - GPR:$vl, sew, TAIL_AGNOSTIC)>; + GPR:$vl, log2sew, TAIL_AGNOSTIC)>; // Tail undisturbed def : Pat<(riscv_vmerge_vl true_mask, (result_type (vop @@ -751,13 +755,13 @@ multiclass VPatTiedBinaryNoMaskVL_V_RM(instruction_name#"_"#suffix#"_"# vlmul.MX#"_TIED") + (!cast(name) result_reg_class:$rs1, op2_reg_class:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR FRM_DYN, - GPR:$vl, sew, TU_MU)>; + GPR:$vl, log2sew, TU_MU)>; } class VPatBinaryVL_XI { } } -multiclass VPatBinaryFPWVL_VV_VF_RM { +multiclass VPatBinaryFPWVL_VV_VF_RM { foreach fvtiToFWti = AllWidenableFloatVectors in { defvar vti = fvtiToFWti.Vti; defvar wti = fvtiToFWti.Wti; @@ -1600,11 +1605,11 @@ multiclass VPatBinaryFPWVL_VV_VF_RM { def : VPatBinaryVL_V_RM; + vti.RegClass, isSEWAware>; def : VPatBinaryVL_VF_RM; + vti.ScalarRegClass, isSEWAware>; } } } @@ -1631,8 +1636,9 @@ multiclass VPatBinaryFPWVL_VV_VF_WV_WF - : VPatBinaryFPWVL_VV_VF_RM { +multiclass VPatBinaryFPWVL_VV_VF_WV_WF_RM< + SDNode vop, SDNode vop_w, string instruction_name, bit isSEWAware = 0> + : VPatBinaryFPWVL_VV_VF_RM { foreach fvtiToFWti = AllWidenableFloatVectors in { defvar vti = fvtiToFWti.Vti; defvar wti = fvtiToFWti.Wti; @@ -1640,15 +1646,16 @@ multiclass VPatBinaryFPWVL_VV_VF_WV_WF_RM.Predicates) in { defm : VPatTiedBinaryNoMaskVL_V_RM; + vti.LMul, wti.RegClass, vti.RegClass, + isSEWAware>; def : VPatBinaryVL_V_RM; + vti.RegClass, isSEWAware>; def : VPatBinaryVL_VF_RM; + vti.ScalarRegClass, isSEWAware>; } } } @@ -2430,8 +2437,10 @@ defm : VPatBinaryFPVL_VV_VF_RM; defm : VPatBinaryFPVL_R_VF_RM; // 13.3. Vector Widening Floating-Point Add/Subtract Instructions -defm : VPatBinaryFPWVL_VV_VF_WV_WF_RM; -defm : VPatBinaryFPWVL_VV_VF_WV_WF_RM; +defm : VPatBinaryFPWVL_VV_VF_WV_WF_RM; +defm : VPatBinaryFPWVL_VV_VF_WV_WF_RM; // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions defm : VPatBinaryFPVL_VV_VF_RM; @@ -2439,7 +2448,7 @@ defm : VPatBinaryFPVL_VV_VF_RM; defm : VPatBinaryFPVL_R_VF_RM; // 13.5. Vector Widening Floating-Point Multiply Instructions -defm : VPatBinaryFPWVL_VV_VF_RM; +defm : VPatBinaryFPWVL_VV_VF_RM; // 13.6 Vector Single-Width Floating-Point Fused Multiply-Add Instructions. defm : VPatFPMulAddVL_VV_VF_RM; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index f14766c98439..2b6fc5e59f80 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -790,18 +790,26 @@ foreach mx = SchedMxListW in { defm "" : LMULWriteResMX<"WriteVFWCvtIToFV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; } } +foreach mx = SchedMxListFW in { + foreach sew = SchedSEWSet.val in { + defvar Cycles = SiFive7GetCyclesDefault.c; + defvar IsWorstCase = SiFive7IsWorstCaseMXSEW.c; + let Latency = 8, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVFWALUV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWALUF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + } + } +} foreach mx = SchedMxListFW in { defvar Cycles = SiFive7GetCyclesDefault.c; defvar IsWorstCase = SiFive7IsWorstCaseMX.c; let Latency = 8, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { - defm "" : LMULWriteResMX<"WriteVFWALUV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFWMulV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFWMulAddV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFWCvtFToIV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFWCvtFToFV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFWMulAddF", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFWMulF", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFWALUF", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; } } // Narrowing @@ -1147,14 +1155,14 @@ defm "" : LMULReadAdvanceW<"ReadVNClipX", 0>; // 14. Vector Floating-Point Instructions defm "" : LMULSEWReadAdvanceF<"ReadVFALUV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFALUF", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWALUV", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWALUF", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUV", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUF", 0>; defm "" : LMULReadAdvance<"ReadVFMulV", 0>; defm "" : LMULReadAdvance<"ReadVFMulF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulV", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulF", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulF", 0>; defm "" : LMULReadAdvance<"ReadVFMulAddV", 0>; defm "" : LMULReadAdvance<"ReadVFMulAddF", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td index 4d81bafdf88b..00e92cde8522 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td @@ -541,16 +541,24 @@ foreach mx = SchedMxListFW in { defm "" : LMULWriteResMX<"WriteVFWCvtFToFV", [SiFiveP600VectorArith], mx, IsWorstCase>; } } +foreach mx = SchedMxListFW in { + foreach sew = SchedSEWSet.val in { + defvar LMulLat = SiFiveP600GetLMulCycles.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVFWALUV", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWALUF", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulV", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulF", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + } + } +} foreach mx = SchedMxListFW in { defvar LMulLat = SiFiveP600GetLMulCycles.c; defvar IsWorstCase = SiFiveP600IsWorstCaseMX.c; let Latency = 6, ReleaseAtCycles = [LMulLat] in { - defm "" : LMULWriteResMX<"WriteVFWALUV", [SiFiveP600VectorArith], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFWMulV", [SiFiveP600VectorArith], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFWMulAddV", [SiFiveP600VectorArith], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFWMulAddF", [SiFiveP600VectorArith], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFWMulF", [SiFiveP600VectorArith], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFWALUF", [SiFiveP600VectorArith], mx, IsWorstCase>; } } // Narrowing @@ -935,14 +943,14 @@ defm "" : LMULReadAdvanceW<"ReadVNClipX", 0>; // 14. Vector Floating-Point Instructions defm "" : LMULSEWReadAdvanceF<"ReadVFALUV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFALUF", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWALUV", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWALUF", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUV", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUF", 0>; defm "" : LMULReadAdvance<"ReadVFMulV", 0>; defm "" : LMULReadAdvance<"ReadVFMulF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulV", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulF", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulF", 0>; defm "" : LMULReadAdvance<"ReadVFMulAddV", 0>; defm "" : LMULReadAdvance<"ReadVFMulAddF", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td index 9b9c72e0767a..8b5bd7a0c28a 100644 --- a/llvm/lib/Target/RISCV/RISCVScheduleV.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td @@ -253,6 +253,18 @@ multiclass LMULReadAdvanceFW writes = []> : LMULReadAdvanceImpl; class LMULSchedWriteListFW names> : LMULSchedWriteListImpl; +multiclass LMULSEWSchedWritesFW + : LMULSEWSchedWritesImpl; +multiclass LMULSEWSchedReadsFW + : LMULSEWSchedReadsImpl; +multiclass LMULSEWWriteResFW resources> + : LMULSEWWriteResImpl; +multiclass + LMULSEWReadAdvanceFW writes = []> + : LMULSEWReadAdvanceImpl; + // 3.6 Vector Byte Length vlenb def WriteRdVLENB : SchedWrite; @@ -400,16 +412,16 @@ defm "" : LMULSchedWritesW<"WriteVNClipI">; defm "" : LMULSEWSchedWritesF<"WriteVFALUV">; defm "" : LMULSEWSchedWritesF<"WriteVFALUF">; // 13.3. Vector Widening Floating-Point Add/Subtract Instructions -defm "" : LMULSchedWritesFW<"WriteVFWALUV">; -defm "" : LMULSchedWritesFW<"WriteVFWALUF">; +defm "" : LMULSEWSchedWritesFW<"WriteVFWALUV">; +defm "" : LMULSEWSchedWritesFW<"WriteVFWALUF">; // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions defm "" : LMULSchedWrites<"WriteVFMulV">; defm "" : LMULSchedWrites<"WriteVFMulF">; defm "" : LMULSEWSchedWritesF<"WriteVFDivV">; defm "" : LMULSEWSchedWritesF<"WriteVFDivF">; // 13.5. Vector Widening Floating-Point Multiply -defm "" : LMULSchedWritesFW<"WriteVFWMulV">; -defm "" : LMULSchedWritesFW<"WriteVFWMulF">; +defm "" : LMULSEWSchedWritesFW<"WriteVFWMulV">; +defm "" : LMULSEWSchedWritesFW<"WriteVFWMulF">; // 13.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions defm "" : LMULSchedWrites<"WriteVFMulAddV">; defm "" : LMULSchedWrites<"WriteVFMulAddF">; @@ -625,16 +637,16 @@ defm "" : LMULSchedReadsW<"ReadVNClipX">; defm "" : LMULSEWSchedReadsF<"ReadVFALUV">; defm "" : LMULSEWSchedReadsF<"ReadVFALUF">; // 13.3. Vector Widening Floating-Point Add/Subtract Instructions -defm "" : LMULSchedReadsFW<"ReadVFWALUV">; -defm "" : LMULSchedReadsFW<"ReadVFWALUF">; +defm "" : LMULSEWSchedReadsFW<"ReadVFWALUV">; +defm "" : LMULSEWSchedReadsFW<"ReadVFWALUF">; // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions defm "" : LMULSchedReads<"ReadVFMulV">; defm "" : LMULSchedReads<"ReadVFMulF">; defm "" : LMULSEWSchedReadsF<"ReadVFDivV">; defm "" : LMULSEWSchedReadsF<"ReadVFDivF">; // 13.5. Vector Widening Floating-Point Multiply -defm "" : LMULSchedReadsFW<"ReadVFWMulV">; -defm "" : LMULSchedReadsFW<"ReadVFWMulF">; +defm "" : LMULSEWSchedReadsFW<"ReadVFWMulV">; +defm "" : LMULSEWSchedReadsFW<"ReadVFWMulF">; // 13.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions defm "" : LMULSchedReads<"ReadVFMulAddV">; defm "" : LMULSchedReads<"ReadVFMulAddF">; @@ -870,14 +882,14 @@ defm "" : LMULWriteResW<"WriteVNClipI", []>; // 13. Vector Floating-Point Instructions defm "" : LMULSEWWriteResF<"WriteVFALUV", []>; defm "" : LMULSEWWriteResF<"WriteVFALUF", []>; -defm "" : LMULWriteResFW<"WriteVFWALUV", []>; -defm "" : LMULWriteResFW<"WriteVFWALUF", []>; +defm "" : LMULSEWWriteResFW<"WriteVFWALUV", []>; +defm "" : LMULSEWWriteResFW<"WriteVFWALUF", []>; defm "" : LMULWriteRes<"WriteVFMulV", []>; defm "" : LMULWriteRes<"WriteVFMulF", []>; defm "" : LMULSEWWriteResF<"WriteVFDivV", []>; defm "" : LMULSEWWriteResF<"WriteVFDivF", []>; -defm "" : LMULWriteResFW<"WriteVFWMulV", []>; -defm "" : LMULWriteResFW<"WriteVFWMulF", []>; +defm "" : LMULSEWWriteResFW<"WriteVFWMulV", []>; +defm "" : LMULSEWWriteResFW<"WriteVFWMulF", []>; defm "" : LMULWriteRes<"WriteVFMulAddV", []>; defm "" : LMULWriteRes<"WriteVFMulAddF", []>; defm "" : LMULWriteResFW<"WriteVFWMulAddV", []>; @@ -1026,14 +1038,14 @@ defm "" : LMULReadAdvanceW<"ReadVNClipX", 0>; // 13. Vector Floating-Point Instructions defm "" : LMULSEWReadAdvanceF<"ReadVFALUV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFALUF", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWALUV", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWALUF", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUV", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUF", 0>; defm "" : LMULReadAdvance<"ReadVFMulV", 0>; defm "" : LMULReadAdvance<"ReadVFMulF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulV", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulF", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulF", 0>; defm "" : LMULReadAdvance<"ReadVFMulAddV", 0>; defm "" : LMULReadAdvance<"ReadVFMulAddF", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; -- GitLab From d309d7e4fe51a0ff0ce6430a8af585e2af2772a3 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Thu, 4 Apr 2024 08:57:15 -0700 Subject: [PATCH 064/464] [RISCV] Split PseudoVFMUL by SEW Co-authored-by: Wang Pengcheng --- llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td | 13 +++++++------ .../Target/RISCV/RISCVInstrInfoVSDPatterns.td | 2 +- .../Target/RISCV/RISCVInstrInfoVVLPatterns.td | 2 +- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 8 ++++---- llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td | 9 +++++---- llvm/lib/Target/RISCV/RISCVScheduleV.td | 16 ++++++++-------- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index 1097eb4fb643..c00c650d2d36 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -2832,16 +2832,17 @@ multiclass VPseudoVDIV_VV_VX { multiclass VPseudoVFMUL_VV_VF_RM { foreach m = MxListF in { - defm "" : VPseudoBinaryFV_VV_RM, - SchedBinary<"WriteVFMulV", "ReadVFMulV", "ReadVFMulV", m.MX, - forceMergeOpRead=true>; + foreach e = SchedSEWSet.val in + defm "" : VPseudoBinaryFV_VV_RM, + SchedBinary<"WriteVFMulV", "ReadVFMulV", "ReadVFMulV", m.MX, e, + forceMergeOpRead=true>; } foreach f = FPList in { foreach m = f.MxList in { - defm "" : VPseudoBinaryV_VF_RM, + defm "" : VPseudoBinaryV_VF_RM, SchedBinary<"WriteVFMulF", "ReadVFMulV", "ReadVFMulF", m.MX, - forceMergeOpRead=true>; + f.SEW, forceMergeOpRead=true>; } } } @@ -7106,7 +7107,7 @@ defm : VPatBinaryW_WV_WX_RM<"int_riscv_vfwsub_w", "PseudoVFWSUB", // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions //===----------------------------------------------------------------------===// defm : VPatBinaryV_VV_VX_RM<"int_riscv_vfmul", "PseudoVFMUL", - AllFloatVectors>; + AllFloatVectors, isSEWAware=1>; defm : VPatBinaryV_VV_VX_RM<"int_riscv_vfdiv", "PseudoVFDIV", AllFloatVectors, isSEWAware=1>; defm : VPatBinaryV_VX_RM<"int_riscv_vfrdiv", "PseudoVFRDIV", diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td index 37acd9667a54..26847e1bdd82 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td @@ -1213,7 +1213,7 @@ defm : VPatWidenBinaryFPSDNode_VV_VF_WV_WF_RM; defm : VPatWidenBinaryFPSDNode_VV_VF_WV_WF_RM; // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions -defm : VPatBinaryFPSDNode_VV_VF_RM; +defm : VPatBinaryFPSDNode_VV_VF_RM; defm : VPatBinaryFPSDNode_VV_VF_RM; defm : VPatBinaryFPSDNode_R_VF_RM; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td index d2f575459e32..3225260dc6f7 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td @@ -2443,7 +2443,7 @@ defm : VPatBinaryFPWVL_VV_VF_WV_WF_RM; // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions -defm : VPatBinaryFPVL_VV_VF_RM; +defm : VPatBinaryFPVL_VV_VF_RM; defm : VPatBinaryFPVL_VV_VF_RM; defm : VPatBinaryFPVL_R_VF_RM; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index 2b6fc5e59f80..af65b706b0e2 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -739,6 +739,8 @@ foreach mx = SchedMxListF in { let Latency = 8, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { defm "" : LMULSEWWriteResMXSEW<"WriteVFALUV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFALUF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFMulV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFMulF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; } } } @@ -746,8 +748,6 @@ foreach mx = SchedMxList in { defvar Cycles = SiFive7GetCyclesDefault.c; defvar IsWorstCase = SiFive7IsWorstCaseMX.c; let Latency = 8, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { - defm "" : LMULWriteResMX<"WriteVFMulV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFMulF", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulAddV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulAddF", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFRecpV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; @@ -1157,8 +1157,8 @@ defm "" : LMULSEWReadAdvanceF<"ReadVFALUV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFALUF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUF", 0>; -defm "" : LMULReadAdvance<"ReadVFMulV", 0>; -defm "" : LMULReadAdvance<"ReadVFMulF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td index 00e92cde8522..5819ce5aa315 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td @@ -493,6 +493,9 @@ foreach mx = SchedMxListF in { let Latency = 6, ReleaseAtCycles = [LMulLat] in { defm "" : LMULSEWWriteResMXSEW<"WriteVFALUV", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFALUF", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFMulV", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFMulF", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + } } } @@ -500,8 +503,6 @@ foreach mx = SchedMxList in { defvar LMulLat = SiFiveP600GetLMulCycles.c; defvar IsWorstCase = SiFiveP600IsWorstCaseMX.c; let Latency = 6, ReleaseAtCycles = [LMulLat] in { - defm "" : LMULWriteResMX<"WriteVFMulV", [SiFiveP600VectorArith], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFMulF", [SiFiveP600VectorArith], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulAddV", [SiFiveP600VectorArith], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFMulAddF", [SiFiveP600VectorArith], mx, IsWorstCase>; } @@ -945,8 +946,8 @@ defm "" : LMULSEWReadAdvanceF<"ReadVFALUV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFALUF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUF", 0>; -defm "" : LMULReadAdvance<"ReadVFMulV", 0>; -defm "" : LMULReadAdvance<"ReadVFMulF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td index 8b5bd7a0c28a..9cb3cd1c3804 100644 --- a/llvm/lib/Target/RISCV/RISCVScheduleV.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td @@ -415,8 +415,8 @@ defm "" : LMULSEWSchedWritesF<"WriteVFALUF">; defm "" : LMULSEWSchedWritesFW<"WriteVFWALUV">; defm "" : LMULSEWSchedWritesFW<"WriteVFWALUF">; // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions -defm "" : LMULSchedWrites<"WriteVFMulV">; -defm "" : LMULSchedWrites<"WriteVFMulF">; +defm "" : LMULSEWSchedWritesF<"WriteVFMulV">; +defm "" : LMULSEWSchedWritesF<"WriteVFMulF">; defm "" : LMULSEWSchedWritesF<"WriteVFDivV">; defm "" : LMULSEWSchedWritesF<"WriteVFDivF">; // 13.5. Vector Widening Floating-Point Multiply @@ -640,8 +640,8 @@ defm "" : LMULSEWSchedReadsF<"ReadVFALUF">; defm "" : LMULSEWSchedReadsFW<"ReadVFWALUV">; defm "" : LMULSEWSchedReadsFW<"ReadVFWALUF">; // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions -defm "" : LMULSchedReads<"ReadVFMulV">; -defm "" : LMULSchedReads<"ReadVFMulF">; +defm "" : LMULSEWSchedReadsF<"ReadVFMulV">; +defm "" : LMULSEWSchedReadsF<"ReadVFMulF">; defm "" : LMULSEWSchedReadsF<"ReadVFDivV">; defm "" : LMULSEWSchedReadsF<"ReadVFDivF">; // 13.5. Vector Widening Floating-Point Multiply @@ -884,8 +884,8 @@ defm "" : LMULSEWWriteResF<"WriteVFALUV", []>; defm "" : LMULSEWWriteResF<"WriteVFALUF", []>; defm "" : LMULSEWWriteResFW<"WriteVFWALUV", []>; defm "" : LMULSEWWriteResFW<"WriteVFWALUF", []>; -defm "" : LMULWriteRes<"WriteVFMulV", []>; -defm "" : LMULWriteRes<"WriteVFMulF", []>; +defm "" : LMULSEWWriteResF<"WriteVFMulV", []>; +defm "" : LMULSEWWriteResF<"WriteVFMulF", []>; defm "" : LMULSEWWriteResF<"WriteVFDivV", []>; defm "" : LMULSEWWriteResF<"WriteVFDivF", []>; defm "" : LMULSEWWriteResFW<"WriteVFWMulV", []>; @@ -1040,8 +1040,8 @@ defm "" : LMULSEWReadAdvanceF<"ReadVFALUV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFALUF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWALUF", 0>; -defm "" : LMULReadAdvance<"ReadVFMulV", 0>; -defm "" : LMULReadAdvance<"ReadVFMulF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; -- GitLab From c6b7944be4dfbb1fb35301c670812726845acaa7 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Thu, 4 Apr 2024 10:52:54 -0700 Subject: [PATCH 065/464] [RISCV] Split single width floating point fused multiple-add pseudo instructions by SEW Co-authored-by: Wang Pengcheng --- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 254 +++++++++++------- .../Target/RISCV/RISCVInstrInfoVPseudos.td | 93 ++++--- .../Target/RISCV/RISCVInstrInfoVSDPatterns.td | 2 +- .../Target/RISCV/RISCVInstrInfoVVLPatterns.td | 4 +- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 8 +- llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td | 19 +- llvm/lib/Target/RISCV/RISCVScheduleV.td | 16 +- 7 files changed, 246 insertions(+), 150 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 3b76e7158ffd..0eed604e251b 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -2712,31 +2712,54 @@ std::string RISCVInstrInfo::createMIROperandComment( } // clang-format off -#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL) \ +#define CASE_VMA_OPCODE_COMMON(OP, TYPE, LMUL) \ RISCV::PseudoV##OP##_##TYPE##_##LMUL -#define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE) \ - CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1): \ - case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2): \ - case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4): \ - case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8) +#define CASE_VMA_OPCODE_LMULS_M1(OP, TYPE) \ + CASE_VMA_OPCODE_COMMON(OP, TYPE, M1): \ + case CASE_VMA_OPCODE_COMMON(OP, TYPE, M2): \ + case CASE_VMA_OPCODE_COMMON(OP, TYPE, M4): \ + case CASE_VMA_OPCODE_COMMON(OP, TYPE, M8) -#define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE) \ - CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2): \ - case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE) +#define CASE_VMA_OPCODE_LMULS_MF2(OP, TYPE) \ + CASE_VMA_OPCODE_COMMON(OP, TYPE, MF2): \ + case CASE_VMA_OPCODE_LMULS_M1(OP, TYPE) -#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE) \ - CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4): \ - case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE) +#define CASE_VMA_OPCODE_LMULS_MF4(OP, TYPE) \ + CASE_VMA_OPCODE_COMMON(OP, TYPE, MF4): \ + case CASE_VMA_OPCODE_LMULS_MF2(OP, TYPE) -#define CASE_VFMA_OPCODE_LMULS(OP, TYPE) \ - CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF8): \ - case CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE) +#define CASE_VMA_OPCODE_LMULS(OP, TYPE) \ + CASE_VMA_OPCODE_COMMON(OP, TYPE, MF8): \ + case CASE_VMA_OPCODE_LMULS_MF4(OP, TYPE) + +// VFMA instructions are SEW specific. +#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL, SEW) \ + RISCV::PseudoV##OP##_##TYPE##_##LMUL##_##SEW + +#define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW) \ + CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1, SEW): \ + case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2, SEW): \ + case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4, SEW): \ + case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8, SEW) + +#define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW) \ + CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2, SEW): \ + case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW) + +#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE, SEW) \ + CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4, SEW): \ + case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW) + +#define CASE_VFMA_OPCODE_VV(OP) \ + CASE_VFMA_OPCODE_LMULS_MF4(OP, VV, E16): \ + case CASE_VFMA_OPCODE_LMULS_MF2(OP, VV, E32): \ + case CASE_VFMA_OPCODE_LMULS_M1(OP, VV, E64) #define CASE_VFMA_SPLATS(OP) \ - CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16): \ - case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32): \ - case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64) + CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16, E16): \ + case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32, E32): \ + case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64, E64) // clang-format on bool RISCVInstrInfo::findCommutedOpIndices(const MachineInstr &MI, @@ -2776,16 +2799,16 @@ bool RISCVInstrInfo::findCommutedOpIndices(const MachineInstr &MI, case CASE_VFMA_SPLATS(FNMSUB): case CASE_VFMA_SPLATS(FNMACC): case CASE_VFMA_SPLATS(FNMSAC): - case CASE_VFMA_OPCODE_LMULS_MF4(FMACC, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FMSAC, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FNMACC, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FNMSAC, VV): - case CASE_VFMA_OPCODE_LMULS(MADD, VX): - case CASE_VFMA_OPCODE_LMULS(NMSUB, VX): - case CASE_VFMA_OPCODE_LMULS(MACC, VX): - case CASE_VFMA_OPCODE_LMULS(NMSAC, VX): - case CASE_VFMA_OPCODE_LMULS(MACC, VV): - case CASE_VFMA_OPCODE_LMULS(NMSAC, VV): { + case CASE_VFMA_OPCODE_VV(FMACC): + case CASE_VFMA_OPCODE_VV(FMSAC): + case CASE_VFMA_OPCODE_VV(FNMACC): + case CASE_VFMA_OPCODE_VV(FNMSAC): + case CASE_VMA_OPCODE_LMULS(MADD, VX): + case CASE_VMA_OPCODE_LMULS(NMSUB, VX): + case CASE_VMA_OPCODE_LMULS(MACC, VX): + case CASE_VMA_OPCODE_LMULS(NMSAC, VX): + case CASE_VMA_OPCODE_LMULS(MACC, VV): + case CASE_VMA_OPCODE_LMULS(NMSAC, VV): { // If the tail policy is undisturbed we can't commute. assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags)); if ((MI.getOperand(MI.getNumExplicitOperands() - 1).getImm() & 1) == 0) @@ -2800,12 +2823,12 @@ bool RISCVInstrInfo::findCommutedOpIndices(const MachineInstr &MI, return false; return true; } - case CASE_VFMA_OPCODE_LMULS_MF4(FMADD, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FMSUB, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FNMADD, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FNMSUB, VV): - case CASE_VFMA_OPCODE_LMULS(MADD, VV): - case CASE_VFMA_OPCODE_LMULS(NMSUB, VV): { + case CASE_VFMA_OPCODE_VV(FMADD): + case CASE_VFMA_OPCODE_VV(FMSUB): + case CASE_VFMA_OPCODE_VV(FNMADD): + case CASE_VFMA_OPCODE_VV(FNMSUB): + case CASE_VMA_OPCODE_LMULS(MADD, VV): + case CASE_VMA_OPCODE_LMULS(NMSUB, VV): { // If the tail policy is undisturbed we can't commute. assert(RISCVII::hasVecPolicyOp(MI.getDesc().TSFlags)); if ((MI.getOperand(MI.getNumExplicitOperands() - 1).getImm() & 1) == 0) @@ -2874,33 +2897,68 @@ bool RISCVInstrInfo::findCommutedOpIndices(const MachineInstr &MI, return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2); } -#define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL) \ +// clang-format off +#define CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL) \ case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL: \ Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL; \ break; -#define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE) \ - CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1) \ - CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2) \ - CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4) \ - CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8) +#define CASE_VMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE) \ + CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1) \ + CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2) \ + CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4) \ + CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8) + +#define CASE_VMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE) \ + CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2) \ + CASE_VMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE) + +#define CASE_VMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE) \ + CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4) \ + CASE_VMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE) + +#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE) \ + CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8) \ + CASE_VMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE) + +#define CASE_VMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \ + CASE_VMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16) \ + CASE_VMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32) \ + CASE_VMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64) + +// VFMA depends on SEW. +#define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL, SEW) \ + case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL##_##SEW: \ + Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL##_##SEW; \ + break; + +#define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW) \ + CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1, SEW) \ + CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2, SEW) \ + CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4, SEW) \ + CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8, SEW) + +#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW) \ + CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2, SEW) \ + CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW) -#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE) \ - CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2) \ - CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE) +#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP) \ + CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, VV, MF4, E16) \ + CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E16) \ + CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E32) -#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE) \ - CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4) \ - CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE) +#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW) \ + CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4, SEW) \ + CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW) -#define CASE_VFMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE) \ - CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8) \ - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE) +#define CASE_VFMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE, SEW) \ + CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8, SEW) \ + CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW) #define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \ - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16) \ - CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32) \ - CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64) + CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16, E16) \ + CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32, E32) \ + CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64, E64) MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, @@ -2939,16 +2997,16 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI, case CASE_VFMA_SPLATS(FNMADD): case CASE_VFMA_SPLATS(FNMSAC): case CASE_VFMA_SPLATS(FNMSUB): - case CASE_VFMA_OPCODE_LMULS_MF4(FMACC, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FMSAC, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FNMACC, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FNMSAC, VV): - case CASE_VFMA_OPCODE_LMULS(MADD, VX): - case CASE_VFMA_OPCODE_LMULS(NMSUB, VX): - case CASE_VFMA_OPCODE_LMULS(MACC, VX): - case CASE_VFMA_OPCODE_LMULS(NMSAC, VX): - case CASE_VFMA_OPCODE_LMULS(MACC, VV): - case CASE_VFMA_OPCODE_LMULS(NMSAC, VV): { + case CASE_VFMA_OPCODE_VV(FMACC): + case CASE_VFMA_OPCODE_VV(FMSAC): + case CASE_VFMA_OPCODE_VV(FNMACC): + case CASE_VFMA_OPCODE_VV(FNMSAC): + case CASE_VMA_OPCODE_LMULS(MADD, VX): + case CASE_VMA_OPCODE_LMULS(NMSUB, VX): + case CASE_VMA_OPCODE_LMULS(MACC, VX): + case CASE_VMA_OPCODE_LMULS(NMSAC, VX): + case CASE_VMA_OPCODE_LMULS(MACC, VV): + case CASE_VMA_OPCODE_LMULS(NMSAC, VV): { // It only make sense to toggle these between clobbering the // addend/subtrahend/minuend one of the multiplicands. assert((OpIdx1 == 1 || OpIdx2 == 1) && "Unexpected opcode index"); @@ -2965,16 +3023,16 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI, CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMADD, FNMACC) CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMSAC, FNMSUB) CASE_VFMA_CHANGE_OPCODE_SPLATS(FNMSUB, FNMSAC) - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMACC, FMADD, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMSAC, FMSUB, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMACC, FNMADD, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMSAC, FNMSUB, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS(MACC, MADD, VX) - CASE_VFMA_CHANGE_OPCODE_LMULS(MADD, MACC, VX) - CASE_VFMA_CHANGE_OPCODE_LMULS(NMSAC, NMSUB, VX) - CASE_VFMA_CHANGE_OPCODE_LMULS(NMSUB, NMSAC, VX) - CASE_VFMA_CHANGE_OPCODE_LMULS(MACC, MADD, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS(NMSAC, NMSUB, VV) + CASE_VFMA_CHANGE_OPCODE_VV(FMACC, FMADD) + CASE_VFMA_CHANGE_OPCODE_VV(FMSAC, FMSUB) + CASE_VFMA_CHANGE_OPCODE_VV(FNMACC, FNMADD) + CASE_VFMA_CHANGE_OPCODE_VV(FNMSAC, FNMSUB) + CASE_VMA_CHANGE_OPCODE_LMULS(MACC, MADD, VX) + CASE_VMA_CHANGE_OPCODE_LMULS(MADD, MACC, VX) + CASE_VMA_CHANGE_OPCODE_LMULS(NMSAC, NMSUB, VX) + CASE_VMA_CHANGE_OPCODE_LMULS(NMSUB, NMSAC, VX) + CASE_VMA_CHANGE_OPCODE_LMULS(MACC, MADD, VV) + CASE_VMA_CHANGE_OPCODE_LMULS(NMSAC, NMSUB, VV) } auto &WorkingMI = cloneIfNew(MI); @@ -2982,12 +3040,12 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI, return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false, OpIdx1, OpIdx2); } - case CASE_VFMA_OPCODE_LMULS_MF4(FMADD, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FMSUB, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FNMADD, VV): - case CASE_VFMA_OPCODE_LMULS_MF4(FNMSUB, VV): - case CASE_VFMA_OPCODE_LMULS(MADD, VV): - case CASE_VFMA_OPCODE_LMULS(NMSUB, VV): { + case CASE_VFMA_OPCODE_VV(FMADD): + case CASE_VFMA_OPCODE_VV(FMSUB): + case CASE_VFMA_OPCODE_VV(FNMADD): + case CASE_VFMA_OPCODE_VV(FNMSUB): + case CASE_VMA_OPCODE_LMULS(MADD, VV): + case CASE_VMA_OPCODE_LMULS(NMSUB, VV): { assert((OpIdx1 == 1 || OpIdx2 == 1) && "Unexpected opcode index"); // If one of the operands, is the addend we need to change opcode. // Otherwise we're just swapping 2 of the multiplicands. @@ -2996,12 +3054,12 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI, switch (MI.getOpcode()) { default: llvm_unreachable("Unexpected opcode"); - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMADD, FMACC, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FMSUB, FMSAC, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMADD, FNMACC, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(FNMSUB, FNMSAC, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS(MADD, MACC, VV) - CASE_VFMA_CHANGE_OPCODE_LMULS(NMSUB, NMSAC, VV) + CASE_VFMA_CHANGE_OPCODE_VV(FMADD, FMACC) + CASE_VFMA_CHANGE_OPCODE_VV(FMSUB, FMSAC) + CASE_VFMA_CHANGE_OPCODE_VV(FNMADD, FNMACC) + CASE_VFMA_CHANGE_OPCODE_VV(FNMSUB, FNMSAC) + CASE_VMA_CHANGE_OPCODE_LMULS(MADD, MACC, VV) + CASE_VMA_CHANGE_OPCODE_LMULS(NMSUB, NMSAC, VV) } auto &WorkingMI = cloneIfNew(MI); @@ -3017,12 +3075,17 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI, return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2); } -#undef CASE_VFMA_CHANGE_OPCODE_SPLATS -#undef CASE_VFMA_CHANGE_OPCODE_LMULS -#undef CASE_VFMA_CHANGE_OPCODE_COMMON -#undef CASE_VFMA_SPLATS -#undef CASE_VFMA_OPCODE_LMULS +#undef CASE_VMA_OPCODE_COMMON +#undef CASE_VMA_OPCODE_LMULS_M1 +#undef CASE_VMA_OPCODE_LMULS_MF2 +#undef CASE_VMA_OPCODE_LMULS_MF4 +#undef CASE_VMA_OPCODE_LMULS #undef CASE_VFMA_OPCODE_COMMON +#undef CASE_VFMA_OPCODE_LMULS_M1 +#undef CASE_VFMA_OPCODE_LMULS_MF2 +#undef CASE_VFMA_OPCODE_LMULS_MF4 +#undef CASE_VFMA_OPCODE_VV +#undef CASE_VFMA_SPLATS // clang-format off #define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL) \ @@ -3190,10 +3253,17 @@ MachineInstr *RISCVInstrInfo::convertToThreeAddress(MachineInstr &MI, return MIB; } -#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS -#undef CASE_WIDEOP_CHANGE_OPCODE_COMMON -#undef CASE_WIDEOP_OPCODE_LMULS #undef CASE_WIDEOP_OPCODE_COMMON +#undef CASE_WIDEOP_OPCODE_LMULS_MF4 +#undef CASE_WIDEOP_OPCODE_LMULS +#undef CASE_WIDEOP_CHANGE_OPCODE_COMMON +#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4 +#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS +#undef CASE_FP_WIDEOP_OPCODE_COMMON +#undef CASE_FP_WIDEOP_OPCODE_LMULS_MF4 +#undef CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON +#undef CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_MF4 +#undef CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS void RISCVInstrInfo::mulImm(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator II, const DebugLoc &DL, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index c00c650d2d36..f1159ee633ea 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -3234,15 +3234,17 @@ multiclass VPseudoTernaryWithPolicyRoundingMode { let VLMul = MInfo.value in { + defvar suffix = !if(sew, "_" # MInfo.MX # "_E" # sew, "_" # MInfo.MX); let isCommutable = Commutable in - def "_" # MInfo.MX : + def suffix : VPseudoTernaryNoMaskWithPolicyRoundingMode; - def "_" # MInfo.MX # "_MASK" : + def suffix # "_MASK" : VPseudoBinaryMaskPolicyRoundingMode { Constraint, Commutable=1>; } -multiclass VPseudoTernaryV_VV_AAXA_RM { +multiclass VPseudoTernaryV_VV_AAXA_RM { defm _VV : VPseudoTernaryWithPolicyRoundingMode; + Constraint, sew, Commutable=1>; } multiclass VPseudoTernaryV_VX_AAXA { @@ -3272,10 +3274,11 @@ multiclass VPseudoTernaryV_VF_AAXA { +multiclass VPseudoTernaryV_VF_AAXA_RM { defm "_V" # f.FX : VPseudoTernaryWithPolicyRoundingMode; + sew, Commutable=1>; } multiclass VPseudoTernaryW_VV { @@ -3345,16 +3348,17 @@ multiclass VPseudoVMAC_VV_VX_AAXA { multiclass VPseudoVMAC_VV_VF_AAXA_RM { foreach m = MxListF in { - defm "" : VPseudoTernaryV_VV_AAXA_RM, - SchedTernary<"WriteVFMulAddV", "ReadVFMulAddV", "ReadVFMulAddV", - "ReadVFMulAddV", m.MX>; + foreach e = SchedSEWSet.val in + defm "" : VPseudoTernaryV_VV_AAXA_RM, + SchedTernary<"WriteVFMulAddV", "ReadVFMulAddV", "ReadVFMulAddV", + "ReadVFMulAddV", m.MX, e>; } foreach f = FPList in { foreach m = f.MxList in { - defm "" : VPseudoTernaryV_VF_AAXA_RM, + defm "" : VPseudoTernaryV_VF_AAXA_RM, SchedTernary<"WriteVFMulAddF", "ReadVFMulAddV", "ReadVFMulAddF", - "ReadVFMulAddV", m.MX>; + "ReadVFMulAddV", m.MX, f.SEW>; } } } @@ -4461,23 +4465,26 @@ class VPatTernaryNoMaskWithPolicyRoundingMode : + DAGOperand op2_kind, + bit isSEWAware = 0> : Pat<(result_type (!cast(intrinsic) (result_type result_reg_class:$rs3), (op1_type op1_reg_class:$rs1), (op2_type op2_kind:$rs2), (XLenVT timm:$round), VLOpFrag, (XLenVT timm:$policy))), - (!cast(inst#"_"#kind#"_"#vlmul.MX) + (!cast(!if(isSEWAware, + inst#"_"#kind#"_"#vlmul.MX#"_E"#!shl(1, log2sew), + inst#"_"#kind#"_"#vlmul.MX)) result_reg_class:$rs3, (op1_type op1_reg_class:$rs1), op2_kind:$rs2, (XLenVT timm:$round), - GPR:$vl, sew, (XLenVT timm:$policy))>; + GPR:$vl, log2sew, (XLenVT timm:$policy))>; class VPatTernaryMask : + DAGOperand op2_kind, + bit isSEWAware = 0> : Pat<(result_type (!cast(intrinsic#"_mask") (result_type result_reg_class:$rs3), (op1_type op1_reg_class:$rs1), @@ -4548,13 +4556,15 @@ class VPatTernaryMaskPolicyRoundingMode(inst#"_"#kind#"_"#vlmul.MX # "_MASK") + (!cast(!if(isSEWAware, + inst#"_"#kind#"_"#vlmul.MX#"_E"#!shl(1, log2sew) # "_MASK", + inst#"_"#kind#"_"#vlmul.MX # "_MASK")) result_reg_class:$rs3, (op1_type op1_reg_class:$rs1), op2_kind:$rs2, (mask_type V0), (XLenVT timm:$round), - GPR:$vl, sew, (XLenVT timm:$policy))>; + GPR:$vl, log2sew, (XLenVT timm:$policy))>; class VPatTernaryMaskTA { + DAGOperand op2_kind, + bit isSEWAware = 0> { def : VPatTernaryNoMaskWithPolicyRoundingMode; + op2_kind, isSEWAware>; def : VPatTernaryMaskPolicyRoundingMode; + op2_kind, isSEWAware>; } multiclass VPatTernaryTA vtilist> { + list vtilist, bit isSEWAware = 0> { foreach vti = vtilist in let Predicates = GetVTypePredicates.Predicates in defm : VPatTernaryWithPolicyRoundingMode; + vti.RegClass, vti.RegClass, isSEWAware>; } multiclass VPatTernaryV_VX vtilist> { + list vtilist, bit isSEWAware = 0> { foreach vti = vtilist in let Predicates = GetVTypePredicates.Predicates in defm : VPatTernaryWithPolicyRoundingMode; + vti.ScalarRegClass, vti.RegClass, isSEWAware>; } multiclass VPatTernaryV_VI; multiclass VPatTernaryV_VV_VX_AAXA_RM vtilist> - : VPatTernaryV_VV_AAXA_RM, - VPatTernaryV_VX_AAXA_RM; + list vtilist, bit isSEWAware = 0> + : VPatTernaryV_VV_AAXA_RM, + VPatTernaryV_VX_AAXA_RM; multiclass VPatTernaryV_VX_VI vtilist, Operand Imm_type = simm5> @@ -7122,14 +7133,22 @@ defm : VPatBinaryW_VV_VX_RM<"int_riscv_vfwmul", "PseudoVFWMUL", //===----------------------------------------------------------------------===// // 13.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions //===----------------------------------------------------------------------===// -defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmacc", "PseudoVFMACC", AllFloatVectors>; -defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmacc", "PseudoVFNMACC", AllFloatVectors>; -defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmsac", "PseudoVFMSAC", AllFloatVectors>; -defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmsac", "PseudoVFNMSAC", AllFloatVectors>; -defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmadd", "PseudoVFMADD", AllFloatVectors>; -defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmadd", "PseudoVFNMADD", AllFloatVectors>; -defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmsub", "PseudoVFMSUB", AllFloatVectors>; -defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmsub", "PseudoVFNMSUB", AllFloatVectors>; +defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmacc", "PseudoVFMACC", + AllFloatVectors, isSEWAware=1>; +defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmacc", "PseudoVFNMACC", + AllFloatVectors, isSEWAware=1>; +defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmsac", "PseudoVFMSAC", + AllFloatVectors, isSEWAware=1>; +defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmsac", "PseudoVFNMSAC", + AllFloatVectors, isSEWAware=1>; +defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmadd", "PseudoVFMADD", + AllFloatVectors, isSEWAware=1>; +defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmadd", "PseudoVFNMADD", + AllFloatVectors, isSEWAware=1>; +defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfmsub", "PseudoVFMSUB", + AllFloatVectors, isSEWAware=1>; +defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmsub", "PseudoVFNMSUB", + AllFloatVectors, isSEWAware=1>; //===----------------------------------------------------------------------===// // 13.7. Vector Widening Floating-Point Fused Multiply-Add Instructions diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td index 26847e1bdd82..d9dc373a628d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td @@ -1224,7 +1224,7 @@ defm : VPatWidenBinaryFPSDNode_VV_VF_RM; foreach fvti = AllFloatVectors in { // NOTE: We choose VFMADD because it has the most commuting freedom. So it // works best with how TwoAddressInstructionPass tries commuting. - defvar suffix = fvti.LMul.MX; + defvar suffix = fvti.LMul.MX # "_E" # fvti.SEW; let Predicates = GetVTypePredicates.Predicates in { def : Pat<(fvti.Vector (any_fma fvti.RegClass:$rs1, fvti.RegClass:$rd, fvti.RegClass:$rs2)), diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td index 3225260dc6f7..a6f24438daa6 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td @@ -1850,7 +1850,7 @@ multiclass VPatFPMulAddVL_VV_VF multiclass VPatFPMulAddVL_VV_VF_RM { foreach vti = AllFloatVectors in { - defvar suffix = vti.LMul.MX; + defvar suffix = vti.LMul.MX # "_E" # vti.SEW; let Predicates = GetVTypePredicates.Predicates in { def : Pat<(vti.Vector (vop vti.RegClass:$rs1, vti.RegClass:$rd, vti.RegClass:$rs2, (vti.Mask V0), @@ -1916,7 +1916,7 @@ multiclass VPatFPMulAccVL_VV_VF { multiclass VPatFPMulAccVL_VV_VF_RM { foreach vti = AllFloatVectors in { - defvar suffix = vti.LMul.MX; + defvar suffix = vti.LMul.MX # "_E" # vti.SEW; let Predicates = GetVTypePredicates.Predicates in { def : Pat<(riscv_vmerge_vl (vti.Mask V0), (vti.Vector (vop vti.RegClass:$rs1, vti.RegClass:$rs2, diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index af65b706b0e2..16bfb509e085 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -741,6 +741,8 @@ foreach mx = SchedMxListF in { defm "" : LMULSEWWriteResMXSEW<"WriteVFALUF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFMulV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFMulF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFMulAddV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFMulAddF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; } } } @@ -748,8 +750,6 @@ foreach mx = SchedMxList in { defvar Cycles = SiFive7GetCyclesDefault.c; defvar IsWorstCase = SiFive7IsWorstCaseMX.c; let Latency = 8, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { - defm "" : LMULWriteResMX<"WriteVFMulAddV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFMulAddF", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFRecpV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFCvtIToFV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFCvtFToIV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; @@ -1163,8 +1163,8 @@ defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulF", 0>; -defm "" : LMULReadAdvance<"ReadVFMulAddV", 0>; -defm "" : LMULReadAdvance<"ReadVFMulAddF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddF", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWMulAddF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td index 5819ce5aa315..0896f3358d23 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td @@ -499,13 +499,20 @@ foreach mx = SchedMxListF in { } } } + +foreach mx = SchedMxListF in { + foreach sew = SchedSEWSet.val in { + defvar LMulLat = SiFiveP600GetLMulCycles.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVFMulAddV", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFMulAddF", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + } + } +} foreach mx = SchedMxList in { defvar LMulLat = SiFiveP600GetLMulCycles.c; defvar IsWorstCase = SiFiveP600IsWorstCaseMX.c; - let Latency = 6, ReleaseAtCycles = [LMulLat] in { - defm "" : LMULWriteResMX<"WriteVFMulAddV", [SiFiveP600VectorArith], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFMulAddF", [SiFiveP600VectorArith], mx, IsWorstCase>; - } let Latency = 3, ReleaseAtCycles = [LMulLat] in { defm "" : LMULWriteResMX<"WriteVFCvtIToFV", [SiFiveP600VectorArith], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFCvtFToIV", [SiFiveP600VectorArith], mx, IsWorstCase>; @@ -952,8 +959,8 @@ defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulF", 0>; -defm "" : LMULReadAdvance<"ReadVFMulAddV", 0>; -defm "" : LMULReadAdvance<"ReadVFMulAddF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddF", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWMulAddF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td index 9cb3cd1c3804..40090d1db887 100644 --- a/llvm/lib/Target/RISCV/RISCVScheduleV.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td @@ -423,8 +423,8 @@ defm "" : LMULSEWSchedWritesF<"WriteVFDivF">; defm "" : LMULSEWSchedWritesFW<"WriteVFWMulV">; defm "" : LMULSEWSchedWritesFW<"WriteVFWMulF">; // 13.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions -defm "" : LMULSchedWrites<"WriteVFMulAddV">; -defm "" : LMULSchedWrites<"WriteVFMulAddF">; +defm "" : LMULSEWSchedWritesF<"WriteVFMulAddV">; +defm "" : LMULSEWSchedWritesF<"WriteVFMulAddF">; // 13.7. Vector Widening Floating-Point Fused Multiply-Add Instructions defm "" : LMULSchedWritesFW<"WriteVFWMulAddV">; defm "" : LMULSchedWritesFW<"WriteVFWMulAddF">; @@ -648,8 +648,8 @@ defm "" : LMULSEWSchedReadsF<"ReadVFDivF">; defm "" : LMULSEWSchedReadsFW<"ReadVFWMulV">; defm "" : LMULSEWSchedReadsFW<"ReadVFWMulF">; // 13.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions -defm "" : LMULSchedReads<"ReadVFMulAddV">; -defm "" : LMULSchedReads<"ReadVFMulAddF">; +defm "" : LMULSEWSchedReadsF<"ReadVFMulAddV">; +defm "" : LMULSEWSchedReadsF<"ReadVFMulAddF">; // 13.7. Vector Widening Floating-Point Fused Multiply-Add Instructions defm "" : LMULSchedReadsFW<"ReadVFWMulAddV">; defm "" : LMULSchedReadsFW<"ReadVFWMulAddF">; @@ -890,8 +890,8 @@ defm "" : LMULSEWWriteResF<"WriteVFDivV", []>; defm "" : LMULSEWWriteResF<"WriteVFDivF", []>; defm "" : LMULSEWWriteResFW<"WriteVFWMulV", []>; defm "" : LMULSEWWriteResFW<"WriteVFWMulF", []>; -defm "" : LMULWriteRes<"WriteVFMulAddV", []>; -defm "" : LMULWriteRes<"WriteVFMulAddF", []>; +defm "" : LMULSEWWriteResF<"WriteVFMulAddV", []>; +defm "" : LMULSEWWriteResF<"WriteVFMulAddF", []>; defm "" : LMULWriteResFW<"WriteVFWMulAddV", []>; defm "" : LMULWriteResFW<"WriteVFWMulAddF", []>; defm "" : LMULSEWWriteResF<"WriteVFSqrtV", []>; @@ -1046,8 +1046,8 @@ defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulF", 0>; -defm "" : LMULReadAdvance<"ReadVFMulAddV", 0>; -defm "" : LMULReadAdvance<"ReadVFMulAddF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddF", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; defm "" : LMULReadAdvanceFW<"ReadVFWMulAddF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; -- GitLab From 43248ffea7b8de3a33b11768e8c21d2434252528 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Thu, 4 Apr 2024 11:58:29 -0700 Subject: [PATCH 066/464] [RISCV] Split widening floating point fused multiple-add pseudo instructions by SEW Co-authored-by: Wang Pengcheng --- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 4 +- .../Target/RISCV/RISCVInstrInfoVPseudos.td | 68 ++++++++++--------- .../Target/RISCV/RISCVInstrInfoVSDPatterns.td | 24 ++++--- .../Target/RISCV/RISCVInstrInfoVVLPatterns.td | 5 +- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 8 +-- llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td | 14 ++-- llvm/lib/Target/RISCV/RISCVScheduleV.td | 16 ++--- .../CodeGen/RISCV/rvv/fixed-vectors-fmf.ll | 4 +- .../RISCV/rvv/pass-fast-math-flags-sdnode.ll | 4 +- 9 files changed, 74 insertions(+), 73 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 0eed604e251b..004a228ccc13 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -2943,9 +2943,9 @@ bool RISCVInstrInfo::findCommutedOpIndices(const MachineInstr &MI, CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW) #define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP) \ - CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, VV, MF4, E16) \ CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E16) \ - CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E32) + CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E32) \ + CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VV, E64) #define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW) \ CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4, SEW) \ diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index f1159ee633ea..77b40999fc6a 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -3287,10 +3287,10 @@ multiclass VPseudoTernaryW_VV { constraint, /*Commutable*/ 0, TargetConstraintType=3>; } -multiclass VPseudoTernaryW_VV_RM { +multiclass VPseudoTernaryW_VV_RM { defvar constraint = "@earlyclobber $rd"; defm _VV : VPseudoTernaryWithPolicyRoundingMode; } @@ -3306,11 +3306,11 @@ multiclass VPseudoTernaryW_VF; } -multiclass VPseudoTernaryW_VF_RM { +multiclass VPseudoTernaryW_VF_RM { defvar constraint = "@earlyclobber $rd"; defm "_V" # f.FX : VPseudoTernaryWithPolicyRoundingMode; } @@ -3396,16 +3396,17 @@ multiclass VPseudoVWMAC_VX { multiclass VPseudoVWMAC_VV_VF_RM { foreach m = MxListFW in { - defm "" : VPseudoTernaryW_VV_RM, - SchedTernary<"WriteVFWMulAddV", "ReadVFWMulAddV", - "ReadVFWMulAddV", "ReadVFWMulAddV", m.MX>; + foreach e = SchedSEWSet.val in + defm "" : VPseudoTernaryW_VV_RM, + SchedTernary<"WriteVFWMulAddV", "ReadVFWMulAddV", + "ReadVFWMulAddV", "ReadVFWMulAddV", m.MX, e>; } foreach f = FPListW in { foreach m = f.MxListFW in { - defm "" : VPseudoTernaryW_VF_RM, + defm "" : VPseudoTernaryW_VF_RM, SchedTernary<"WriteVFWMulAddF", "ReadVFWMulAddV", - "ReadVFWMulAddF", "ReadVFWMulAddV", m.MX>; + "ReadVFWMulAddF", "ReadVFWMulAddV", m.MX, f.SEW>; } } } @@ -3413,17 +3414,18 @@ multiclass VPseudoVWMAC_VV_VF_RM { multiclass VPseudoVWMAC_VV_VF_BF_RM { foreach m = MxListFW in { defvar mx = m.MX; - defm "" : VPseudoTernaryW_VV_RM, - SchedTernary<"WriteVFWMulAddV", "ReadVFWMulAddV", - "ReadVFWMulAddV", "ReadVFWMulAddV", mx>; + foreach e = SchedSEWSet.val in + defm "" : VPseudoTernaryW_VV_RM, + SchedTernary<"WriteVFWMulAddV", "ReadVFWMulAddV", + "ReadVFWMulAddV", "ReadVFWMulAddV", mx, e>; } foreach f = BFPListW in { foreach m = f.MxListFW in { defvar mx = m.MX; - defm "" : VPseudoTernaryW_VF_RM, + defm "" : VPseudoTernaryW_VF_RM, SchedTernary<"WriteVFWMulAddF", "ReadVFWMulAddV", - "ReadVFWMulAddF", "ReadVFWMulAddV", mx>; + "ReadVFWMulAddF", "ReadVFWMulAddV", mx, f.SEW>; } } } @@ -5703,7 +5705,7 @@ multiclass VPatTernaryW_VV vtilist> { + list vtilist, bit isSEWAware = 0> { foreach vtiToWti = vtilist in { defvar vti = vtiToWti.Vti; defvar wti = vtiToWti.Wti; @@ -5712,7 +5714,8 @@ multiclass VPatTernaryW_VV_RM; + wti.RegClass, vti.RegClass, + vti.RegClass, isSEWAware>; } } @@ -5731,19 +5734,18 @@ multiclass VPatTernaryW_VX vtilist> { +multiclass + VPatTernaryW_VX_RM vtilist, bit isSEWAware = 0> { foreach vtiToWti = vtilist in { defvar vti = vtiToWti.Vti; defvar wti = vtiToWti.Wti; let Predicates = !listconcat(GetVTypePredicates.Predicates, - GetVTypePredicates.Predicates) in - defm : VPatTernaryWithPolicyRoundingMode; + GetVTypePredicates.Predicates) in defm + : VPatTernaryWithPolicyRoundingMode< + intrinsic, instruction, "V" #vti.ScalarSuffix, wti.Vector, + vti.Scalar, vti.Vector, vti.Mask, vti.Log2SEW, vti.LMul, + wti.RegClass, vti.ScalarRegClass, vti.RegClass, isSEWAware>; } } @@ -5775,9 +5777,9 @@ multiclass VPatTernaryW_VV_VX; multiclass VPatTernaryW_VV_VX_RM vtilist> - : VPatTernaryW_VV_RM, - VPatTernaryW_VX_RM; + list vtilist, bit isSEWAware = 1> + : VPatTernaryW_VV_RM, + VPatTernaryW_VX_RM; multiclass VPatBinaryM_VV_VX vtilist> @@ -7154,16 +7156,16 @@ defm : VPatTernaryV_VV_VX_AAXA_RM<"int_riscv_vfnmsub", "PseudoVFNMSUB", // 13.7. Vector Widening Floating-Point Fused Multiply-Add Instructions //===----------------------------------------------------------------------===// defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwmacc", "PseudoVFWMACC", - AllWidenableFloatVectors>; + AllWidenableFloatVectors, isSEWAware=1>; defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwnmacc", "PseudoVFWNMACC", - AllWidenableFloatVectors>; + AllWidenableFloatVectors, isSEWAware=1>; defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwmsac", "PseudoVFWMSAC", - AllWidenableFloatVectors>; + AllWidenableFloatVectors, isSEWAware=1>; defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwnmsac", "PseudoVFWNMSAC", - AllWidenableFloatVectors>; + AllWidenableFloatVectors, isSEWAware=1>; let Predicates = [HasStdExtZvfbfwma] in defm : VPatTernaryW_VV_VX_RM<"int_riscv_vfwmaccbf16", "PseudoVFWMACCBF16", - AllWidenableBFloatToFloatVectors>; + AllWidenableBFloatToFloatVectors, isSEWAware=1>; //===----------------------------------------------------------------------===// // 13.8. Vector Floating-Point Square-Root Instruction diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td index d9dc373a628d..7c77449b4f6e 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td @@ -706,6 +706,7 @@ multiclass VPatWidenFPMulAccSDNode_VV_VF_RM { foreach vtiToWti = AllWidenableFloatVectors in { defvar vti = vtiToWti.Vti; defvar wti = vtiToWti.Wti; + defvar suffix = vti.LMul.MX # "_E" # vti.SEW; let Predicates = !listconcat(GetVTypePredicates.Predicates, GetVTypePredicates.Predicates) in { def : Pat<(fma (wti.Vector (riscv_fpextend_vl_oneuse @@ -715,7 +716,7 @@ multiclass VPatWidenFPMulAccSDNode_VV_VF_RM { (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue))), (wti.Vector wti.RegClass:$rd)), - (!cast(instruction_name#"_VV_"#vti.LMul.MX) + (!cast(instruction_name#"_VV_"#suffix) wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -727,7 +728,7 @@ multiclass VPatWidenFPMulAccSDNode_VV_VF_RM { (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue))), (wti.Vector wti.RegClass:$rd)), - (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#suffix) wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -741,6 +742,7 @@ multiclass VPatWidenFPNegMulAccSDNode_VV_VF_RM { foreach vtiToWti = AllWidenableFloatVectors in { defvar vti = vtiToWti.Vti; defvar wti = vtiToWti.Wti; + defvar suffix = vti.LMul.MX # "_E" # vti.SEW; let Predicates = !listconcat(GetVTypePredicates.Predicates, GetVTypePredicates.Predicates) in { def : Pat<(fma (fneg (wti.Vector (riscv_fpextend_vl_oneuse @@ -749,7 +751,7 @@ multiclass VPatWidenFPNegMulAccSDNode_VV_VF_RM { (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue)), (fneg wti.RegClass:$rd)), - (!cast(instruction_name#"_VV_"#vti.LMul.MX) + (!cast(instruction_name#"_VV_"#suffix) wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -760,7 +762,7 @@ multiclass VPatWidenFPNegMulAccSDNode_VV_VF_RM { (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue)))), (fneg wti.RegClass:$rd)), - (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#suffix) wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -770,7 +772,7 @@ multiclass VPatWidenFPNegMulAccSDNode_VV_VF_RM { (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue)), (fneg wti.RegClass:$rd)), - (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#suffix) wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -784,6 +786,7 @@ multiclass VPatWidenFPMulSacSDNode_VV_VF_RM { foreach vtiToWti = AllWidenableFloatVectors in { defvar vti = vtiToWti.Vti; defvar wti = vtiToWti.Wti; + defvar suffix = vti.LMul.MX # "_E" # vti.SEW; let Predicates = !listconcat(GetVTypePredicates.Predicates, GetVTypePredicates.Predicates) in { def : Pat<(fma (wti.Vector (riscv_fpextend_vl_oneuse @@ -792,7 +795,7 @@ multiclass VPatWidenFPMulSacSDNode_VV_VF_RM { (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue)), (fneg wti.RegClass:$rd)), - (!cast(instruction_name#"_VV_"#vti.LMul.MX) + (!cast(instruction_name#"_VV_"#suffix) wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -802,7 +805,7 @@ multiclass VPatWidenFPMulSacSDNode_VV_VF_RM { (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue)), (fneg wti.RegClass:$rd)), - (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#suffix) wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -816,6 +819,7 @@ multiclass VPatWidenFPNegMulSacSDNode_VV_VF_RM { foreach vtiToWti = AllWidenableFloatVectors in { defvar vti = vtiToWti.Vti; defvar wti = vtiToWti.Wti; + defvar suffix = vti.LMul.MX # "_E" # vti.SEW; let Predicates = !listconcat(GetVTypePredicates.Predicates, GetVTypePredicates.Predicates) in { def : Pat<(fma (fneg (wti.Vector (riscv_fpextend_vl_oneuse @@ -824,7 +828,7 @@ multiclass VPatWidenFPNegMulSacSDNode_VV_VF_RM { (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue)), wti.RegClass:$rd), - (!cast(instruction_name#"_VV_"#vti.LMul.MX) + (!cast(instruction_name#"_VV_"#suffix) wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -835,7 +839,7 @@ multiclass VPatWidenFPNegMulSacSDNode_VV_VF_RM { (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue)))), wti.RegClass:$rd), - (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#suffix) wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR @@ -845,7 +849,7 @@ multiclass VPatWidenFPNegMulSacSDNode_VV_VF_RM { (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2), (vti.Mask true_mask), (XLenVT srcvalue)), wti.RegClass:$rd), - (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX) + (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#suffix) wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2, // Value to indicate no rounding mode change in // RISCVInsertReadWriteCSR diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td index a6f24438daa6..322c055306e8 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td @@ -1994,13 +1994,14 @@ multiclass VPatWidenFPMulAccVL_VV_VF_RM { foreach vtiToWti = AllWidenableFloatVectors in { defvar vti = vtiToWti.Vti; defvar wti = vtiToWti.Wti; + defvar suffix = vti.LMul.MX # "_E" # vti.SEW; let Predicates = !listconcat(GetVTypePredicates.Predicates, GetVTypePredicates.Predicates) in { def : Pat<(vop (vti.Vector vti.RegClass:$rs1), (vti.Vector vti.RegClass:$rs2), (wti.Vector wti.RegClass:$rd), (vti.Mask V0), VLOpFrag), - (!cast(instruction_name#"_VV_"#vti.LMul.MX #"_MASK") + (!cast(instruction_name#"_VV_"#suffix#"_MASK") wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2, (vti.Mask V0), // Value to indicate no rounding mode change in @@ -2011,7 +2012,7 @@ multiclass VPatWidenFPMulAccVL_VV_VF_RM { (vti.Vector vti.RegClass:$rs2), (wti.Vector wti.RegClass:$rd), (vti.Mask V0), VLOpFrag), - (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX #"_MASK") + (!cast(instruction_name#"_V"#vti.ScalarSuffix#"_"#suffix#"_MASK") wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2, (vti.Mask V0), // Value to indicate no rounding mode change in diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index 16bfb509e085..1dd4afa4ee48 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -799,6 +799,8 @@ foreach mx = SchedMxListFW in { defm "" : LMULSEWWriteResMXSEW<"WriteVFWALUF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulAddV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulAddF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; } } } @@ -806,10 +808,8 @@ foreach mx = SchedMxListFW in { defvar Cycles = SiFive7GetCyclesDefault.c; defvar IsWorstCase = SiFive7IsWorstCaseMX.c; let Latency = 8, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { - defm "" : LMULWriteResMX<"WriteVFWMulAddV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFWCvtFToIV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFWCvtFToFV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFWMulAddF", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; } } // Narrowing @@ -1165,8 +1165,8 @@ defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddF", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulAddF", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddV", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; defm "" : LMULReadAdvance<"ReadVFRecpV", 0>; defm "" : LMULReadAdvance<"ReadVFMinMaxV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td index 0896f3358d23..f63dcf20e683 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td @@ -558,17 +558,11 @@ foreach mx = SchedMxListFW in { defm "" : LMULSEWWriteResMXSEW<"WriteVFWALUF", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulV", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulF", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulAddV", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWMulAddF", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; } } } -foreach mx = SchedMxListFW in { - defvar LMulLat = SiFiveP600GetLMulCycles.c; - defvar IsWorstCase = SiFiveP600IsWorstCaseMX.c; - let Latency = 6, ReleaseAtCycles = [LMulLat] in { - defm "" : LMULWriteResMX<"WriteVFWMulAddV", [SiFiveP600VectorArith], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFWMulAddF", [SiFiveP600VectorArith], mx, IsWorstCase>; - } -} // Narrowing foreach mx = SchedMxListW in { defvar LMulLat = SiFiveP600GetLMulCycles.c; @@ -961,8 +955,8 @@ defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddF", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulAddF", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddV", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; defm "" : LMULReadAdvance<"ReadVFRecpV", 0>; defm "" : LMULReadAdvance<"ReadVFCmpV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td index 40090d1db887..b82e86e9fcd5 100644 --- a/llvm/lib/Target/RISCV/RISCVScheduleV.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td @@ -426,8 +426,8 @@ defm "" : LMULSEWSchedWritesFW<"WriteVFWMulF">; defm "" : LMULSEWSchedWritesF<"WriteVFMulAddV">; defm "" : LMULSEWSchedWritesF<"WriteVFMulAddF">; // 13.7. Vector Widening Floating-Point Fused Multiply-Add Instructions -defm "" : LMULSchedWritesFW<"WriteVFWMulAddV">; -defm "" : LMULSchedWritesFW<"WriteVFWMulAddF">; +defm "" : LMULSEWSchedWritesFW<"WriteVFWMulAddV">; +defm "" : LMULSEWSchedWritesFW<"WriteVFWMulAddF">; // 13.8. Vector Floating-Point Square-Root Instruction defm "" : LMULSEWSchedWritesF<"WriteVFSqrtV">; // 13.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction @@ -651,8 +651,8 @@ defm "" : LMULSEWSchedReadsFW<"ReadVFWMulF">; defm "" : LMULSEWSchedReadsF<"ReadVFMulAddV">; defm "" : LMULSEWSchedReadsF<"ReadVFMulAddF">; // 13.7. Vector Widening Floating-Point Fused Multiply-Add Instructions -defm "" : LMULSchedReadsFW<"ReadVFWMulAddV">; -defm "" : LMULSchedReadsFW<"ReadVFWMulAddF">; +defm "" : LMULSEWSchedReadsFW<"ReadVFWMulAddV">; +defm "" : LMULSEWSchedReadsFW<"ReadVFWMulAddF">; // 13.8. Vector Floating-Point Square-Root Instruction defm "" : LMULSEWSchedReadsF<"ReadVFSqrtV">; // 13.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction @@ -892,8 +892,8 @@ defm "" : LMULSEWWriteResFW<"WriteVFWMulV", []>; defm "" : LMULSEWWriteResFW<"WriteVFWMulF", []>; defm "" : LMULSEWWriteResF<"WriteVFMulAddV", []>; defm "" : LMULSEWWriteResF<"WriteVFMulAddF", []>; -defm "" : LMULWriteResFW<"WriteVFWMulAddV", []>; -defm "" : LMULWriteResFW<"WriteVFWMulAddF", []>; +defm "" : LMULSEWWriteResFW<"WriteVFWMulAddV", []>; +defm "" : LMULSEWWriteResFW<"WriteVFWMulAddF", []>; defm "" : LMULSEWWriteResF<"WriteVFSqrtV", []>; defm "" : LMULWriteRes<"WriteVFRecpV", []>; defm "" : LMULWriteRes<"WriteVFMinMaxV", []>; @@ -1048,8 +1048,8 @@ defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddV", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddF", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; -defm "" : LMULReadAdvanceFW<"ReadVFWMulAddF", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddV", 0>; +defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; defm "" : LMULReadAdvance<"ReadVFRecpV", 0>; defm "" : LMULReadAdvance<"ReadVFMinMaxV", 0>; diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fmf.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fmf.ll index 1c1440c3e6d0..a4851e9838fb 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fmf.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fmf.ll @@ -9,8 +9,8 @@ define <2 x double> @foo(<2 x double> %x, <2 x double> %y) { ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:vr = COPY $v9 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vr = COPY $v8 - ; CHECK-NEXT: [[PseudoVFADD_VV_M1_:%[0-9]+]]:vr = nnan ninf nsz arcp contract afn reassoc nofpexcept PseudoVFADD_VV_M1 $noreg, [[COPY1]], [[COPY]], 7, 2, 6 /* e64 */, 1 /* ta, mu */, implicit $frm - ; CHECK-NEXT: $v8 = COPY [[PseudoVFADD_VV_M1_]] + ; CHECK-NEXT: [[PseudoVFADD_VV_M1_E64_:%[0-9]+]]:vr = nnan ninf nsz arcp contract afn reassoc nofpexcept PseudoVFADD_VV_M1_E64 $noreg, [[COPY1]], [[COPY]], 7, 2, 6 /* e64 */, 1 /* ta, mu */, implicit $frm + ; CHECK-NEXT: $v8 = COPY [[PseudoVFADD_VV_M1_E64_]] ; CHECK-NEXT: PseudoRET implicit $v8 %1 = fadd fast <2 x double> %x, %y ret <2 x double> %1 diff --git a/llvm/test/CodeGen/RISCV/rvv/pass-fast-math-flags-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/pass-fast-math-flags-sdnode.ll index 1ad8e2d66392..8457f3d2c149 100644 --- a/llvm/test/CodeGen/RISCV/rvv/pass-fast-math-flags-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/pass-fast-math-flags-sdnode.ll @@ -15,8 +15,8 @@ define @foo( %x, @llvm.vp.fmul.nxv1f64( %x, %y, %m, i32 %vl) ret %1 -- GitLab From b8e1ff322104e5445371328a4fbc9c1d2bf82f01 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Thu, 4 Apr 2024 12:16:39 -0700 Subject: [PATCH 067/464] [RISCV] Split PseudoVFRSQRT7 and PseudoVFREC7 by SEW Co-authored-by: Wang Pengcheng --- .../Target/RISCV/RISCVInstrInfoVPseudos.td | 62 +++++++++++-------- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 4 +- llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td | 11 +++- llvm/lib/Target/RISCV/RISCVScheduleV.td | 8 +-- 4 files changed, 52 insertions(+), 33 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index 77b40999fc6a..a5f56a1c209c 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -2577,14 +2577,16 @@ multiclass VPseudoVSQR_V_RM { multiclass VPseudoVRCP_V { foreach m = MxListF in { defvar mx = m.MX; - let VLMul = m.value in { - def "_V_" # mx - : VPseudoUnaryNoMask, - SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, forceMergeOpRead=true>; - def "_V_" # mx # "_MASK" - : VPseudoUnaryMask, - RISCVMaskedPseudo, - SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, forceMergeOpRead=true>; + foreach e = SchedSEWSet.val in { + let VLMul = m.value in { + def "_V_" # mx # "_E" # e + : VPseudoUnaryNoMask, + SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, e, forceMergeOpRead=true>; + def "_V_" # mx # "_E" # e # "_MASK" + : VPseudoUnaryMask, + RISCVMaskedPseudo, + SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, e, forceMergeOpRead=true>; + } } } } @@ -2592,14 +2594,16 @@ multiclass VPseudoVRCP_V { multiclass VPseudoVRCP_V_RM { foreach m = MxListF in { defvar mx = m.MX; - let VLMul = m.value in { - def "_V_" # mx - : VPseudoUnaryNoMaskRoundingMode, - SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, forceMergeOpRead=true>; - def "_V_" # mx # "_MASK" - : VPseudoUnaryMaskRoundingMode, - RISCVMaskedPseudo, - SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, forceMergeOpRead=true>; + foreach e = SchedSEWSet.val in { + let VLMul = m.value in { + def "_V_" # mx # "_E" # e + : VPseudoUnaryNoMaskRoundingMode, + SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, e, forceMergeOpRead=true>; + def "_V_" # mx # "_E" # e # "_MASK" + : VPseudoUnaryMaskRoundingMode, + RISCVMaskedPseudo, + SchedUnary<"WriteVFRecpV", "ReadVFRecpV", mx, e, forceMergeOpRead=true>; + } } } } @@ -3939,12 +3943,16 @@ class VPatUnaryNoMask : + VReg op2_reg_class, + bit isSEWAware = 0> : Pat<(result_type (!cast(intrinsic_name) (result_type result_reg_class:$merge), (op2_type op2_reg_class:$rs2), VLOpFrag)), - (!cast(inst#"_"#kind#"_"#vlmul.MX) + (!cast( + !if(isSEWAware, + inst#"_"#kind#"_"#vlmul.MX#"_E"#!shl(1, log2sew), + inst#"_"#kind#"_"#vlmul.MX)) (result_type result_reg_class:$merge), (op2_type op2_reg_class:$rs2), GPR:$vl, log2sew, TU_MU)>; @@ -3983,13 +3991,17 @@ class VPatUnaryMask : + VReg op2_reg_class, + bit isSEWAware = 0> : Pat<(result_type (!cast(intrinsic_name#"_mask") (result_type result_reg_class:$merge), (op2_type op2_reg_class:$rs2), (mask_type V0), VLOpFrag, (XLenVT timm:$policy))), - (!cast(inst#"_"#kind#"_"#vlmul.MX#"_MASK") + (!cast( + !if(isSEWAware, + inst#"_"#kind#"_"#vlmul.MX#"_E"#!shl(1, log2sew)#"_MASK", + inst#"_"#kind#"_"#vlmul.MX#"_MASK")) (result_type result_reg_class:$merge), (op2_type op2_reg_class:$rs2), (mask_type V0), GPR:$vl, log2sew, (XLenVT timm:$policy))>; @@ -4681,15 +4693,15 @@ multiclass VPatUnaryV_VF vtilist> { + list vtilist, bit isSEWAware = 0> { foreach vti = vtilist in { let Predicates = GetVTypePredicates.Predicates in { def : VPatUnaryNoMask; + vti.LMul, vti.RegClass, vti.RegClass, isSEWAware>; def : VPatUnaryMask; + vti.LMul, vti.RegClass, vti.RegClass, isSEWAware>; } } } @@ -7175,12 +7187,12 @@ defm : VPatUnaryV_V_RM<"int_riscv_vfsqrt", "PseudoVFSQRT", AllFloatVectors, isSE //===----------------------------------------------------------------------===// // 13.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction //===----------------------------------------------------------------------===// -defm : VPatUnaryV_V<"int_riscv_vfrsqrt7", "PseudoVFRSQRT7", AllFloatVectors>; +defm : VPatUnaryV_V<"int_riscv_vfrsqrt7", "PseudoVFRSQRT7", AllFloatVectors, isSEWAware=1>; //===----------------------------------------------------------------------===// // 13.10. Vector Floating-Point Reciprocal Estimate Instruction //===----------------------------------------------------------------------===// -defm : VPatUnaryV_V_RM<"int_riscv_vfrec7", "PseudoVFREC7", AllFloatVectors>; +defm : VPatUnaryV_V_RM<"int_riscv_vfrec7", "PseudoVFREC7", AllFloatVectors, isSEWAware=1>; //===----------------------------------------------------------------------===// // 13.11. Vector Floating-Point Min/Max Instructions diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index 1dd4afa4ee48..2a13cb4beac1 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -743,6 +743,7 @@ foreach mx = SchedMxListF in { defm "" : LMULSEWWriteResMXSEW<"WriteVFMulF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFMulAddV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVFMulAddF", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFRecpV", [SiFive7VCQ, SiFive7VA], mx, sew, IsWorstCase>; } } } @@ -750,7 +751,6 @@ foreach mx = SchedMxList in { defvar Cycles = SiFive7GetCyclesDefault.c; defvar IsWorstCase = SiFive7IsWorstCaseMX.c; let Latency = 8, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { - defm "" : LMULWriteResMX<"WriteVFRecpV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFCvtIToFV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFCvtFToIV", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; } @@ -1168,7 +1168,7 @@ defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; -defm "" : LMULReadAdvance<"ReadVFRecpV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFRecpV", 0>; defm "" : LMULReadAdvance<"ReadVFMinMaxV", 0>; defm "" : LMULReadAdvance<"ReadVFMinMaxF", 0>; defm "" : LMULReadAdvance<"ReadVFSgnjV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td index f63dcf20e683..80090a002714 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td @@ -510,6 +510,14 @@ foreach mx = SchedMxListF in { } } } +foreach mx = SchedMxListF in { + foreach sew = SchedSEWSet.val in { + defvar LMulLat = SiFiveP600GetLMulCycles.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW.c; + let Latency = 2, ReleaseAtCycles = [LMulLat] in + defm "" : LMULSEWWriteResMXSEW<"WriteVFRecpV", [SiFiveP600VectorArith], mx, sew, IsWorstCase>; + } +} foreach mx = SchedMxList in { defvar LMulLat = SiFiveP600GetLMulCycles.c; defvar IsWorstCase = SiFiveP600IsWorstCaseMX.c; @@ -520,7 +528,6 @@ foreach mx = SchedMxList in { let Latency = 2, ReleaseAtCycles = [LMulLat] in { defm "" : LMULWriteResMX<"WriteVFCmpV", [SiFiveP600VectorArith], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVFCmpF", [SiFiveP600VectorArith], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFRecpV", [SiFiveP600VectorArith], mx, IsWorstCase>; } let Latency = 1, ReleaseAtCycles = [LMulLat] in { defm "" : LMULWriteResMX<"WriteVFSgnjV", [SiFiveP600VectorArith], mx, IsWorstCase>; @@ -958,7 +965,7 @@ defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; -defm "" : LMULReadAdvance<"ReadVFRecpV", 0>; +defm "" : LMULSEWReadAdvance<"ReadVFRecpV", 0>; defm "" : LMULReadAdvance<"ReadVFCmpV", 0>; defm "" : LMULReadAdvance<"ReadVFCmpF", 0>; defm "" : LMULReadAdvance<"ReadVFMinMaxV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td index b82e86e9fcd5..6070482ea175 100644 --- a/llvm/lib/Target/RISCV/RISCVScheduleV.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td @@ -432,7 +432,7 @@ defm "" : LMULSEWSchedWritesFW<"WriteVFWMulAddF">; defm "" : LMULSEWSchedWritesF<"WriteVFSqrtV">; // 13.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction // 13.10. Vector Floating-Point Reciprocal Estimate Instruction -defm "" : LMULSchedWrites<"WriteVFRecpV">; +defm "" : LMULSEWSchedWritesF<"WriteVFRecpV">; // 13.11. Vector Floating-Point MIN/MAX Instructions defm "" : LMULSchedWrites<"WriteVFMinMaxV">; defm "" : LMULSchedWrites<"WriteVFMinMaxF">; @@ -657,7 +657,7 @@ defm "" : LMULSEWSchedReadsFW<"ReadVFWMulAddF">; defm "" : LMULSEWSchedReadsF<"ReadVFSqrtV">; // 13.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction // 13.10. Vector Floating-Point Reciprocal Estimate Instruction -defm "" : LMULSchedReads<"ReadVFRecpV">; +defm "" : LMULSEWSchedReadsF<"ReadVFRecpV">; // 13.11. Vector Floating-Point MIN/MAX Instructions defm "" : LMULSchedReads<"ReadVFMinMaxV">; defm "" : LMULSchedReads<"ReadVFMinMaxF">; @@ -895,7 +895,7 @@ defm "" : LMULSEWWriteResF<"WriteVFMulAddF", []>; defm "" : LMULSEWWriteResFW<"WriteVFWMulAddV", []>; defm "" : LMULSEWWriteResFW<"WriteVFWMulAddF", []>; defm "" : LMULSEWWriteResF<"WriteVFSqrtV", []>; -defm "" : LMULWriteRes<"WriteVFRecpV", []>; +defm "" : LMULSEWWriteResF<"WriteVFRecpV", []>; defm "" : LMULWriteRes<"WriteVFMinMaxV", []>; defm "" : LMULWriteRes<"WriteVFMinMaxF", []>; defm "" : LMULWriteRes<"WriteVFSgnjV", []>; @@ -1051,7 +1051,7 @@ defm "" : LMULSEWReadAdvanceF<"ReadVFMulAddF", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddV", 0>; defm "" : LMULSEWReadAdvanceFW<"ReadVFWMulAddF", 0>; defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; -defm "" : LMULReadAdvance<"ReadVFRecpV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFRecpV", 0>; defm "" : LMULReadAdvance<"ReadVFMinMaxV", 0>; defm "" : LMULReadAdvance<"ReadVFMinMaxF", 0>; defm "" : LMULReadAdvance<"ReadVFSgnjV", 0>; -- GitLab From f4e3226a6c2bd89247192e4aae395a8deb3868b1 Mon Sep 17 00:00:00 2001 From: Xiaoyang Liu Date: Fri, 12 Apr 2024 10:09:05 -0400 Subject: [PATCH 068/464] [libc++][ranges] LWG3736: move_iterator missing disable_sized_sentinel_for specialization (#85611) This pull request implements LWG3736: move_iterator missing disable_sized_sentinel_for specialization. --- libcxx/docs/Status/Cxx23Issues.csv | 2 +- libcxx/include/__iterator/move_iterator.h | 6 ++++ libcxx/include/iterator | 5 +++ .../sized_sentinel.compile.pass.cpp | 32 +++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 libcxx/test/std/iterators/predef.iterators/move.iterators/sized_sentinel.compile.pass.cpp diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index fa82e67ac7db..04f6e23375ac 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -201,7 +201,7 @@ "`3677 `__","Is a cv-qualified ``pair`` specially handled in uses-allocator construction?", "November 2022","|Complete|","18.0","" "`3717 `__","``common_view::end`` should improve ``random_access_range`` case", "November 2022","","","|ranges|" "`3732 `__","``prepend_range`` and ``append_range`` can't be amortized constant time", "November 2022","|Nothing to do|","","|ranges|" -"`3736 `__","``move_iterator`` missing ``disable_sized_sentinel_for`` specialization", "November 2022","","","|ranges|" +"`3736 `__","``move_iterator`` missing ``disable_sized_sentinel_for`` specialization", "November 2022","|Complete|","19.0","|ranges|" "`3737 `__","``take_view::sentinel`` should provide ``operator-``", "November 2022","","","|ranges|" "`3738 `__","Missing preconditions for ``take_view`` constructor", "November 2022","|Complete|","16.0","|ranges|" "`3743 `__","``ranges::to``'s reserve may be ill-formed", "November 2022","","","|ranges|" diff --git a/libcxx/include/__iterator/move_iterator.h b/libcxx/include/__iterator/move_iterator.h index eefd5b374845..6382c947060b 100644 --- a/libcxx/include/__iterator/move_iterator.h +++ b/libcxx/include/__iterator/move_iterator.h @@ -330,6 +330,12 @@ operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterato } #endif // _LIBCPP_STD_VER >= 20 +#if _LIBCPP_STD_VER >= 20 +template + requires(!sized_sentinel_for<_Iter1, _Iter2>) +inline constexpr bool disable_sized_sentinel_for, move_iterator<_Iter2>> = true; +#endif // _LIBCPP_STD_VER >= 20 + template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator<_Iter> make_move_iterator(_Iter __i) { return move_iterator<_Iter>(std::move(__i)); diff --git a/libcxx/include/iterator b/libcxx/include/iterator index 5779bf828711..1b9e7eaf0c1e 100644 --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -475,6 +475,11 @@ constexpr move_iterator operator+( // constexpr in C++17 template // constexpr in C++17 constexpr move_iterator make_move_iterator(const Iterator& i); +template + requires (!sized_sentinel_for) + inline constexpr bool disable_sized_sentinel_for, // since C++20 + move_iterator> = true; + template class move_sentinel { public: diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/sized_sentinel.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/sized_sentinel.compile.pass.cpp new file mode 100644 index 000000000000..cb49086dd680 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/sized_sentinel.compile.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +#include + +#include "test_iterators.h" + +using sized_it = random_access_iterator; +static_assert(std::sized_sentinel_for); +static_assert(std::sized_sentinel_for, std::move_iterator>); + +struct unsized_it { + using value_type = int; + using difference_type = std::ptrdiff_t; + + value_type& operator*() const; + bool operator==(const unsized_it&) const; + difference_type operator-(const unsized_it&) const { return 0; } +}; + +template <> +inline constexpr bool std::disable_sized_sentinel_for = true; + +static_assert(!std::sized_sentinel_for); +static_assert(!std::sized_sentinel_for, std::move_iterator>); -- GitLab From 9d8ccbc1be78fb4ba0ad1c6ead2dc04b24c66668 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Fri, 12 Apr 2024 16:13:54 +0200 Subject: [PATCH 069/464] [lldb][test] Add tests for evaluating local variables whose name clashes with Objective-C types (#87807) Depends on https://github.com/llvm/llvm-project/pull/87767 --- .../objc-builtin-types/TestObjCBuiltinTypes.py | 13 +++++++++++++ .../API/lang/objcxx/objc-builtin-types/main.cpp | 8 +++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py b/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py index 611c73889990..3cdca31b8969 100644 --- a/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py +++ b/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py @@ -13,6 +13,7 @@ class TestObjCBuiltinTypes(TestBase): # Find the line numbers to break inside main(). self.main_source = "main.cpp" self.break_line = line_number(self.main_source, "// Set breakpoint here.") + self.bar_break_line = line_number(self.main_source, "return id + Class") @add_test_categories(["pyapi"]) def test_with_python_api(self): @@ -26,6 +27,11 @@ class TestObjCBuiltinTypes(TestBase): bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line) self.assertTrue(bpt, VALID_BREAKPOINT) + bar_bpt = target.BreakpointCreateByLocation( + self.main_source, self.bar_break_line + ) + self.assertTrue(bar_bpt, VALID_BREAKPOINT) + # Now launch the process, and do not stop at entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) @@ -52,3 +58,10 @@ class TestObjCBuiltinTypes(TestBase): patterns=["\(id\) \$.* = nil"], ) self.expect("expr --language C++ -- id my_id = 0; my_id", error=True) + + lldbutil.continue_to_breakpoint(process, bar_bpt) + + self.expect_expr("id", result_value="12", result_type="int") + self.expect_expr("Class", result_value="15", result_type="int") + self.expect("expr --language Objective-C++ -- id", error=True) + self.expect("expr --language Objective-C++ -- Class", error=True) diff --git a/lldb/test/API/lang/objcxx/objc-builtin-types/main.cpp b/lldb/test/API/lang/objcxx/objc-builtin-types/main.cpp index 6dd8cbc6e9fe..5b35ec0f0b8c 100644 --- a/lldb/test/API/lang/objcxx/objc-builtin-types/main.cpp +++ b/lldb/test/API/lang/objcxx/objc-builtin-types/main.cpp @@ -2,8 +2,14 @@ namespace ns { typedef int id; }; +int bar() { + int id = 12; + int Class = 15; + return id + Class; +} + int main() { ns::id foo = 0; - return foo; // Set breakpoint here. + return foo + bar(); // Set breakpoint here. } -- GitLab From bcf047a4ed9afc49f851156698a6d277ab2c00ea Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Wed, 3 Apr 2024 19:00:17 +0200 Subject: [PATCH 070/464] [ARM][PowerPC] Add regression tests for narrowing load in TargetLowering::SimplifySetCC These test cases show some miscomplies for big-endian when dealing with non byte-sized loads. One part of the problem is that LLVM IR isn't really telling where the padding goes for non byte-sized loads/stores. So currently TargetLowering::SimplifySetCC can't assume anything about it. But the implementation also do not consider that the TypeStoreSize could be larger than the TypeSize, resulting in the offset calculation being wrong for big-endian. Pre-commit for https://github.com/llvm/llvm-project/pull/87646 --- .../CodeGen/ARM/simplifysetcc_narrow_load.ll | 665 ++++++++++++++++++ .../PowerPC/simplifysetcc_narrow_load.ll | 390 ++++++++++ 2 files changed, 1055 insertions(+) create mode 100644 llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll create mode 100644 llvm/test/CodeGen/PowerPC/simplifysetcc_narrow_load.ll diff --git a/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll b/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll new file mode 100644 index 000000000000..2cba4b46f9a8 --- /dev/null +++ b/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll @@ -0,0 +1,665 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -O1 -mtriple arm -o - %s | FileCheck --check-prefix CHECK-LE %s +; RUN: llc -O1 -mtriple armv7 -o - %s | FileCheck --check-prefix CHECK-V7-LE %s +; RUN: llc -O1 -mtriple armeb -o - %s | FileCheck --check-prefix CHECK-BE %s +; RUN: llc -O1 -mtriple armv7eb -o - %s | FileCheck --check-prefix CHECK-V7-BE %s + +; A collection of regression tests to verify the load-narrowing part of +; TargetLowering::SimplifySetCC (and/or other similar rewrites such as +; combining AND+LOAD into ZEXTLOAD). +; +; Using both arm and armv7 to show that alignment restrictions are +; considered for the narrowed load (armv7 is a bit more relaxed when it +; comes to unaligned memory accesses). + +;-------------------------------------------------------------------------- +; Test non byte-sized types. +; +; As long as LLVM IR isn't defining where the padding goes we can't really +; optimize these (without adding a target lowering hook that can inform +; ISel about which bits are padding). +; -------------------------------------------------------------------------- + +define i1 @test_129_15_0(ptr %y) { +; CHECK-LE-LABEL: test_129_15_0: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrh r0, [r0] +; CHECK-LE-NEXT: mov r1, #255 +; CHECK-LE-NEXT: orr r1, r1, #32512 +; CHECK-LE-NEXT: ands r0, r0, r1 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_129_15_0: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrh r0, [r0] +; CHECK-V7-LE-NEXT: bfc r0, #15, #17 +; CHECK-V7-LE-NEXT: cmp r0, #0 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_129_15_0: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrh r0, [r0, #14] +; CHECK-BE-NEXT: mov r1, #255 +; CHECK-BE-NEXT: orr r1, r1, #32512 +; CHECK-BE-NEXT: ands r0, r0, r1 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_129_15_0: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrh r0, [r0, #14] +; CHECK-V7-BE-NEXT: bfc r0, #15, #17 +; CHECK-V7-BE-NEXT: cmp r0, #0 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i129, ptr %y + %b = and i129 %a, u0x7fff + %cmp = icmp ne i129 %b, 0 + ret i1 %cmp +} + +define i1 @test_126_20_4(ptr %y) { +; CHECK-LE-LABEL: test_126_20_4: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldr r0, [r0] +; CHECK-LE-NEXT: mvn r1, #15 +; CHECK-LE-NEXT: sub r1, r1, #-16777216 +; CHECK-LE-NEXT: ands r0, r0, r1 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_126_20_4: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldr r0, [r0] +; CHECK-V7-LE-NEXT: movw r1, #65520 +; CHECK-V7-LE-NEXT: movt r1, #255 +; CHECK-V7-LE-NEXT: ands r0, r0, r1 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_126_20_4: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldr r0, [r0, #12] +; CHECK-BE-NEXT: mvn r1, #15 +; CHECK-BE-NEXT: sub r1, r1, #-16777216 +; CHECK-BE-NEXT: ands r0, r0, r1 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_126_20_4: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldr r0, [r0, #12] +; CHECK-V7-BE-NEXT: movw r1, #65520 +; CHECK-V7-BE-NEXT: movt r1, #255 +; CHECK-V7-BE-NEXT: ands r0, r0, r1 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i126, ptr %y + %b = and i126 %a, u0xfffff0 + %cmp = icmp ne i126 %b, 0 + ret i1 %cmp +} + +define i1 @test_33_8_0(ptr %y) { +; CHECK-LE-LABEL: test_33_8_0: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrb r0, [r0] +; CHECK-LE-NEXT: cmp r0, #0 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_33_8_0: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrb r0, [r0] +; CHECK-V7-LE-NEXT: cmp r0, #0 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_33_8_0: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrb r0, [r0, #3] +; CHECK-BE-NEXT: cmp r0, #0 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_33_8_0: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrb r0, [r0, #3] +; CHECK-V7-BE-NEXT: cmp r0, #0 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i33, ptr %y + %b = and i33 %a, u0xff + %cmp = icmp ne i33 %b, 0 + ret i1 %cmp +} + +define i1 @test_33_1_32(ptr %y) { +; CHECK-LE-LABEL: test_33_1_32: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrb r0, [r0, #4] +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_33_1_32: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrb r0, [r0, #4] +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_33_1_32: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldr r0, [r0] +; CHECK-BE-NEXT: lsr r0, r0, #24 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_33_1_32: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldr r0, [r0] +; CHECK-V7-BE-NEXT: lsr r0, r0, #24 +; CHECK-V7-BE-NEXT: bx lr + %a = load i33, ptr %y + %b = and i33 %a, u0x100000000 + %cmp = icmp ne i33 %b, 0 + ret i1 %cmp +} + +define i1 @test_33_1_31(ptr %y) { +; CHECK-LE-LABEL: test_33_1_31: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrb r0, [r0, #3] +; CHECK-LE-NEXT: lsr r0, r0, #7 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_33_1_31: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrb r0, [r0, #3] +; CHECK-V7-LE-NEXT: lsr r0, r0, #7 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_33_1_31: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrb r0, [r0] +; CHECK-BE-NEXT: lsr r0, r0, #7 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_33_1_31: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrb r0, [r0] +; CHECK-V7-BE-NEXT: lsr r0, r0, #7 +; CHECK-V7-BE-NEXT: bx lr + %a = load i33, ptr %y + %b = and i33 %a, u0x80000000 + %cmp = icmp ne i33 %b, 0 + ret i1 %cmp +} + +define i1 @test_33_1_0(ptr %y) { +; CHECK-LE-LABEL: test_33_1_0: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrb r0, [r0] +; CHECK-LE-NEXT: and r0, r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_33_1_0: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrb r0, [r0] +; CHECK-V7-LE-NEXT: and r0, r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_33_1_0: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrb r0, [r0, #3] +; CHECK-BE-NEXT: and r0, r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_33_1_0: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrb r0, [r0, #3] +; CHECK-V7-BE-NEXT: and r0, r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i33, ptr %y + %b = and i33 %a, u0x1 + %cmp = icmp ne i33 %b, 0 + ret i1 %cmp +} + +;-------------------------------------------------------------------------- +; Test byte-sized types. +;-------------------------------------------------------------------------- + + +define i1 @test_128_20_4(ptr %y) { +; CHECK-LE-LABEL: test_128_20_4: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldr r0, [r0] +; CHECK-LE-NEXT: mvn r1, #15 +; CHECK-LE-NEXT: sub r1, r1, #-16777216 +; CHECK-LE-NEXT: ands r0, r0, r1 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_128_20_4: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldr r0, [r0] +; CHECK-V7-LE-NEXT: movw r1, #65520 +; CHECK-V7-LE-NEXT: movt r1, #255 +; CHECK-V7-LE-NEXT: ands r0, r0, r1 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_128_20_4: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldr r0, [r0, #12] +; CHECK-BE-NEXT: mvn r1, #15 +; CHECK-BE-NEXT: sub r1, r1, #-16777216 +; CHECK-BE-NEXT: ands r0, r0, r1 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_128_20_4: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldr r0, [r0, #12] +; CHECK-V7-BE-NEXT: movw r1, #65520 +; CHECK-V7-BE-NEXT: movt r1, #255 +; CHECK-V7-BE-NEXT: ands r0, r0, r1 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i128, ptr %y + %b = and i128 %a, u0xfffff0 + %cmp = icmp ne i128 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_16_0(ptr %y) { +; CHECK-LE-LABEL: test_48_16_0: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrh r0, [r0] +; CHECK-LE-NEXT: cmp r0, #0 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_48_16_0: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrh r0, [r0] +; CHECK-V7-LE-NEXT: cmp r0, #0 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_48_16_0: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrh r0, [r0, #4] +; CHECK-BE-NEXT: cmp r0, #0 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_48_16_0: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrh r0, [r0, #4] +; CHECK-V7-BE-NEXT: cmp r0, #0 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i48, ptr %y + %b = and i48 %a, u0xffff + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_16_8(ptr %y) { +; CHECK-LE-LABEL: test_48_16_8: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrh r0, [r0, #1] +; CHECK-LE-NEXT: cmp r0, #0 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_48_16_8: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrh r0, [r0, #1] +; CHECK-V7-LE-NEXT: cmp r0, #0 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_48_16_8: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrh r0, [r0, #3] +; CHECK-BE-NEXT: cmp r0, #0 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_48_16_8: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrh r0, [r0, #3] +; CHECK-V7-BE-NEXT: cmp r0, #0 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i48, ptr %y + %b = and i48 %a, u0xffff00 + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_16_16(ptr %y) { +; CHECK-LE-LABEL: test_48_16_16: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrh r0, [r0, #2] +; CHECK-LE-NEXT: cmp r0, #0 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_48_16_16: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrh r0, [r0, #2] +; CHECK-V7-LE-NEXT: cmp r0, #0 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_48_16_16: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrh r0, [r0, #2] +; CHECK-BE-NEXT: cmp r0, #0 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_48_16_16: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrh r0, [r0, #2] +; CHECK-V7-BE-NEXT: cmp r0, #0 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i48, ptr %y + %b = and i48 %a, u0xffff0000 + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_16_32(ptr %y) { +; CHECK-LE-LABEL: test_48_16_32: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrh r0, [r0, #4] +; CHECK-LE-NEXT: cmp r0, #0 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_48_16_32: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrh r0, [r0, #4] +; CHECK-V7-LE-NEXT: cmp r0, #0 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_48_16_32: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrh r0, [r0] +; CHECK-BE-NEXT: cmp r0, #0 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_48_16_32: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrh r0, [r0] +; CHECK-V7-BE-NEXT: cmp r0, #0 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i48, ptr %y + %b = and i48 %a, u0xffff00000000 + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_17_0(ptr %y) { +; CHECK-LE-LABEL: test_48_17_0: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldr r0, [r0] +; CHECK-LE-NEXT: ldr r1, .LCPI11_0 +; CHECK-LE-NEXT: ands r0, r0, r1 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; CHECK-LE-NEXT: .p2align 2 +; CHECK-LE-NEXT: @ %bb.1: +; CHECK-LE-NEXT: .LCPI11_0: +; CHECK-LE-NEXT: .long 131071 @ 0x1ffff +; +; CHECK-V7-LE-LABEL: test_48_17_0: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldr r0, [r0] +; CHECK-V7-LE-NEXT: bfc r0, #17, #15 +; CHECK-V7-LE-NEXT: cmp r0, #0 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_48_17_0: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldr r1, [r0] +; CHECK-BE-NEXT: ldrh r0, [r0, #4] +; CHECK-BE-NEXT: orr r0, r0, r1, lsl #16 +; CHECK-BE-NEXT: ldr r1, .LCPI11_0 +; CHECK-BE-NEXT: ands r0, r0, r1 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; CHECK-BE-NEXT: .p2align 2 +; CHECK-BE-NEXT: @ %bb.1: +; CHECK-BE-NEXT: .LCPI11_0: +; CHECK-BE-NEXT: .long 131071 @ 0x1ffff +; +; CHECK-V7-BE-LABEL: test_48_17_0: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldr r1, [r0] +; CHECK-V7-BE-NEXT: ldrh r0, [r0, #4] +; CHECK-V7-BE-NEXT: orr r0, r0, r1, lsl #16 +; CHECK-V7-BE-NEXT: bfc r0, #17, #15 +; CHECK-V7-BE-NEXT: cmp r0, #0 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i48, ptr %y + %b = and i48 %a, u0x1ffff + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_40_16_0(ptr %y) { +; CHECK-LE-LABEL: test_40_16_0: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrh r0, [r0] +; CHECK-LE-NEXT: cmp r0, #0 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_40_16_0: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrh r0, [r0] +; CHECK-V7-LE-NEXT: cmp r0, #0 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_40_16_0: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrh r0, [r0, #3] +; CHECK-BE-NEXT: cmp r0, #0 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_40_16_0: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrh r0, [r0, #3] +; CHECK-V7-BE-NEXT: cmp r0, #0 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i40, ptr %y + %b = and i40 %a, u0xffff + %cmp = icmp ne i40 %b, 0 + ret i1 %cmp +} + +define i1 @test_40_1_32(ptr %y) { +; CHECK-LE-LABEL: test_40_1_32: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrb r0, [r0, #4] +; CHECK-LE-NEXT: and r0, r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_40_1_32: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrb r0, [r0, #4] +; CHECK-V7-LE-NEXT: and r0, r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_40_1_32: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldr r0, [r0] +; CHECK-BE-NEXT: mov r1, #1 +; CHECK-BE-NEXT: and r0, r1, r0, lsr #24 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_40_1_32: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldr r0, [r0] +; CHECK-V7-BE-NEXT: ubfx r0, r0, #24, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i40, ptr %y + %b = and i40 %a, u0x100000000 + %cmp = icmp ne i40 %b, 0 + ret i1 %cmp +} + +define i1 @test_24_16_0(ptr %y) { +; CHECK-LE-LABEL: test_24_16_0: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrh r0, [r0] +; CHECK-LE-NEXT: cmp r0, #0 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_24_16_0: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrh r0, [r0] +; CHECK-V7-LE-NEXT: cmp r0, #0 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_24_16_0: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrh r0, [r0, #1] +; CHECK-BE-NEXT: cmp r0, #0 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_24_16_0: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrh r0, [r0, #1] +; CHECK-V7-BE-NEXT: cmp r0, #0 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i24, ptr %y + %b = and i24 %a, u0xffff + %cmp = icmp ne i24 %b, 0 + ret i1 %cmp +} + +define i1 @test_24_8_8(ptr %y) { +; CHECK-LE-LABEL: test_24_8_8: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrb r0, [r0, #1] +; CHECK-LE-NEXT: lsls r0, r0, #8 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_24_8_8: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrb r0, [r0, #1] +; CHECK-V7-LE-NEXT: lsls r0, r0, #8 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_24_8_8: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrb r0, [r0, #1] +; CHECK-BE-NEXT: lsls r0, r0, #8 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_24_8_8: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrb r0, [r0, #1] +; CHECK-V7-BE-NEXT: lsls r0, r0, #8 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i24, ptr %y + %b = and i24 %a, u0xff00 + %cmp = icmp ne i24 %b, 0 + ret i1 %cmp +} + +define i1 @test_24_8_12(ptr %y) { +; CHECK-LE-LABEL: test_24_8_12: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrb r1, [r0, #2] +; CHECK-LE-NEXT: ldrh r0, [r0] +; CHECK-LE-NEXT: orr r0, r0, r1, lsl #16 +; CHECK-LE-NEXT: ands r0, r0, #1044480 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_24_8_12: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrb r1, [r0, #2] +; CHECK-V7-LE-NEXT: ldrh r0, [r0] +; CHECK-V7-LE-NEXT: orr r0, r0, r1, lsl #16 +; CHECK-V7-LE-NEXT: ands r0, r0, #1044480 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_24_8_12: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrh r0, [r0] +; CHECK-BE-NEXT: mov r1, #1044480 +; CHECK-BE-NEXT: ands r0, r1, r0, lsl #8 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_24_8_12: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrh r0, [r0] +; CHECK-V7-BE-NEXT: mov r1, #1044480 +; CHECK-V7-BE-NEXT: ands r0, r1, r0, lsl #8 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i24, ptr %y + %b = and i24 %a, u0xff000 + %cmp = icmp ne i24 %b, 0 + ret i1 %cmp +} + +define i1 @test_24_8_16(ptr %y) { +; CHECK-LE-LABEL: test_24_8_16: +; CHECK-LE: @ %bb.0: +; CHECK-LE-NEXT: ldrb r0, [r0, #2] +; CHECK-LE-NEXT: lsls r0, r0, #16 +; CHECK-LE-NEXT: movne r0, #1 +; CHECK-LE-NEXT: mov pc, lr +; +; CHECK-V7-LE-LABEL: test_24_8_16: +; CHECK-V7-LE: @ %bb.0: +; CHECK-V7-LE-NEXT: ldrb r0, [r0, #2] +; CHECK-V7-LE-NEXT: lsls r0, r0, #16 +; CHECK-V7-LE-NEXT: movwne r0, #1 +; CHECK-V7-LE-NEXT: bx lr +; +; CHECK-BE-LABEL: test_24_8_16: +; CHECK-BE: @ %bb.0: +; CHECK-BE-NEXT: ldrb r0, [r0] +; CHECK-BE-NEXT: lsls r0, r0, #16 +; CHECK-BE-NEXT: movne r0, #1 +; CHECK-BE-NEXT: mov pc, lr +; +; CHECK-V7-BE-LABEL: test_24_8_16: +; CHECK-V7-BE: @ %bb.0: +; CHECK-V7-BE-NEXT: ldrb r0, [r0] +; CHECK-V7-BE-NEXT: lsls r0, r0, #16 +; CHECK-V7-BE-NEXT: movwne r0, #1 +; CHECK-V7-BE-NEXT: bx lr + %a = load i24, ptr %y + %b = and i24 %a, u0xff0000 + %cmp = icmp ne i24 %b, 0 + ret i1 %cmp +} diff --git a/llvm/test/CodeGen/PowerPC/simplifysetcc_narrow_load.ll b/llvm/test/CodeGen/PowerPC/simplifysetcc_narrow_load.ll new file mode 100644 index 000000000000..1a03423fe6ae --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/simplifysetcc_narrow_load.ll @@ -0,0 +1,390 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -O1 -mtriple ppc32le -o - %s | FileCheck --check-prefix CHECK-LE %s +; RUN: llc -O1 -mtriple ppc32 -o - %s | FileCheck --check-prefix CHECK-BE %s + +; A collection of regression tests to verify the load-narrowing part of +; TargetLowering::SimplifySetCC (and/or other similar rewrites such as +; combining AND+LOAD into ZEXTLOAD). + + +;-------------------------------------------------------------------------- +; Test non byte-sized types. +; +; As long as LLVM IR isn't defining where the padding goes we can't really +; optimize these (without adding a target lowering hook that can inform +; ISel about which bits are padding). +; -------------------------------------------------------------------------- + +define i1 @test_129_15_0(ptr %y) { +; CHECK-LE-LABEL: test_129_15_0: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lhz 3, 0(3) +; CHECK-LE-NEXT: clrlwi 3, 3, 17 +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_129_15_0: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lhz 3, 14(3) +; CHECK-BE-NEXT: clrlwi 3, 3, 17 +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i129, ptr %y + %b = and i129 %a, u0x7fff + %cmp = icmp ne i129 %b, 0 + ret i1 %cmp +} + +define i1 @test_126_20_4(ptr %y) { +; CHECK-LE-LABEL: test_126_20_4: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lwz 3, 0(3) +; CHECK-LE-NEXT: rlwinm 3, 3, 0, 8, 27 +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_126_20_4: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lwz 3, 12(3) +; CHECK-BE-NEXT: rlwinm 3, 3, 0, 8, 27 +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i126, ptr %y + %b = and i126 %a, u0xfffff0 + %cmp = icmp ne i126 %b, 0 + ret i1 %cmp +} + +define i1 @test_33_8_0(ptr %y) { +; CHECK-LE-LABEL: test_33_8_0: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lbz 3, 0(3) +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_33_8_0: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lbz 3, 3(3) +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i33, ptr %y + %b = and i33 %a, u0xff + %cmp = icmp ne i33 %b, 0 + ret i1 %cmp +} + +define i1 @test_33_1_32(ptr %y) { +; CHECK-LE-LABEL: test_33_1_32: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lbz 3, 4(3) +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_33_1_32: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lwz 3, 0(3) +; CHECK-BE-NEXT: srwi 3, 3, 24 +; CHECK-BE-NEXT: blr + %a = load i33, ptr %y + %b = and i33 %a, u0x100000000 + %cmp = icmp ne i33 %b, 0 + ret i1 %cmp +} + +define i1 @test_33_1_31(ptr %y) { +; CHECK-LE-LABEL: test_33_1_31: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lbz 3, 3(3) +; CHECK-LE-NEXT: srwi 3, 3, 7 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_33_1_31: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lbz 3, 0(3) +; CHECK-BE-NEXT: srwi 3, 3, 7 +; CHECK-BE-NEXT: blr + %a = load i33, ptr %y + %b = and i33 %a, u0x80000000 + %cmp = icmp ne i33 %b, 0 + ret i1 %cmp +} + +define i1 @test_33_1_0(ptr %y) { +; CHECK-LE-LABEL: test_33_1_0: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lbz 3, 0(3) +; CHECK-LE-NEXT: clrlwi 3, 3, 31 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_33_1_0: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lbz 3, 3(3) +; CHECK-BE-NEXT: clrlwi 3, 3, 31 +; CHECK-BE-NEXT: blr + %a = load i33, ptr %y + %b = and i33 %a, u0x1 + %cmp = icmp ne i33 %b, 0 + ret i1 %cmp +} + +;-------------------------------------------------------------------------- +; Test byte-sized types. +;-------------------------------------------------------------------------- + + +define i1 @test_128_20_4(ptr %y) { +; CHECK-LE-LABEL: test_128_20_4: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lwz 3, 0(3) +; CHECK-LE-NEXT: rlwinm 3, 3, 0, 8, 27 +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_128_20_4: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lwz 3, 12(3) +; CHECK-BE-NEXT: rlwinm 3, 3, 0, 8, 27 +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i128, ptr %y + %b = and i128 %a, u0xfffff0 + %cmp = icmp ne i128 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_16_0(ptr %y) { +; CHECK-LE-LABEL: test_48_16_0: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lhz 3, 0(3) +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_48_16_0: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lhz 3, 4(3) +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i48, ptr %y + %b = and i48 %a, u0xffff + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_16_8(ptr %y) { +; CHECK-LE-LABEL: test_48_16_8: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lhz 3, 1(3) +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_48_16_8: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lhz 3, 3(3) +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i48, ptr %y + %b = and i48 %a, u0xffff00 + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_16_16(ptr %y) { +; CHECK-LE-LABEL: test_48_16_16: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lhz 3, 2(3) +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_48_16_16: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lhz 3, 2(3) +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i48, ptr %y + %b = and i48 %a, u0xffff0000 + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_16_32(ptr %y) { +; CHECK-LE-LABEL: test_48_16_32: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lhz 3, 4(3) +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_48_16_32: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lhz 3, 0(3) +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i48, ptr %y + %b = and i48 %a, u0xffff00000000 + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_48_17_0(ptr %y) { +; CHECK-LE-LABEL: test_48_17_0: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lwz 3, 0(3) +; CHECK-LE-NEXT: clrlwi 3, 3, 15 +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_48_17_0: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lhz 4, 4(3) +; CHECK-BE-NEXT: lwz 3, 0(3) +; CHECK-BE-NEXT: clrlwi 4, 4, 16 +; CHECK-BE-NEXT: rlwimi 4, 3, 16, 15, 15 +; CHECK-BE-NEXT: addic 3, 4, -1 +; CHECK-BE-NEXT: subfe 3, 3, 4 +; CHECK-BE-NEXT: blr + %a = load i48, ptr %y + %b = and i48 %a, u0x1ffff + %cmp = icmp ne i48 %b, 0 + ret i1 %cmp +} + +define i1 @test_40_16_0(ptr %y) { +; CHECK-LE-LABEL: test_40_16_0: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lhz 3, 0(3) +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_40_16_0: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lhz 3, 3(3) +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i40, ptr %y + %b = and i40 %a, u0xffff + %cmp = icmp ne i40 %b, 0 + ret i1 %cmp +} + +define i1 @test_40_1_32(ptr %y) { +; CHECK-LE-LABEL: test_40_1_32: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lbz 3, 4(3) +; CHECK-LE-NEXT: clrlwi 3, 3, 31 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_40_1_32: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lwz 3, 0(3) +; CHECK-BE-NEXT: rlwinm 3, 3, 8, 31, 31 +; CHECK-BE-NEXT: blr + %a = load i40, ptr %y + %b = and i40 %a, u0x100000000 + %cmp = icmp ne i40 %b, 0 + ret i1 %cmp +} + +define i1 @test_24_16_0(ptr %y) { +; CHECK-LE-LABEL: test_24_16_0: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lhz 3, 0(3) +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_24_16_0: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lhz 3, 1(3) +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i24, ptr %y + %b = and i24 %a, u0xffff + %cmp = icmp ne i24 %b, 0 + ret i1 %cmp +} + +define i1 @test_24_8_8(ptr %y) { +; CHECK-LE-LABEL: test_24_8_8: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lbz 3, 1(3) +; CHECK-LE-NEXT: slwi 3, 3, 8 +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_24_8_8: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lbz 3, 1(3) +; CHECK-BE-NEXT: slwi 3, 3, 8 +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i24, ptr %y + %b = and i24 %a, u0xff00 + %cmp = icmp ne i24 %b, 0 + ret i1 %cmp +} + +define i1 @test_24_8_12(ptr %y) { +; CHECK-LE-LABEL: test_24_8_12: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lhz 4, 0(3) +; CHECK-LE-NEXT: lbz 3, 2(3) +; CHECK-LE-NEXT: rlwinm 4, 4, 0, 16, 19 +; CHECK-LE-NEXT: rlwimi 4, 3, 16, 12, 15 +; CHECK-LE-NEXT: addic 3, 4, -1 +; CHECK-LE-NEXT: subfe 3, 3, 4 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_24_8_12: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lhz 3, 0(3) +; CHECK-BE-NEXT: rlwinm 3, 3, 8, 12, 19 +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i24, ptr %y + %b = and i24 %a, u0xff000 + %cmp = icmp ne i24 %b, 0 + ret i1 %cmp +} + +define i1 @test_24_8_16(ptr %y) { +; CHECK-LE-LABEL: test_24_8_16: +; CHECK-LE: # %bb.0: +; CHECK-LE-NEXT: lbz 3, 2(3) +; CHECK-LE-NEXT: slwi 3, 3, 16 +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: test_24_8_16: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: lbz 3, 0(3) +; CHECK-BE-NEXT: slwi 3, 3, 16 +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 +; CHECK-BE-NEXT: blr + %a = load i24, ptr %y + %b = and i24 %a, u0xff0000 + %cmp = icmp ne i24 %b, 0 + ret i1 %cmp +} -- GitLab From 33e6b488beda80dddb68016a132ee1f0a3c04aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Pettersson?= Date: Fri, 12 Apr 2024 16:18:12 +0200 Subject: [PATCH 071/464] [SelectionDAG] Fix and improve TargetLowering::SimplifySetCC (#87646) The load narrowing part of TargetLowering::SimplifySetCC is updated according to this: 1) The offset calculation (for big endian) did not work properly for non byte-sized types. This is basically solved by an early exit if the memory type isn't byte-sized. But the code is also corrected to use the store size when calculating the offset. 2) To still allow some optimizations for non-byte-sized types the TargetLowering::isPaddedAtMostSignificantBitsWhenStored hook is added. By default it assumes that scalar integer types are padded starting at the most significant bits, if the type needs padding when being stored to memory. 3) Allow optimizing when isPaddedAtMostSignificantBitsWhenStored is true, as that hook makes it possible for TargetLowering to know how the non byte-sized value is aligned in memory. 4) Update the algorithm to always search for a narrowed load with a power-of-2 byte-sized type. In the past the algorithm started with the the width of the original load, and then divided it by two for each iteration. But for a type such as i48 that would just end up trying to narrow the load into a i24 or i12 load, and then we would fail sooner or later due to not finding a newVT that fulfilled newVT.isRound(). With this new approach we can narrow the i48 load into either an i8, i16 or i32 load. By checking if such a load is allowed (e.g. alignment wise) for any "multiple of 8 offset", then we can find more opportunities for the optimization to trigger. So even for a byte-sized type such as i32 we may now end up narrowing the load into loading the 16 bits starting at offset 8 (if that is allowed by the target). The old algorithm did not even consider that case. 5) Also start using getObjectPtrOffset instead of getMemBasePlusOffset when creating the new ptr. This way we get "nsw" on the add. --- llvm/include/llvm/CodeGen/TargetLowering.h | 7 ++ .../CodeGen/SelectionDAG/TargetLowering.cpp | 68 +++++++++++-------- .../CodeGen/ARM/simplifysetcc_narrow_load.ll | 33 +++++---- .../PowerPC/simplifysetcc_narrow_load.ll | 38 ++++------- 4 files changed, 79 insertions(+), 67 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index a4dc09744618..980d75ad91a0 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -1804,6 +1804,13 @@ public: /// where the sext is redundant, and use x directly. virtual bool shouldRemoveRedundantExtend(SDValue Op) const { return true; } + /// Indicates if any padding is guaranteed to go at the most significant bits + /// when storing the type to memory and the type size isn't equal to the store + /// size. + bool isPaddedAtMostSignificantBitsWhenStored(EVT VT) const { + return VT.isScalarInteger() && !VT.isByteSized(); + } + /// When splitting a value of the specified type into parts, does the Lo /// or Hi part come first? This usually follows the endianness, except /// for ppcf128, where the Hi part always comes first. diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 409d66adfd67..4939976b8e28 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -4621,7 +4621,10 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, LoadSDNode *Lod = cast(N0.getOperand(0)); APInt bestMask; unsigned bestWidth = 0, bestOffset = 0; - if (Lod->isSimple() && Lod->isUnindexed()) { + if (Lod->isSimple() && Lod->isUnindexed() && + (Lod->getMemoryVT().isByteSized() || + isPaddedAtMostSignificantBitsWhenStored(Lod->getMemoryVT()))) { + unsigned memWidth = Lod->getMemoryVT().getStoreSizeInBits(); unsigned origWidth = N0.getValueSizeInBits(); unsigned maskWidth = origWidth; // We can narrow (e.g.) 16-bit extending loads on 32-bit target to @@ -4629,40 +4632,51 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, if (Lod->getExtensionType() != ISD::NON_EXTLOAD) origWidth = Lod->getMemoryVT().getSizeInBits(); const APInt &Mask = N0.getConstantOperandAPInt(1); - for (unsigned width = origWidth / 2; width>=8; width /= 2) { + // Only consider power-of-2 widths (and at least one byte) as candiates + // for the narrowed load. + for (unsigned width = 8; width < origWidth; width *= 2) { + EVT newVT = EVT::getIntegerVT(*DAG.getContext(), width); + if (!shouldReduceLoadWidth(Lod, ISD::NON_EXTLOAD, newVT)) + continue; APInt newMask = APInt::getLowBitsSet(maskWidth, width); - for (unsigned offset=0; offsetgetAlign(), ptrOffset / 8); + if (allowsMemoryAccess( + *DAG.getContext(), Layout, newVT, Lod->getAddressSpace(), + NewAlign, Lod->getMemOperand()->getFlags(), &IsFast) && + IsFast) { + bestOffset = ptrOffset / 8; + bestMask = Mask.lshr(offset); + bestWidth = width; + break; + } } - newMask <<= width; + newMask <<= 8; } + if (bestWidth) + break; } } if (bestWidth) { EVT newVT = EVT::getIntegerVT(*DAG.getContext(), bestWidth); - if (newVT.isRound() && - shouldReduceLoadWidth(Lod, ISD::NON_EXTLOAD, newVT)) { - SDValue Ptr = Lod->getBasePtr(); - if (bestOffset != 0) - Ptr = DAG.getMemBasePlusOffset(Ptr, TypeSize::getFixed(bestOffset), - dl); - SDValue NewLoad = - DAG.getLoad(newVT, dl, Lod->getChain(), Ptr, - Lod->getPointerInfo().getWithOffset(bestOffset), - Lod->getOriginalAlign()); - return DAG.getSetCC(dl, VT, - DAG.getNode(ISD::AND, dl, newVT, NewLoad, - DAG.getConstant(bestMask.trunc(bestWidth), - dl, newVT)), - DAG.getConstant(0LL, dl, newVT), Cond); - } + SDValue Ptr = Lod->getBasePtr(); + if (bestOffset != 0) + Ptr = DAG.getObjectPtrOffset(dl, Ptr, TypeSize::getFixed(bestOffset)); + SDValue NewLoad = + DAG.getLoad(newVT, dl, Lod->getChain(), Ptr, + Lod->getPointerInfo().getWithOffset(bestOffset), + Lod->getOriginalAlign()); + SDValue And = + DAG.getNode(ISD::AND, dl, newVT, NewLoad, + DAG.getConstant(bestMask.trunc(bestWidth), dl, newVT)); + return DAG.getSetCC(dl, VT, And, DAG.getConstant(0LL, dl, newVT), Cond); } } diff --git a/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll b/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll index 2cba4b46f9a8..838da59f9e41 100644 --- a/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll +++ b/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll @@ -40,7 +40,9 @@ define i1 @test_129_15_0(ptr %y) { ; ; CHECK-BE-LABEL: test_129_15_0: ; CHECK-BE: @ %bb.0: -; CHECK-BE-NEXT: ldrh r0, [r0, #14] +; CHECK-BE-NEXT: ldr r1, [r0, #12] +; CHECK-BE-NEXT: ldrb r0, [r0, #16] +; CHECK-BE-NEXT: orr r0, r0, r1, lsl #8 ; CHECK-BE-NEXT: mov r1, #255 ; CHECK-BE-NEXT: orr r1, r1, #32512 ; CHECK-BE-NEXT: ands r0, r0, r1 @@ -49,7 +51,7 @@ define i1 @test_129_15_0(ptr %y) { ; ; CHECK-V7-BE-LABEL: test_129_15_0: ; CHECK-V7-BE: @ %bb.0: -; CHECK-V7-BE-NEXT: ldrh r0, [r0, #14] +; CHECK-V7-BE-NEXT: ldrh r0, [r0, #15] ; CHECK-V7-BE-NEXT: bfc r0, #15, #17 ; CHECK-V7-BE-NEXT: cmp r0, #0 ; CHECK-V7-BE-NEXT: movwne r0, #1 @@ -119,14 +121,14 @@ define i1 @test_33_8_0(ptr %y) { ; ; CHECK-BE-LABEL: test_33_8_0: ; CHECK-BE: @ %bb.0: -; CHECK-BE-NEXT: ldrb r0, [r0, #3] +; CHECK-BE-NEXT: ldrb r0, [r0, #4] ; CHECK-BE-NEXT: cmp r0, #0 ; CHECK-BE-NEXT: movne r0, #1 ; CHECK-BE-NEXT: mov pc, lr ; ; CHECK-V7-BE-LABEL: test_33_8_0: ; CHECK-V7-BE: @ %bb.0: -; CHECK-V7-BE-NEXT: ldrb r0, [r0, #3] +; CHECK-V7-BE-NEXT: ldrb r0, [r0, #4] ; CHECK-V7-BE-NEXT: cmp r0, #0 ; CHECK-V7-BE-NEXT: movwne r0, #1 ; CHECK-V7-BE-NEXT: bx lr @@ -179,13 +181,13 @@ define i1 @test_33_1_31(ptr %y) { ; ; CHECK-BE-LABEL: test_33_1_31: ; CHECK-BE: @ %bb.0: -; CHECK-BE-NEXT: ldrb r0, [r0] +; CHECK-BE-NEXT: ldrb r0, [r0, #1] ; CHECK-BE-NEXT: lsr r0, r0, #7 ; CHECK-BE-NEXT: mov pc, lr ; ; CHECK-V7-BE-LABEL: test_33_1_31: ; CHECK-V7-BE: @ %bb.0: -; CHECK-V7-BE-NEXT: ldrb r0, [r0] +; CHECK-V7-BE-NEXT: ldrb r0, [r0, #1] ; CHECK-V7-BE-NEXT: lsr r0, r0, #7 ; CHECK-V7-BE-NEXT: bx lr %a = load i33, ptr %y @@ -209,13 +211,13 @@ define i1 @test_33_1_0(ptr %y) { ; ; CHECK-BE-LABEL: test_33_1_0: ; CHECK-BE: @ %bb.0: -; CHECK-BE-NEXT: ldrb r0, [r0, #3] +; CHECK-BE-NEXT: ldrb r0, [r0, #4] ; CHECK-BE-NEXT: and r0, r0, #1 ; CHECK-BE-NEXT: mov pc, lr ; ; CHECK-V7-BE-LABEL: test_33_1_0: ; CHECK-V7-BE: @ %bb.0: -; CHECK-V7-BE-NEXT: ldrb r0, [r0, #3] +; CHECK-V7-BE-NEXT: ldrb r0, [r0, #4] ; CHECK-V7-BE-NEXT: and r0, r0, #1 ; CHECK-V7-BE-NEXT: bx lr %a = load i33, ptr %y @@ -309,7 +311,7 @@ define i1 @test_48_16_8(ptr %y) { ; CHECK-LE-LABEL: test_48_16_8: ; CHECK-LE: @ %bb.0: ; CHECK-LE-NEXT: ldrh r0, [r0, #1] -; CHECK-LE-NEXT: cmp r0, #0 +; CHECK-LE-NEXT: lsls r0, r0, #8 ; CHECK-LE-NEXT: movne r0, #1 ; CHECK-LE-NEXT: mov pc, lr ; @@ -444,9 +446,7 @@ define i1 @test_48_17_0(ptr %y) { ; ; CHECK-V7-BE-LABEL: test_48_17_0: ; CHECK-V7-BE: @ %bb.0: -; CHECK-V7-BE-NEXT: ldr r1, [r0] -; CHECK-V7-BE-NEXT: ldrh r0, [r0, #4] -; CHECK-V7-BE-NEXT: orr r0, r0, r1, lsl #16 +; CHECK-V7-BE-NEXT: ldr r0, [r0, #2] ; CHECK-V7-BE-NEXT: bfc r0, #17, #15 ; CHECK-V7-BE-NEXT: cmp r0, #0 ; CHECK-V7-BE-NEXT: movwne r0, #1 @@ -506,15 +506,14 @@ define i1 @test_40_1_32(ptr %y) { ; ; CHECK-BE-LABEL: test_40_1_32: ; CHECK-BE: @ %bb.0: -; CHECK-BE-NEXT: ldr r0, [r0] -; CHECK-BE-NEXT: mov r1, #1 -; CHECK-BE-NEXT: and r0, r1, r0, lsr #24 +; CHECK-BE-NEXT: ldrb r0, [r0] +; CHECK-BE-NEXT: and r0, r0, #1 ; CHECK-BE-NEXT: mov pc, lr ; ; CHECK-V7-BE-LABEL: test_40_1_32: ; CHECK-V7-BE: @ %bb.0: -; CHECK-V7-BE-NEXT: ldr r0, [r0] -; CHECK-V7-BE-NEXT: ubfx r0, r0, #24, #1 +; CHECK-V7-BE-NEXT: ldrb r0, [r0] +; CHECK-V7-BE-NEXT: and r0, r0, #1 ; CHECK-V7-BE-NEXT: bx lr %a = load i40, ptr %y %b = and i40 %a, u0x100000000 diff --git a/llvm/test/CodeGen/PowerPC/simplifysetcc_narrow_load.ll b/llvm/test/CodeGen/PowerPC/simplifysetcc_narrow_load.ll index 1a03423fe6ae..49b8e2bc2f7b 100644 --- a/llvm/test/CodeGen/PowerPC/simplifysetcc_narrow_load.ll +++ b/llvm/test/CodeGen/PowerPC/simplifysetcc_narrow_load.ll @@ -26,7 +26,7 @@ define i1 @test_129_15_0(ptr %y) { ; ; CHECK-BE-LABEL: test_129_15_0: ; CHECK-BE: # %bb.0: -; CHECK-BE-NEXT: lhz 3, 14(3) +; CHECK-BE-NEXT: lhz 3, 15(3) ; CHECK-BE-NEXT: clrlwi 3, 3, 17 ; CHECK-BE-NEXT: addic 4, 3, -1 ; CHECK-BE-NEXT: subfe 3, 4, 3 @@ -69,7 +69,7 @@ define i1 @test_33_8_0(ptr %y) { ; ; CHECK-BE-LABEL: test_33_8_0: ; CHECK-BE: # %bb.0: -; CHECK-BE-NEXT: lbz 3, 3(3) +; CHECK-BE-NEXT: lbz 3, 4(3) ; CHECK-BE-NEXT: addic 4, 3, -1 ; CHECK-BE-NEXT: subfe 3, 4, 3 ; CHECK-BE-NEXT: blr @@ -105,7 +105,7 @@ define i1 @test_33_1_31(ptr %y) { ; ; CHECK-BE-LABEL: test_33_1_31: ; CHECK-BE: # %bb.0: -; CHECK-BE-NEXT: lbz 3, 0(3) +; CHECK-BE-NEXT: lbz 3, 1(3) ; CHECK-BE-NEXT: srwi 3, 3, 7 ; CHECK-BE-NEXT: blr %a = load i33, ptr %y @@ -123,7 +123,7 @@ define i1 @test_33_1_0(ptr %y) { ; ; CHECK-BE-LABEL: test_33_1_0: ; CHECK-BE: # %bb.0: -; CHECK-BE-NEXT: lbz 3, 3(3) +; CHECK-BE-NEXT: lbz 3, 4(3) ; CHECK-BE-NEXT: clrlwi 3, 3, 31 ; CHECK-BE-NEXT: blr %a = load i33, ptr %y @@ -250,12 +250,10 @@ define i1 @test_48_17_0(ptr %y) { ; ; CHECK-BE-LABEL: test_48_17_0: ; CHECK-BE: # %bb.0: -; CHECK-BE-NEXT: lhz 4, 4(3) -; CHECK-BE-NEXT: lwz 3, 0(3) -; CHECK-BE-NEXT: clrlwi 4, 4, 16 -; CHECK-BE-NEXT: rlwimi 4, 3, 16, 15, 15 -; CHECK-BE-NEXT: addic 3, 4, -1 -; CHECK-BE-NEXT: subfe 3, 3, 4 +; CHECK-BE-NEXT: lwz 3, 2(3) +; CHECK-BE-NEXT: clrlwi 3, 3, 15 +; CHECK-BE-NEXT: addic 4, 3, -1 +; CHECK-BE-NEXT: subfe 3, 4, 3 ; CHECK-BE-NEXT: blr %a = load i48, ptr %y %b = and i48 %a, u0x1ffff @@ -292,8 +290,8 @@ define i1 @test_40_1_32(ptr %y) { ; ; CHECK-BE-LABEL: test_40_1_32: ; CHECK-BE: # %bb.0: -; CHECK-BE-NEXT: lwz 3, 0(3) -; CHECK-BE-NEXT: rlwinm 3, 3, 8, 31, 31 +; CHECK-BE-NEXT: lbz 3, 0(3) +; CHECK-BE-NEXT: clrlwi 3, 3, 31 ; CHECK-BE-NEXT: blr %a = load i40, ptr %y %b = and i40 %a, u0x100000000 @@ -325,7 +323,6 @@ define i1 @test_24_8_8(ptr %y) { ; CHECK-LE-LABEL: test_24_8_8: ; CHECK-LE: # %bb.0: ; CHECK-LE-NEXT: lbz 3, 1(3) -; CHECK-LE-NEXT: slwi 3, 3, 8 ; CHECK-LE-NEXT: addic 4, 3, -1 ; CHECK-LE-NEXT: subfe 3, 4, 3 ; CHECK-LE-NEXT: blr @@ -333,7 +330,6 @@ define i1 @test_24_8_8(ptr %y) { ; CHECK-BE-LABEL: test_24_8_8: ; CHECK-BE: # %bb.0: ; CHECK-BE-NEXT: lbz 3, 1(3) -; CHECK-BE-NEXT: slwi 3, 3, 8 ; CHECK-BE-NEXT: addic 4, 3, -1 ; CHECK-BE-NEXT: subfe 3, 4, 3 ; CHECK-BE-NEXT: blr @@ -346,18 +342,16 @@ define i1 @test_24_8_8(ptr %y) { define i1 @test_24_8_12(ptr %y) { ; CHECK-LE-LABEL: test_24_8_12: ; CHECK-LE: # %bb.0: -; CHECK-LE-NEXT: lhz 4, 0(3) -; CHECK-LE-NEXT: lbz 3, 2(3) -; CHECK-LE-NEXT: rlwinm 4, 4, 0, 16, 19 -; CHECK-LE-NEXT: rlwimi 4, 3, 16, 12, 15 -; CHECK-LE-NEXT: addic 3, 4, -1 -; CHECK-LE-NEXT: subfe 3, 3, 4 +; CHECK-LE-NEXT: lhz 3, 1(3) +; CHECK-LE-NEXT: rlwinm 3, 3, 0, 20, 27 +; CHECK-LE-NEXT: addic 4, 3, -1 +; CHECK-LE-NEXT: subfe 3, 4, 3 ; CHECK-LE-NEXT: blr ; ; CHECK-BE-LABEL: test_24_8_12: ; CHECK-BE: # %bb.0: ; CHECK-BE-NEXT: lhz 3, 0(3) -; CHECK-BE-NEXT: rlwinm 3, 3, 8, 12, 19 +; CHECK-BE-NEXT: rlwinm 3, 3, 0, 20, 27 ; CHECK-BE-NEXT: addic 4, 3, -1 ; CHECK-BE-NEXT: subfe 3, 4, 3 ; CHECK-BE-NEXT: blr @@ -371,7 +365,6 @@ define i1 @test_24_8_16(ptr %y) { ; CHECK-LE-LABEL: test_24_8_16: ; CHECK-LE: # %bb.0: ; CHECK-LE-NEXT: lbz 3, 2(3) -; CHECK-LE-NEXT: slwi 3, 3, 16 ; CHECK-LE-NEXT: addic 4, 3, -1 ; CHECK-LE-NEXT: subfe 3, 4, 3 ; CHECK-LE-NEXT: blr @@ -379,7 +372,6 @@ define i1 @test_24_8_16(ptr %y) { ; CHECK-BE-LABEL: test_24_8_16: ; CHECK-BE: # %bb.0: ; CHECK-BE-NEXT: lbz 3, 0(3) -; CHECK-BE-NEXT: slwi 3, 3, 16 ; CHECK-BE-NEXT: addic 4, 3, -1 ; CHECK-BE-NEXT: subfe 3, 4, 3 ; CHECK-BE-NEXT: blr -- GitLab From 2c2377d3a9305b86ab110a4f8390b2d16bff9510 Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Fri, 12 Apr 2024 15:39:22 +0100 Subject: [PATCH 072/464] Add lldb-dap to Swift distributions (#88482) This includes the lldb-dap executable in the MacOS and Linux distributions of Swift. Currently there is a commit in the Apple repo to do this for just MacOS https://github.com/apple/llvm-project/pull/8176. This PR extends this to both Linux and MacOS and brings the change upstream. @JDevlieghere @adrian-prantl --- lldb/cmake/caches/Apple-lldb-Linux.cmake | 1 + lldb/cmake/caches/Apple-lldb-macOS.cmake | 1 + 2 files changed, 2 insertions(+) diff --git a/lldb/cmake/caches/Apple-lldb-Linux.cmake b/lldb/cmake/caches/Apple-lldb-Linux.cmake index bfa660d8654b..b936929afc42 100644 --- a/lldb/cmake/caches/Apple-lldb-Linux.cmake +++ b/lldb/cmake/caches/Apple-lldb-Linux.cmake @@ -5,6 +5,7 @@ set(LLVM_DISTRIBUTION_COMPONENTS lldb liblldb lldb-argdumper + lldb-dap lldb-server lldb-python-scripts CACHE STRING "") diff --git a/lldb/cmake/caches/Apple-lldb-macOS.cmake b/lldb/cmake/caches/Apple-lldb-macOS.cmake index 2aef41157bab..5155024ac3a0 100644 --- a/lldb/cmake/caches/Apple-lldb-macOS.cmake +++ b/lldb/cmake/caches/Apple-lldb-macOS.cmake @@ -22,6 +22,7 @@ set(LLVM_DISTRIBUTION_COMPONENTS lldb liblldb lldb-argdumper + lldb-dap darwin-debug debugserver CACHE STRING "") -- GitLab From 986d0dba85f3239671c5151d9817b73de08664a0 Mon Sep 17 00:00:00 2001 From: yronglin Date: Fri, 12 Apr 2024 22:39:40 +0800 Subject: [PATCH 073/464] [Clang] Fix AST dump for {CXXDefaultArgExpr, CXXDefaultInitExpr} (#88269) This PR fix a AST dump issue since https://github.com/llvm/llvm-project/pull/80001 When Clang dumps `CXXDefaultArgExpr`/`CXXDefaultInitExpr`, there has no recursively dump the complete `CXXDefaultArgExpr`/`CXXDefaultInitExpr`. Since this PR, Clang will recursively dump a `CXXDefaultArgExpr`/`CXXDefaultInitExpr` node, even if the node has no rewritten init. *Consider*: ``` struct A { int arr[1]; }; struct B { const A &a = A{{0}}; }; void test() { B b{}; } ``` *Before*: ``` `-FunctionDecl line:9:6 test 'void ()' `-CompoundStmt `-DeclStmt `-VarDecl col:5 b 'B' listinit `-InitListExpr 'B' `-CXXDefaultInitExpr 'const A' lvalue has rewritten init `-ExprWithCleanups 'const A' lvalue ``` *After*: ``` `-FunctionDecl 0x15a9455a8 line:9:6 test 'void ()' `-CompoundStmt 0x15a945850 `-DeclStmt 0x15a945838 `-VarDecl 0x15a945708 col:5 b 'B' listinit `-InitListExpr 0x15a9457b0 'B' `-CXXDefaultInitExpr 0x15a9457f8 'const A' lvalue has rewritten init `-ExprWithCleanups 0x15a945568 'const A' lvalue `-MaterializeTemporaryExpr 0x15a945500 'const A' lvalue extended by Field 0x15a945160 'a' 'const A &' `-ImplicitCastExpr 0x15a9454e8 'const A' `-CXXFunctionalCastExpr 0x15a9454c0 'A' functional cast to A `-InitListExpr 0x15a9452c0 'A' `-InitListExpr 0x15a945308 'int[1]' `-IntegerLiteral 0x15a945210 'int' 0 ``` --------- Signed-off-by: yronglin --- clang/include/clang/AST/ASTNodeTraverser.h | 8 + clang/include/clang/AST/JSONNodeDumper.h | 2 + clang/lib/AST/JSONNodeDumper.cpp | 8 + clang/lib/AST/TextNodeDumper.cpp | 14 +- clang/test/AST/ast-dump-default-arg-json.cpp | 2091 +++++++++++++++++ clang/test/AST/ast-dump-default-init-json.cpp | 929 ++++++++ clang/test/AST/ast-dump-default-init.cpp | 21 + .../test/AST/ast-dump-for-range-lifetime.cpp | 21 + clang/unittests/AST/ASTTraverserTest.cpp | 8 + 9 files changed, 3090 insertions(+), 12 deletions(-) create mode 100644 clang/test/AST/ast-dump-default-arg-json.cpp create mode 100644 clang/test/AST/ast-dump-default-init-json.cpp create mode 100644 clang/test/AST/ast-dump-default-init.cpp diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 94e7dd817809..a6e3b05b0059 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -932,6 +932,14 @@ public: Visit(TArg); } + void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) { + Visit(Node->getExpr()); + } + + void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) { + Visit(Node->getExpr()); + } + // Implements Visit methods for Attrs. #include "clang/AST/AttrNodeTraverse.inc" }; diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h index 7a60f362650c..55bd583e304e 100644 --- a/clang/include/clang/AST/JSONNodeDumper.h +++ b/clang/include/clang/AST/JSONNodeDumper.h @@ -310,6 +310,8 @@ public: void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE); void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME); void VisitRequiresExpr(const RequiresExpr *RE); + void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node); + void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node); void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE); void VisitObjCMessageExpr(const ObjCMessageExpr *OME); diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index fb3494393f75..78115200f4f0 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1576,6 +1576,14 @@ void JSONNodeDumper::VisitMaterializeTemporaryExpr( attributeOnlyIfTrue("boundToLValueRef", MTE->isBoundToLvalueReference()); } +void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) { + attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit()); +} + +void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) { + attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit()); +} + void JSONNodeDumper::VisitCXXDependentScopeMemberExpr( const CXXDependentScopeMemberExpr *DSME) { JOS.attribute("isArrow", DSME->isArrow()); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 085a7f51ce99..f4b2df7730ae 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1450,23 +1450,13 @@ void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) { } void TextNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) { - if (Node->hasRewrittenInit()) { + if (Node->hasRewrittenInit()) OS << " has rewritten init"; - AddChild([=] { - ColorScope Color(OS, ShowColors, StmtColor); - Visit(Node->getExpr()); - }); - } } void TextNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) { - if (Node->hasRewrittenInit()) { + if (Node->hasRewrittenInit()) OS << " has rewritten init"; - AddChild([=] { - ColorScope Color(OS, ShowColors, StmtColor); - Visit(Node->getExpr()); - }); - } } void TextNodeDumper::VisitMaterializeTemporaryExpr( diff --git a/clang/test/AST/ast-dump-default-arg-json.cpp b/clang/test/AST/ast-dump-default-arg-json.cpp new file mode 100644 index 000000000000..b6a138934caf --- /dev/null +++ b/clang/test/AST/ast-dump-default-arg-json.cpp @@ -0,0 +1,2091 @@ +// RUN: %clang_cc1 -std=c++23 -triple x86_64-linux-gnu -fsyntax-only -ast-dump=json %s | FileCheck %s + +struct S { + int arr[1]; + const int *begin() const { return arr; } + const int *end() const { return &arr[1]; } + S() {} + ~S() {} +}; + +S func(const int &, const S &s = S()); + +void test() { + for (auto v : func(1)) {} +} + +// NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py + + +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "TranslationUnitDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__int128_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__int128" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__int128" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__uint128_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned __int128" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned __int128" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__NSConstantString", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__NSConstantString_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__NSConstantString_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "__NSConstantString_tag" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__builtin_ms_va_list", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char *" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "PointerType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char *" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__builtin_va_list", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ConstantArrayType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "size": 1, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "__va_list_tag" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 103, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 235, +// CHECK-NEXT: "line": 9, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "S", +// CHECK-NEXT: "tagUsed": "struct", +// CHECK-NEXT: "completeDefinition": true, +// CHECK-NEXT: "definitionData": { +// CHECK-NEXT: "canConstDefaultInit": true, +// CHECK-NEXT: "copyAssign": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "copyCtor": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "defaultCtor": { +// CHECK-NEXT: "defaultedIsConstexpr": true, +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "nonTrivial": true, +// CHECK-NEXT: "userProvided": true +// CHECK-NEXT: }, +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "nonTrivial": true, +// CHECK-NEXT: "userDeclared": true +// CHECK-NEXT: }, +// CHECK-NEXT: "hasUserDeclaredConstructor": true, +// CHECK-NEXT: "isStandardLayout": true, +// CHECK-NEXT: "moveAssign": {}, +// CHECK-NEXT: "moveCtor": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 103, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "S", +// CHECK-NEXT: "tagUsed": "struct" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 120, +// CHECK-NEXT: "line": 4, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 116, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 125, +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "arr", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int[1]" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXMethodDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 141, +// CHECK-NEXT: "line": 5, +// CHECK-NEXT: "col": 14, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 130, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 169, +// CHECK-NEXT: "col": 42, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "begin", +// CHECK-NEXT: "mangledName": "_ZNK1S5beginEv", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *() const" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 155, +// CHECK-NEXT: "col": 28, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 169, +// CHECK-NEXT: "col": 42, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ReturnStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 157, +// CHECK-NEXT: "col": 30, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "ArrayToPointerDecay", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MemberExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "name": "arr", +// CHECK-NEXT: "isArrow": true, +// CHECK-NEXT: "referencedMemberDecl": "0x{{.*}}", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXThisExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "implicit": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXMethodDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 184, +// CHECK-NEXT: "line": 6, +// CHECK-NEXT: "col": 14, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 173, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 214, +// CHECK-NEXT: "col": 44, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "end", +// CHECK-NEXT: "mangledName": "_ZNK1S3endEv", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *() const" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 196, +// CHECK-NEXT: "col": 26, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 214, +// CHECK-NEXT: "col": 44, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ReturnStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 198, +// CHECK-NEXT: "col": 28, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 211, +// CHECK-NEXT: "col": 41, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "UnaryOperator", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 205, +// CHECK-NEXT: "col": 35, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 211, +// CHECK-NEXT: "col": 41, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "isPostfix": false, +// CHECK-NEXT: "opcode": "&", +// CHECK-NEXT: "canOverflow": false, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ArraySubscriptExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 211, +// CHECK-NEXT: "col": 41, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "ArrayToPointerDecay", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MemberExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "name": "arr", +// CHECK-NEXT: "isArrow": true, +// CHECK-NEXT: "referencedMemberDecl": "0x{{.*}}", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXThisExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "implicit": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 210, +// CHECK-NEXT: "col": 40, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 210, +// CHECK-NEXT: "col": 40, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "value": "1" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXConstructorDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 218, +// CHECK-NEXT: "line": 7, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 218, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 223, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "S", +// CHECK-NEXT: "mangledName": "_ZN1SC1Ev", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 222, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 223, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 227, +// CHECK-NEXT: "line": 8, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 227, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 233, +// CHECK-NEXT: "col": 9, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "~S", +// CHECK-NEXT: "mangledName": "_ZN1SD1Ev", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 232, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 233, +// CHECK-NEXT: "col": 9, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXConstructorDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "S", +// CHECK-NEXT: "mangledName": "_ZN1SC1ERKS_", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (const S &)" +// CHECK-NEXT: }, +// CHECK-NEXT: "inline": true, +// CHECK-NEXT: "constexpr": true, +// CHECK-NEXT: "explicitlyDefaulted": "default", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S &" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 241, +// CHECK-NEXT: "line": 11, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 239, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 275, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "func", +// CHECK-NEXT: "mangledName": "_Z4funcRKiRK1S", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S (const int &, const S &)" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 257, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 246, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 256, +// CHECK-NEXT: "col": 18, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int &" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 268, +// CHECK-NEXT: "col": 30, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 259, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "s", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S &" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ExprWithCleanups", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "cleanupsHaveSideEffects": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "storageDuration": "full expression", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXBindTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "temp": "0x{{.*}}", +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "name": "~S", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXTemporaryObjectExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "ctorType": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "hadMultipleCandidates": true, +// CHECK-NEXT: "constructionKind": "complete" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 284, +// CHECK-NEXT: "line": 13, +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 279, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 321, +// CHECK-NEXT: "line": 15, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "test", +// CHECK-NEXT: "mangledName": "_Z4testv", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 291, +// CHECK-NEXT: "line": 13, +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 321, +// CHECK-NEXT: "line": 15, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXForRangeStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 295, +// CHECK-NEXT: "line": 14, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 319, +// CHECK-NEXT: "col": 27, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: {}, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ExprWithCleanups", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "xvalue", +// CHECK-NEXT: "cleanupsHaveSideEffects": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "xvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXBindTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "temp": "0x{{.*}}", +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "name": "~S", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CallExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S (*)(const int &, const S &)" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "FunctionToPointerDecay", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S (const int &, const S &)" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FunctionDecl", +// CHECK-NEXT: "name": "func", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S (const int &, const S &)" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "value": "1" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDefaultArgExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "hasRewrittenInit": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "line": 11, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXBindTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "temp": "0x{{.*}}", +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "name": "~S", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXTemporaryObjectExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "ctorType": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "hadMultipleCandidates": true, +// CHECK-NEXT: "constructionKind": "complete" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "line": 14, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "__begin1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXMemberCallExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MemberExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "name": "begin", +// CHECK-NEXT: "isArrow": false, +// CHECK-NEXT: "referencedMemberDecl": "0x{{.*}}", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "__end1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXMemberCallExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MemberExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "name": "end", +// CHECK-NEXT: "isArrow": false, +// CHECK-NEXT: "referencedMemberDecl": "0x{{.*}}", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BinaryOperator", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "opcode": "!=", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__begin1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__end1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "UnaryOperator", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "isPostfix": false, +// CHECK-NEXT: "opcode": "++", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__begin1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 300, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 316, +// CHECK-NEXT: "col": 24, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 305, +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 300, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "v", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "UnaryOperator", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "isPostfix": false, +// CHECK-NEXT: "opcode": "*", +// CHECK-NEXT: "canOverflow": false, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__begin1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 318, +// CHECK-NEXT: "col": 26, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 319, +// CHECK-NEXT: "col": 27, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } diff --git a/clang/test/AST/ast-dump-default-init-json.cpp b/clang/test/AST/ast-dump-default-init-json.cpp new file mode 100644 index 000000000000..1058b4e3ea4d --- /dev/null +++ b/clang/test/AST/ast-dump-default-init-json.cpp @@ -0,0 +1,929 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump=json %s | FileCheck %s + +struct A { + int arr[1]; +}; + +struct B { + const A &a = A{{0}}; +}; + +void test() { + B b{}; +} + +// NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py + + +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "TranslationUnitDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__int128_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__int128" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__int128" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__uint128_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned __int128" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned __int128" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__NSConstantString", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__NSConstantString_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__NSConstantString_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "__NSConstantString_tag" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__builtin_ms_va_list", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char *" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "PointerType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char *" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__builtin_va_list", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ConstantArrayType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "size": 1, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "__va_list_tag" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 92, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 117, +// CHECK-NEXT: "line": 5, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "A", +// CHECK-NEXT: "tagUsed": "struct", +// CHECK-NEXT: "completeDefinition": true, +// CHECK-NEXT: "definitionData": { +// CHECK-NEXT: "canPassInRegisters": true, +// CHECK-NEXT: "copyAssign": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "copyCtor": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "defaultCtor": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "irrelevant": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "isAggregate": true, +// CHECK-NEXT: "isLiteral": true, +// CHECK-NEXT: "isPOD": true, +// CHECK-NEXT: "isStandardLayout": true, +// CHECK-NEXT: "isTrivial": true, +// CHECK-NEXT: "isTriviallyCopyable": true, +// CHECK-NEXT: "moveAssign": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "moveCtor": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 92, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "A", +// CHECK-NEXT: "tagUsed": "struct" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 109, +// CHECK-NEXT: "line": 4, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 105, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 114, +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "arr", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int[1]" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "~A", +// CHECK-NEXT: "mangledName": "_ZN1AD1Ev", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inline": true, +// CHECK-NEXT: "explicitlyDefaulted": "default" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 128, +// CHECK-NEXT: "line": 7, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 121, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 155, +// CHECK-NEXT: "line": 9, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "B", +// CHECK-NEXT: "tagUsed": "struct", +// CHECK-NEXT: "completeDefinition": true, +// CHECK-NEXT: "definitionData": { +// CHECK-NEXT: "canConstDefaultInit": true, +// CHECK-NEXT: "canPassInRegisters": true, +// CHECK-NEXT: "copyAssign": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "copyCtor": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "defaultCtor": { +// CHECK-NEXT: "defaultedIsConstexpr": true, +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "isConstexpr": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "nonTrivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "irrelevant": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "hasConstexprNonCopyMoveConstructor": true, +// CHECK-NEXT: "isAggregate": true, +// CHECK-NEXT: "isLiteral": true, +// CHECK-NEXT: "isTriviallyCopyable": true, +// CHECK-NEXT: "moveAssign": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "moveCtor": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 128, +// CHECK-NEXT: "line": 7, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 121, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 128, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "B", +// CHECK-NEXT: "tagUsed": "struct" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 143, +// CHECK-NEXT: "line": 8, +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 134, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "a", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A &" +// CHECK-NEXT: }, +// CHECK-NEXT: "hasInClassInitializer": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ExprWithCleanups", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "name": "a", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A &" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXFunctionalCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 148, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 149, +// CHECK-NEXT: "col": 18, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 151, +// CHECK-NEXT: "col": 20, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 150, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 150, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "value": "0" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "line": 11, +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 159, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 182, +// CHECK-NEXT: "line": 13, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "test", +// CHECK-NEXT: "mangledName": "_Z4testv", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 171, +// CHECK-NEXT: "line": 11, +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 182, +// CHECK-NEXT: "line": 13, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 175, +// CHECK-NEXT: "line": 12, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 180, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 177, +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 175, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 179, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "b", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "B" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "list", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 178, +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 179, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "B" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDefaultInitExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 179, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 179, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "hasRewrittenInit": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ExprWithCleanups", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "line": 8, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "name": "a", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A &" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXFunctionalCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 148, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 149, +// CHECK-NEXT: "col": 18, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 151, +// CHECK-NEXT: "col": 20, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 150, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 150, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "value": "0" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } diff --git a/clang/test/AST/ast-dump-default-init.cpp b/clang/test/AST/ast-dump-default-init.cpp new file mode 100644 index 000000000000..9fe945ee6e93 --- /dev/null +++ b/clang/test/AST/ast-dump-default-init.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -ast-dump %s | FileCheck %s + +struct A { + int arr[1]; +}; + +struct B { + const A &a = A{{0}}; +}; + +void test() { + B b{}; +} +// CHECK: -CXXDefaultInitExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue has rewritten init +// CHECK-NEXT: `-ExprWithCleanups 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue +// CHECK-NEXT: `-MaterializeTemporaryExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue extended by Field 0x{{[^ ]*}} 'a' 'const A &' +// CHECK-NEXT: `-ImplicitCastExpr 0x{{[^ ]*}} <{{.*}}> 'const A' +// CHECK-NEXT: `-CXXFunctionalCastExpr 0x{{[^ ]*}} <{{.*}}> 'A' functional cast to A +// CHECK-NEXT: `-InitListExpr 0x{{[^ ]*}} <{{.*}}> 'A' +// CHECK-NEXT: `-InitListExpr 0x{{[^ ]*}} <{{.*}}> 'int[1]' +// CHECK-NEXT: `-IntegerLiteral 0x{{[^ ]*}} <{{.*}}> 'int' 0 diff --git a/clang/test/AST/ast-dump-for-range-lifetime.cpp b/clang/test/AST/ast-dump-for-range-lifetime.cpp index 88b838268be2..0e92b6990ed5 100644 --- a/clang/test/AST/ast-dump-for-range-lifetime.cpp +++ b/clang/test/AST/ast-dump-for-range-lifetime.cpp @@ -132,6 +132,9 @@ void test4() { // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const A &))[3]' lvalue Function {{.*}} 'default_arg_fn' 'int (&(const A &))[3]' // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const A':'const P2718R0::A' lvalue has rewritten init // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'A':'P2718R0::A' 'void ()' for (auto e : default_arg_fn()) bar(e); } @@ -179,10 +182,19 @@ void test5() { // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'A':'P2718R0::A' 'void ()' // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' for (auto e : default_arg_fn(foo(foo(foo(A()))))) bar(e); } @@ -219,10 +231,19 @@ void test6() { // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void ()' // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' for (auto e : C(0, C(0, C(0, C())))) bar(e); } diff --git a/clang/unittests/AST/ASTTraverserTest.cpp b/clang/unittests/AST/ASTTraverserTest.cpp index 362f37655a0a..8b6e3e90c0ea 100644 --- a/clang/unittests/AST/ASTTraverserTest.cpp +++ b/clang/unittests/AST/ASTTraverserTest.cpp @@ -368,6 +368,8 @@ FunctionDecl 'stringConstruct' | |-ImplicitCastExpr | | `-StringLiteral | `-CXXDefaultArgExpr + | `-UnaryOperator + | `-IntegerLiteral `-ExprWithCleanups `-CXXOperatorCallExpr |-ImplicitCastExpr @@ -378,6 +380,8 @@ FunctionDecl 'stringConstruct' |-ImplicitCastExpr | `-StringLiteral `-CXXDefaultArgExpr + `-UnaryOperator + `-IntegerLiteral )cpp"); EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, @@ -415,6 +419,8 @@ FunctionDecl 'overloadCall' | |-ImplicitCastExpr | | `-StringLiteral | `-CXXDefaultArgExpr + | `-UnaryOperator + | `-IntegerLiteral `-CXXMemberCallExpr `-MemberExpr `-ParenExpr @@ -1219,6 +1225,7 @@ CXXRecordDecl 'Record' | | `-IntegerLiteral | |-CXXCtorInitializer 'm_i2' | | `-CXXDefaultInitExpr +| | `-IntegerLiteral | |-CXXCtorInitializer 'm_s' | | `-CXXConstructExpr | `-CompoundStmt @@ -1485,6 +1492,7 @@ CallExpr | `-DeclRefExpr 'hasDefaultArg' |-IntegerLiteral `-CXXDefaultArgExpr + `-IntegerLiteral )cpp"); EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, BN[0].getNodeAs("funcCall")), -- GitLab From a27ab3f54377a0addeef1ec9ba7c826fd885a304 Mon Sep 17 00:00:00 2001 From: Dominik Adamski Date: Fri, 12 Apr 2024 16:41:34 +0200 Subject: [PATCH 074/464] [Flang][AMDGPU] Add rocm-path flag (#88190) ROCm installation path is used for finding and automatically linking required bitcode libraries for OpenMP AMDGPU offload. Reported issue: https://github.com/llvm/llvm-project/issues/82553 --- clang/include/clang/Driver/Options.td | 3 ++- .../Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/asanrtl.bc | 0 .../Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/hip.bc | 0 .../Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ockl.bc | 0 .../bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_off.bc | 0 .../bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_on.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_off.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_on.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_off.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_on.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1010.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1011.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1012.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_803.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_900.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_908.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_off.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_on.bc | 0 .../amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_off.bc | 0 .../amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_on.bc | 0 .../Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ocml.bc | 0 .../Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/opencl.bc | 0 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/asanrtl.bc | 0 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/hip.bc | 0 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/ockl.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_abi_version_400.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_abi_version_500.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_abi_version_600.bc | 0 .../rocm/amdgcn/bitcode/oclc_correctly_rounded_sqrt_off.bc | 0 .../rocm/amdgcn/bitcode/oclc_correctly_rounded_sqrt_on.bc | 0 .../Driver/Inputs/rocm/amdgcn/bitcode/oclc_daz_opt_off.bc | 0 .../Driver/Inputs/rocm/amdgcn/bitcode/oclc_daz_opt_on.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_finite_only_off.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_finite_only_on.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1010.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1011.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1012.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_isa_version_803.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_isa_version_900.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_isa_version_908.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_unsafe_math_off.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_unsafe_math_on.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_wavefrontsize64_off.bc | 0 .../Inputs/rocm/amdgcn/bitcode/oclc_wavefrontsize64_on.bc | 0 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/ocml.bc | 0 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/opencl.bc | 0 flang/test/Driver/Inputs/rocm/bin/.hipVersion | 6 ++++++ flang/test/Driver/Inputs/rocm/include/hip/hip_runtime.h | 0 flang/test/Driver/Inputs/rocm/share/hip/hipVersion | 6 ++++++ flang/test/Driver/driver-help-hidden.f90 | 1 + flang/test/Driver/driver-help.f90 | 1 + flang/test/Driver/omp-driver-offload.f90 | 6 ++++++ 52 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/asanrtl.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/hip.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ockl.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1010.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1011.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1012.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_803.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_900.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_908.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ocml.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/opencl.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/asanrtl.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/hip.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/ockl.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_400.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_500.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_600.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_correctly_rounded_sqrt_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_correctly_rounded_sqrt_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_daz_opt_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_daz_opt_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_finite_only_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_finite_only_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1010.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1011.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1012.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_803.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_900.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_908.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_unsafe_math_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_unsafe_math_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_wavefrontsize64_off.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_wavefrontsize64_on.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/ocml.bc create mode 100644 flang/test/Driver/Inputs/rocm/amdgcn/bitcode/opencl.bc create mode 100644 flang/test/Driver/Inputs/rocm/bin/.hipVersion create mode 100644 flang/test/Driver/Inputs/rocm/include/hip/hip_runtime.h create mode 100644 flang/test/Driver/Inputs/rocm/share/hip/hipVersion diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 400f72f2250a..9a0b5d3304ca 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1341,7 +1341,8 @@ def hip_link : Flag<["--"], "hip-link">, Group, HelpText<"Link clang-offload-bundler bundles for HIP">; def no_hip_rt: Flag<["-"], "no-hip-rt">, Group, HelpText<"Do not link against HIP runtime libraries">; -def rocm_path_EQ : Joined<["--"], "rocm-path=">, Group, +def rocm_path_EQ : Joined<["--"], "rocm-path=">, + Visibility<[FlangOption]>, Group, HelpText<"ROCm installation path, used for finding and automatically linking required bitcode libraries.">; def hip_path_EQ : Joined<["--"], "hip-path=">, Group, HelpText<"HIP runtime installation path, used for finding HIP version and adding HIP include path.">; diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/asanrtl.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/asanrtl.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/hip.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/hip.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ockl.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ockl.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1010.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1010.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1011.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1011.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1012.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1012.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_803.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_803.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_900.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_900.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_908.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_908.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ocml.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ocml.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/opencl.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/opencl.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/asanrtl.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/asanrtl.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/hip.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/hip.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/ockl.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/ockl.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_400.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_400.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_500.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_500.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_600.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_600.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_correctly_rounded_sqrt_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_correctly_rounded_sqrt_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_correctly_rounded_sqrt_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_correctly_rounded_sqrt_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_daz_opt_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_daz_opt_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_daz_opt_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_daz_opt_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_finite_only_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_finite_only_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_finite_only_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_finite_only_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1010.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1010.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1011.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1011.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1012.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1012.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_803.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_803.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_900.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_900.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_908.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_908.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_unsafe_math_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_unsafe_math_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_unsafe_math_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_unsafe_math_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_wavefrontsize64_off.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_wavefrontsize64_off.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_wavefrontsize64_on.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_wavefrontsize64_on.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/ocml.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/ocml.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/opencl.bc b/flang/test/Driver/Inputs/rocm/amdgcn/bitcode/opencl.bc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/bin/.hipVersion b/flang/test/Driver/Inputs/rocm/bin/.hipVersion new file mode 100644 index 000000000000..677293c09139 --- /dev/null +++ b/flang/test/Driver/Inputs/rocm/bin/.hipVersion @@ -0,0 +1,6 @@ +# Auto-generated by cmake +# NOTE: The trailing whitespace is added on purpose to verify that these +# whitespaces are trimmed before paring. +HIP_VERSION_MAJOR=3 +HIP_VERSION_MINOR=6 +HIP_VERSION_PATCH=20214-a2917cd diff --git a/flang/test/Driver/Inputs/rocm/include/hip/hip_runtime.h b/flang/test/Driver/Inputs/rocm/include/hip/hip_runtime.h new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/flang/test/Driver/Inputs/rocm/share/hip/hipVersion b/flang/test/Driver/Inputs/rocm/share/hip/hipVersion new file mode 100644 index 000000000000..677293c09139 --- /dev/null +++ b/flang/test/Driver/Inputs/rocm/share/hip/hipVersion @@ -0,0 +1,6 @@ +# Auto-generated by cmake +# NOTE: The trailing whitespace is added on purpose to verify that these +# whitespaces are trimmed before paring. +HIP_VERSION_MAJOR=3 +HIP_VERSION_MINOR=6 +HIP_VERSION_PATCH=20214-a2917cd diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90 index eb00949c2a95..de2fe3048f99 100644 --- a/flang/test/Driver/driver-help-hidden.f90 +++ b/flang/test/Driver/driver-help-hidden.f90 @@ -148,6 +148,7 @@ ! CHECK-NEXT: -pthread Support POSIX threads in generated code ! CHECK-NEXT: -P Disable linemarker output in -E mode ! CHECK-NEXT: -resource-dir The directory which holds the compiler resource files +! CHECK-NEXT: --rocm-path= ROCm installation path, used for finding and automatically linking required bitcode libraries. ! CHECK-NEXT: -Rpass-analysis= Report transformation analysis from optimization passes whose name matches the given POSIX regular expression ! CHECK-NEXT: -Rpass-missed= Report missed transformations by optimization passes whose name matches the given POSIX regular expression ! CHECK-NEXT: -Rpass= Report transformations performed by optimization passes whose name matches the given POSIX regular expression diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 index 05f50ea348c2..b258eb59c186 100644 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -135,6 +135,7 @@ ! HELP-NEXT: -print-target-triple Print the normalized target triple ! HELP-NEXT: -pthread Support POSIX threads in generated code ! HELP-NEXT: -P Disable linemarker output in -E mode +! HELP-NEXT: --rocm-path= ROCm installation path, used for finding and automatically linking required bitcode libraries. ! HELP-NEXT: -Rpass-analysis= Report transformation analysis from optimization passes whose name matches the given POSIX regular expression ! HELP-NEXT: -Rpass-missed= Report missed transformations by optimization passes whose name matches the given POSIX regular expression ! HELP-NEXT: -Rpass= Report transformations performed by optimization passes whose name matches the given POSIX regular expression diff --git a/flang/test/Driver/omp-driver-offload.f90 b/flang/test/Driver/omp-driver-offload.f90 index 7e9a73627cd7..8f48ca75114c 100644 --- a/flang/test/Driver/omp-driver-offload.f90 +++ b/flang/test/Driver/omp-driver-offload.f90 @@ -201,3 +201,9 @@ ! RUN: -nogpulibc %s 2>&1 \ ! RUN: | FileCheck --check-prefix=NO-LIBC-GPU-AMDGPU %s ! NO-LIBC-GPU-AMDGPU-NOT: "-lcgpu-amdgpu" + +! RUN: %flang -### -v --target=x86_64-unknown-linux-gnu -fopenmp \ +! RUN: --offload-arch=gfx900 \ +! RUN: --rocm-path=%S/Inputs/rocm %s 2>&1 \ +! RUN: | FileCheck --check-prefix=ROCM-PATH %s +! ROCM-PATH: Found HIP installation: {{.*Inputs.*rocm}}, version 3.6.20214-a2917cd -- GitLab From 5752e3196bc52fdac70e3650abc703570ff6209b Mon Sep 17 00:00:00 2001 From: Vincent Belliard <81770341+v-bulle@users.noreply.github.com> Date: Fri, 12 Apr 2024 07:48:41 -0700 Subject: [PATCH 075/464] [lldb] fix dead lock in TypeCategoryMap.cpp (#87540) FormatManager::GetCategoryForLanguage and FormatManager::GetCategory(can_create = true) can be called concurrently and they both take the TypeCategory::m_map_mutex and the FormatManager::m_language_categories_mutex but in reverse order. On one thread, GetCategoryForLanguage takes m_language_categories_mutex and then ends calling TypeCategoryMap::Get which takes m_map_mutex On another thread GetCategory calls TypeCategoryMap::Add which takes m_map_mutex and then calls FormatManager::Changed() which takes m_language_categories_mutex If both threads are running concurrently, we have a dead lock. The patch releases the m_map_mutex before calling Changed which avoids the dead lock. --------- Co-authored-by: Vincent Belliard --- .../source/DataFormatters/TypeCategoryMap.cpp | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/lldb/source/DataFormatters/TypeCategoryMap.cpp b/lldb/source/DataFormatters/TypeCategoryMap.cpp index fd76bab95826..ce2cf369b5be 100644 --- a/lldb/source/DataFormatters/TypeCategoryMap.cpp +++ b/lldb/source/DataFormatters/TypeCategoryMap.cpp @@ -25,19 +25,31 @@ TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst) } void TypeCategoryMap::Add(KeyType name, const TypeCategoryImplSP &entry) { - std::lock_guard guard(m_map_mutex); - m_map[name] = entry; + { + std::lock_guard guard(m_map_mutex); + m_map[name] = entry; + } + // Release the mutex to avoid a potential deadlock between + // TypeCategoryMap::m_map_mutex and + // FormatManager::m_language_categories_mutex which can be acquired in + // reverse order when calling FormatManager::Changed. if (listener) listener->Changed(); } bool TypeCategoryMap::Delete(KeyType name) { - std::lock_guard guard(m_map_mutex); - MapIterator iter = m_map.find(name); - if (iter == m_map.end()) - return false; - m_map.erase(name); - Disable(name); + { + std::lock_guard guard(m_map_mutex); + MapIterator iter = m_map.find(name); + if (iter == m_map.end()) + return false; + m_map.erase(name); + Disable(name); + } + // Release the mutex to avoid a potential deadlock between + // TypeCategoryMap::m_map_mutex and + // FormatManager::m_language_categories_mutex which can be acquired in + // reverse order when calling FormatManager::Changed. if (listener) listener->Changed(); return true; @@ -123,9 +135,15 @@ void TypeCategoryMap::DisableAllCategories() { } void TypeCategoryMap::Clear() { - std::lock_guard guard(m_map_mutex); - m_map.clear(); - m_active_categories.clear(); + { + std::lock_guard guard(m_map_mutex); + m_map.clear(); + m_active_categories.clear(); + } + // Release the mutex to avoid a potential deadlock between + // TypeCategoryMap::m_map_mutex and + // FormatManager::m_language_categories_mutex which can be acquired in + // reverse order when calling FormatManager::Changed. if (listener) listener->Changed(); } -- GitLab From 4dd20b0728223ff20f4817edc2f89901385cb990 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 12 Apr 2024 11:35:23 -0400 Subject: [PATCH 076/464] [BOLT][NFC] Refactor relocation loop (#88424) Use the std `if () continue;` idiom before falling into the processing. --- bolt/lib/Rewrite/RewriteInstance.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index cbbe7d00d35d..f22bede002da 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -2306,9 +2306,13 @@ void RewriteInstance::processRelocations() { return; for (const SectionRef &Section : InputFile->sections()) { - if (cantFail(Section.getRelocatedSection()) != InputFile->section_end() && - !BinarySection(*BC, Section).isAllocatable()) - readRelocations(Section); + section_iterator SecIter = cantFail(Section.getRelocatedSection()); + if (SecIter == InputFile->section_end()) + continue; + if (BinarySection(*BC, Section).isAllocatable()) + continue; + + readRelocations(Section); } if (NumFailedRelocations) -- GitLab From 040efafa9fef101924d3cf67db20f6429ce1c871 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 12 Apr 2024 08:45:03 -0700 Subject: [PATCH 077/464] [RISCV] Support uimm32 immediates in RISCVInstrInfo::movImm for RV32. (#88464) This allows us to support larger stack offsets for FrameLowering. Fixes #88365. --- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 11 ++++++++-- llvm/test/CodeGen/RISCV/pr88365.ll | 26 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/pr88365.ll diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 004a228ccc13..508f607fab20 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -767,8 +767,15 @@ void RISCVInstrInfo::movImm(MachineBasicBlock &MBB, bool DstIsDead) const { Register SrcReg = RISCV::X0; - if (!STI.is64Bit() && !isInt<32>(Val)) - report_fatal_error("Should only materialize 32-bit constants for RV32"); + // For RV32, allow a sign or unsigned 32 bit value. + if (!STI.is64Bit() && !isInt<32>(Val)) { + // If have a uimm32 it will still fit in a register so we can allow it. + if (!isUInt<32>(Val)) + report_fatal_error("Should only materialize 32-bit constants for RV32"); + + // Sign extend for generateInstSeq. + Val = SignExtend64<32>(Val); + } RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(Val, STI); assert(!Seq.empty()); diff --git a/llvm/test/CodeGen/RISCV/pr88365.ll b/llvm/test/CodeGen/RISCV/pr88365.ll new file mode 100644 index 000000000000..73010fdf4044 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/pr88365.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=riscv32 | FileCheck %s + +define void @foo() { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -2032 +; CHECK-NEXT: .cfi_def_cfa_offset 2032 +; CHECK-NEXT: sw ra, 2028(sp) # 4-byte Folded Spill +; CHECK-NEXT: .cfi_offset ra, -4 +; CHECK-NEXT: li a0, -2048 +; CHECK-NEXT: sub sp, sp, a0 +; CHECK-NEXT: .cfi_def_cfa_offset -16 +; CHECK-NEXT: addi a0, sp, 4 +; CHECK-NEXT: call use +; CHECK-NEXT: li a0, -2048 +; CHECK-NEXT: add sp, sp, a0 +; CHECK-NEXT: lw ra, 2028(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 2032 +; CHECK-NEXT: ret + %1 = alloca [1073741818 x i32], align 4 + call void @use(ptr %1) + ret void +} + +declare void @use(ptr) -- GitLab From 72dfee114bd38dc4b424d392bc14cd6b7dfb79e5 Mon Sep 17 00:00:00 2001 From: Francis Visoiu Mistrih <890283+francisvm@users.noreply.github.com> Date: Fri, 12 Apr 2024 08:45:47 -0700 Subject: [PATCH 078/464] [RISCV] Remove mayLoad = 1 from store-conditional (#88470) lr.[wd]: mayLoad = 1, mayStore = 0 sc.[wd]: mayLoad = 0, mayStore = 1 all other AMOs: mayLoad = 1, mayStore = 1 --- llvm/lib/Target/RISCV/RISCVInstrInfoA.td | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td index 36842ceb49bf..814e0ddf111e 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td @@ -30,6 +30,19 @@ multiclass LR_r_aq_rl funct3, string opcodestr> { def _AQ_RL : LR_r<1, 1, funct3, opcodestr # ".aqrl">; } +let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +class SC_r funct3, string opcodestr> + : RVInstRAtomic<0b00011, aq, rl, funct3, OPC_AMO, + (outs GPR:$rd), (ins GPRMemZeroOffset:$rs1, GPR:$rs2), + opcodestr, "$rd, $rs2, $rs1">; + +multiclass SC_r_aq_rl funct3, string opcodestr> { + def "" : SC_r<0, 0, funct3, opcodestr>; + def _AQ : SC_r<1, 0, funct3, opcodestr # ".aq">; + def _RL : SC_r<0, 1, funct3, opcodestr # ".rl">; + def _AQ_RL : SC_r<1, 1, funct3, opcodestr # ".aqrl">; +} + let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in class AMO_rr funct5, bit aq, bit rl, bits<3> funct3, string opcodestr> : RVInstRAtomic funct5, bits<3> funct3, string opcodestr> { let Predicates = [HasStdExtAOrZalrsc], IsSignExtendingOpW = 1 in { defm LR_W : LR_r_aq_rl<0b010, "lr.w">, Sched<[WriteAtomicLDW, ReadAtomicLDW]>; -defm SC_W : AMO_rr_aq_rl<0b00011, 0b010, "sc.w">, +defm SC_W : SC_r_aq_rl<0b010, "sc.w">, Sched<[WriteAtomicSTW, ReadAtomicSTW, ReadAtomicSTW]>; } // Predicates = [HasStdExtAOrZalrsc], IsSignExtendingOpW = 1 @@ -76,7 +89,7 @@ defm AMOMAXU_W : AMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">, let Predicates = [HasStdExtAOrZalrsc, IsRV64] in { defm LR_D : LR_r_aq_rl<0b011, "lr.d">, Sched<[WriteAtomicLDD, ReadAtomicLDD]>; -defm SC_D : AMO_rr_aq_rl<0b00011, 0b011, "sc.d">, +defm SC_D : SC_r_aq_rl<0b011, "sc.d">, Sched<[WriteAtomicSTD, ReadAtomicSTD, ReadAtomicSTD]>; } // Predicates = [HasStdExtAOrZalrsc, IsRV64] -- GitLab From e0a628715a8464e220c8ba9e9aaaf2561139198a Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Fri, 12 Apr 2024 23:47:20 +0800 Subject: [PATCH 079/464] [ValueTracking] Convert `isKnownNonZero` to use SimplifyQuery (#85863) This patch converts `isKnownNonZero` to use SimplifyQuery. Then we can use the context information from `DomCondCache`. Fixes https://github.com/llvm/llvm-project/issues/85823. Alive2: https://alive2.llvm.org/ce/z/QUvHVj --- clang/lib/CodeGen/CGCall.cpp | 3 +- llvm/include/llvm/Analysis/ValueTracking.h | 6 +- llvm/lib/Analysis/BasicAliasAnalysis.cpp | 3 +- llvm/lib/Analysis/InstructionSimplify.cpp | 29 ++-- llvm/lib/Analysis/LazyValueInfo.cpp | 5 +- llvm/lib/Analysis/Loads.cpp | 6 +- llvm/lib/Analysis/ScalarEvolution.cpp | 2 +- llvm/lib/Analysis/ValueTracking.cpp | 17 +-- llvm/lib/CodeGen/CodeGenPrepare.cpp | 2 +- .../Transforms/IPO/AttributorAttributes.cpp | 5 +- llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 2 +- .../InstCombine/InstCombineAddSub.cpp | 2 +- .../InstCombine/InstCombineAndOrXor.cpp | 8 +- .../InstCombine/InstCombineCalls.cpp | 13 +- .../InstCombine/InstCombineCompares.cpp | 21 ++- .../Transforms/InstCombine/InstCombinePHI.cpp | 3 +- .../InstCombine/InstructionCombining.cpp | 2 +- .../Instrumentation/MemorySanitizer.cpp | 4 +- .../Utils/PromoteMemoryToRegister.cpp | 2 +- .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 20 +-- .../Transforms/Vectorize/VectorCombine.cpp | 3 +- llvm/test/Transforms/InstCombine/icmp-dom.ll | 131 ++++++++++++++++++ llvm/unittests/Analysis/ValueTrackingTest.cpp | 15 +- 23 files changed, 213 insertions(+), 91 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 3f5463a9a70e..7a0bc6fa77b8 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4124,7 +4124,8 @@ static bool isProvablyNull(llvm::Value *addr) { } static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { - return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); + return llvm::isKnownNonZero(Addr.getBasePointer(), /*Depth=*/0, + CGF.CGM.getDataLayout()); } /// Emit the actual writing-back of a writeback. diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index 3970efba18cc..9db0894162af 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -124,11 +124,7 @@ bool isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI); /// specified, perform context-sensitive analysis and return true if the /// pointer couldn't possibly be null at the specified instruction. /// Supports values with integer or pointer type and vectors of integers. -bool isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth = 0, - AssumptionCache *AC = nullptr, - const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr, - bool UseInstrInfo = true); +bool isKnownNonZero(const Value *V, unsigned Depth, const SimplifyQuery &Q); /// Return true if the two given values are negation. /// Currently can recoginze Value pair: diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp index 8dfc4b2a1cb1..b082dfe8fbd2 100644 --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1283,7 +1283,8 @@ AliasResult BasicAAResult::aliasGEP( // VarIndex = Scale*V. const VariableGEPIndex &Var = DecompGEP1.VarIndices[0]; if (Var.Val.TruncBits == 0 && - isKnownNonZero(Var.Val.V, DL, 0, &AC, Var.CxtI, DT)) { + isKnownNonZero(Var.Val.V, /*Depth=*/0, + SimplifyQuery(DL, DT, &AC, Var.CxtI))) { // Check if abs(V*Scale) >= abs(Scale) holds in the presence of // potentially wrapping math. auto MultiplyByScaleNoWrap = [](const VariableGEPIndex &Var) { diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 1aaa4d658803..e83657df20f2 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1586,12 +1586,10 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp, if (match(UnsignedICmp, m_c_ICmp(UnsignedPred, m_Specific(Y), m_Specific(A)))) { if (UnsignedPred == ICmpInst::ICMP_UGE && IsAnd && - EqPred == ICmpInst::ICMP_NE && - isKnownNonZero(B, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + EqPred == ICmpInst::ICMP_NE && isKnownNonZero(B, /*Depth=*/0, Q)) return UnsignedICmp; if (UnsignedPred == ICmpInst::ICMP_ULT && !IsAnd && - EqPred == ICmpInst::ICMP_EQ && - isKnownNonZero(B, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + EqPred == ICmpInst::ICMP_EQ && isKnownNonZero(B, /*Depth=*/0, Q)) return UnsignedICmp; } } @@ -1609,13 +1607,13 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp, // X > Y && Y == 0 --> Y == 0 iff X != 0 // X > Y || Y == 0 --> X > Y iff X != 0 if (UnsignedPred == ICmpInst::ICMP_UGT && EqPred == ICmpInst::ICMP_EQ && - isKnownNonZero(X, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + isKnownNonZero(X, /*Depth=*/0, Q)) return IsAnd ? ZeroICmp : UnsignedICmp; // X <= Y && Y != 0 --> X <= Y iff X != 0 // X <= Y || Y != 0 --> Y != 0 iff X != 0 if (UnsignedPred == ICmpInst::ICMP_ULE && EqPred == ICmpInst::ICMP_NE && - isKnownNonZero(X, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + isKnownNonZero(X, /*Depth=*/0, Q)) return IsAnd ? UnsignedICmp : ZeroICmp; // The transforms below here are expected to be handled more generally with @@ -2821,11 +2819,10 @@ static Constant *computePointerICmp(CmpInst::Predicate Pred, Value *LHS, // the other operand can not be based on the alloc - if it were, then // the cmp itself would be a capture. Value *MI = nullptr; - if (isAllocLikeFn(LHS, TLI) && - llvm::isKnownNonZero(RHS, DL, 0, nullptr, CxtI, DT)) + if (isAllocLikeFn(LHS, TLI) && llvm::isKnownNonZero(RHS, /*Depth=*/0, Q)) MI = LHS; else if (isAllocLikeFn(RHS, TLI) && - llvm::isKnownNonZero(LHS, DL, 0, nullptr, CxtI, DT)) + llvm::isKnownNonZero(LHS, /*Depth=*/0, Q)) MI = RHS; if (MI) { // FIXME: This is incorrect, see PR54002. While we can assume that the @@ -2981,12 +2978,12 @@ static Value *simplifyICmpWithZero(CmpInst::Predicate Pred, Value *LHS, return getTrue(ITy); case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_ULE: - if (isKnownNonZero(LHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT, Q.IIQ.UseInstrInfo)) + if (isKnownNonZero(LHS, /*Depth=*/0, Q)) return getFalse(ITy); break; case ICmpInst::ICMP_NE: case ICmpInst::ICMP_UGT: - if (isKnownNonZero(LHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT, Q.IIQ.UseInstrInfo)) + if (isKnownNonZero(LHS, /*Depth=*/0, Q)) return getTrue(ITy); break; case ICmpInst::ICMP_SLT: { @@ -3001,8 +2998,7 @@ static Value *simplifyICmpWithZero(CmpInst::Predicate Pred, Value *LHS, KnownBits LHSKnown = computeKnownBits(LHS, /* Depth */ 0, Q); if (LHSKnown.isNegative()) return getTrue(ITy); - if (LHSKnown.isNonNegative() && - isKnownNonZero(LHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT)) + if (LHSKnown.isNonNegative() && isKnownNonZero(LHS, /*Depth=*/0, Q)) return getFalse(ITy); break; } @@ -3018,8 +3014,7 @@ static Value *simplifyICmpWithZero(CmpInst::Predicate Pred, Value *LHS, KnownBits LHSKnown = computeKnownBits(LHS, /* Depth */ 0, Q); if (LHSKnown.isNegative()) return getFalse(ITy); - if (LHSKnown.isNonNegative() && - isKnownNonZero(LHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT)) + if (LHSKnown.isNonNegative() && isKnownNonZero(LHS, /*Depth=*/0, Q)) return getTrue(ITy); break; } @@ -3172,7 +3167,7 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpInst::Predicate Pred, const APInt *C; if ((match(LBO, m_LShr(m_Specific(RHS), m_APInt(C))) && *C != 0) || (match(LBO, m_UDiv(m_Specific(RHS), m_APInt(C))) && *C != 1)) { - if (isKnownNonZero(RHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT)) { + if (isKnownNonZero(RHS, /*Depth=*/0, Q)) { switch (Pred) { default: break; @@ -3405,7 +3400,7 @@ static Value *simplifyICmpWithBinOp(CmpInst::Predicate Pred, Value *LHS, bool NUW = Q.IIQ.hasNoUnsignedWrap(LBO) && Q.IIQ.hasNoUnsignedWrap(RBO); bool NSW = Q.IIQ.hasNoSignedWrap(LBO) && Q.IIQ.hasNoSignedWrap(RBO); if (!NUW || (ICmpInst::isSigned(Pred) && !NSW) || - !isKnownNonZero(LBO->getOperand(0), Q.DL)) + !isKnownNonZero(LBO->getOperand(0), /*Depth=*/0, Q)) break; if (Value *V = simplifyICmpInst(Pred, LBO->getOperand(1), RBO->getOperand(1), Q, MaxRecurse - 1)) diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index 6cded828c25f..3223b0564e6c 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -645,7 +645,7 @@ LazyValueInfoImpl::solveBlockValueImpl(Value *Val, BasicBlock *BB) { // instruction is placed, even if it could legally be hoisted much higher. // That is unfortunate. PointerType *PT = dyn_cast(BBI->getType()); - if (PT && isKnownNonZero(BBI, DL)) + if (PT && isKnownNonZero(BBI, /*Depth=*/0, DL)) return ValueLatticeElement::getNot(ConstantPointerNull::get(PT)); if (BBI->getType()->isIntegerTy()) { @@ -1863,7 +1863,8 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C, Module *M = CxtI->getModule(); const DataLayout &DL = M->getDataLayout(); if (V->getType()->isPointerTy() && C->isNullValue() && - isKnownNonZero(V->stripPointerCastsSameRepresentation(), DL)) { + isKnownNonZero(V->stripPointerCastsSameRepresentation(), /*Depth=*/0, + DL)) { if (Pred == ICmpInst::ICMP_EQ) return LazyValueInfo::False; else if (Pred == ICmpInst::ICMP_NE) diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index 5916d2ab48ec..b5403408cf2a 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -99,7 +99,8 @@ static bool isDereferenceableAndAlignedPointer( CheckForFreed)); if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) && !CheckForFreed) - if (!CheckForNonNull || isKnownNonZero(V, DL, 0, AC, CtxI, DT)) { + if (!CheckForNonNull || + isKnownNonZero(V, /*Depth=*/0, SimplifyQuery(DL, DT, AC, CtxI))) { // As we recursed through GEPs to get here, we've incrementally checked // that each step advanced by a multiple of the alignment. If our base is // properly aligned, then the original offset accessed must also be. @@ -133,7 +134,8 @@ static bool isDereferenceableAndAlignedPointer( if (getObjectSize(V, ObjSize, DL, TLI, Opts)) { APInt KnownDerefBytes(Size.getBitWidth(), ObjSize); if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) && - isKnownNonZero(V, DL, 0, AC, CtxI, DT) && !V->canBeFreed()) { + isKnownNonZero(V, /*Depth=*/0, SimplifyQuery(DL, DT, AC, CtxI)) && + !V->canBeFreed()) { // As we recursed through GEPs to get here, we've incrementally // checked that each step advanced by a multiple of the alignment. If // our base is properly aligned, then the original offset accessed diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 95440dda3b4c..1c98b0295e52 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -6900,7 +6900,7 @@ const ConstantRange &ScalarEvolution::getRangeRef( uint64_t Rem = MaxVal.urem(Align); MaxVal -= APInt(BitWidth, Rem); APInt MinVal = APInt::getZero(BitWidth); - if (llvm::isKnownNonZero(V, DL)) + if (llvm::isKnownNonZero(V, /*Depth=*/0, DL)) MinVal = Align; ConservativeResult = ConservativeResult.intersectWith( ConstantRange::getNonEmpty(MinVal, MaxVal + 1), RangeType); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index ca257cc6aefd..b83e7e6769c2 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -274,16 +274,6 @@ bool llvm::isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL, static bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth, const SimplifyQuery &Q); -static bool isKnownNonZero(const Value *V, unsigned Depth, - const SimplifyQuery &Q); - -bool llvm::isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth, - AssumptionCache *AC, const Instruction *CxtI, - const DominatorTree *DT, bool UseInstrInfo) { - return ::isKnownNonZero( - V, Depth, SimplifyQuery(DL, DT, AC, safeCxtI(V, CxtI), UseInstrInfo)); -} - bool llvm::isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth) { return computeKnownBits(V, Depth, SQ).isNonNegative(); @@ -298,7 +288,7 @@ bool llvm::isKnownPositive(const Value *V, const SimplifyQuery &SQ, // this updated. KnownBits Known = computeKnownBits(V, Depth, SQ); return Known.isNonNegative() && - (Known.isNonZero() || ::isKnownNonZero(V, Depth, SQ)); + (Known.isNonZero() || isKnownNonZero(V, Depth, SQ)); } bool llvm::isKnownNegative(const Value *V, const SimplifyQuery &SQ, @@ -3093,11 +3083,12 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth, return false; } -bool isKnownNonZero(const Value *V, unsigned Depth, const SimplifyQuery &Q) { +bool llvm::isKnownNonZero(const Value *V, unsigned Depth, + const SimplifyQuery &Q) { auto *FVTy = dyn_cast(V->getType()); APInt DemandedElts = FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1); - return isKnownNonZero(V, DemandedElts, Depth, Q); + return ::isKnownNonZero(V, DemandedElts, Depth, Q); } /// If the pair of operators are the same invertible function, return the diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index e657872c3828..22dbb3198a9f 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -2314,7 +2314,7 @@ static bool despeculateCountZeros(IntrinsicInst *CountZeros, // Bail if the value is never zero. Use &Op = CountZeros->getOperandUse(0); - if (isKnownNonZero(Op, *DL)) + if (isKnownNonZero(Op, /*Depth=*/0, *DL)) return false; // The intrinsic will be sunk behind a compare against zero and branch. diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index ff680e998e71..f27d8d64a104 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -2452,8 +2452,9 @@ bool AANonNull::isImpliedByIR(Attributor &A, const IRPosition &IRP, } if (llvm::any_of(Worklist, [&](AA::ValueAndContext VAC) { - return !isKnownNonZero(VAC.getValue(), A.getDataLayout(), 0, AC, - VAC.getCtxI(), DT); + return !isKnownNonZero( + VAC.getValue(), /*Depth=*/0, + SimplifyQuery(A.getDataLayout(), DT, AC, VAC.getCtxI())); })) return false; diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 7ebf265e17ba..14612b251d1a 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -1175,7 +1175,7 @@ static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes, Value *RetVal = FlowsToReturn[i]; // If this value is locally known to be non-null, we're good - if (isKnownNonZero(RetVal, DL)) + if (isKnownNonZero(RetVal, /*Depth=*/0, DL)) continue; // Otherwise, we need to look upwards since we can't make any local diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index fa1e2280991f..07c50d866544 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -988,7 +988,7 @@ Instruction *InstCombinerImpl::foldAddWithConstant(BinaryOperator &Add) { if (C->isOne()) { if (match(Op0, m_ZExt(m_Add(m_Value(X), m_AllOnes())))) { const SimplifyQuery Q = SQ.getWithInstruction(&Add); - if (llvm::isKnownNonZero(X, DL, 0, Q.AC, Q.CxtI, Q.DT)) + if (llvm::isKnownNonZero(X, /*Depth=*/0, Q)) return new ZExtInst(X, Ty); } } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index c0cf1a7db726..2c0c4ee46e80 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1031,10 +1031,6 @@ static Value *foldUnsignedUnderflowCheck(ICmpInst *ZeroICmp, !ICmpInst::isEquality(EqPred)) return nullptr; - auto IsKnownNonZero = [&](Value *V) { - return isKnownNonZero(V, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT); - }; - ICmpInst::Predicate UnsignedPred; Value *A, *B; @@ -1043,9 +1039,9 @@ static Value *foldUnsignedUnderflowCheck(ICmpInst *ZeroICmp, match(ZeroCmpOp, m_c_Add(m_Specific(A), m_Value(B))) && (ZeroICmp->hasOneUse() || UnsignedICmp->hasOneUse())) { auto GetKnownNonZeroAndOther = [&](Value *&NonZero, Value *&Other) { - if (!IsKnownNonZero(NonZero)) + if (!isKnownNonZero(NonZero, /*Depth=*/0, Q)) std::swap(NonZero, Other); - return IsKnownNonZero(NonZero); + return isKnownNonZero(NonZero, /*Depth=*/0, Q); }; // Given ZeroCmpOp = (A + B) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index b1017f4d6bc1..b35ab8751a21 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -601,8 +601,8 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) { // then change the 'ZeroIsPoison' parameter to 'true' // because we know the zero behavior can't affect the result. if (!Known.One.isZero() || - isKnownNonZero(Op0, IC.getDataLayout(), 0, &IC.getAssumptionCache(), &II, - &IC.getDominatorTree())) { + isKnownNonZero(Op0, /*Depth=*/0, + IC.getSimplifyQuery().getWithInstruction(&II))) { if (!match(II.getArgOperand(1), m_One())) return IC.replaceOperand(II, 1, IC.Builder.getTrue()); } @@ -2061,7 +2061,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { // See if we can deduce non-null. if (!CI.hasRetAttr(Attribute::NonNull) && (Known.isNonZero() || - isKnownNonZero(II, DL, /*Depth*/ 0, &AC, II, &DT))) { + isKnownNonZero(II, /*Depth=*/0, + getSimplifyQuery().getWithInstruction(II)))) { CI.addRetAttr(Attribute::NonNull); Changed = true; } @@ -3648,7 +3649,8 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) { for (Value *V : Call.args()) { if (V->getType()->isPointerTy() && !Call.paramHasAttr(ArgNo, Attribute::NonNull) && - isKnownNonZero(V, DL, 0, &AC, &Call, &DT)) + isKnownNonZero(V, /*Depth=*/0, + getSimplifyQuery().getWithInstruction(&Call))) ArgNos.push_back(ArgNo); ArgNo++; } @@ -3828,7 +3830,8 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) { // isKnownNonNull -> nonnull attribute if (!GCR.hasRetAttr(Attribute::NonNull) && - isKnownNonZero(DerivedPtr, DL, 0, &AC, &Call, &DT)) { + isKnownNonZero(DerivedPtr, /*Depth=*/0, + getSimplifyQuery().getWithInstruction(&Call))) { GCR.addRetAttr(Attribute::NonNull); // We discovered new fact, re-check users. Worklist.pushUsersToWorkList(GCR); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 7292bb62702a..90550cdbdf89 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1273,12 +1273,12 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) { // if X non-zero and NoOverflow(X * Y) // (icmp eq/ne Y) - if (!XKnown.One.isZero() || isKnownNonZero(X, DL, 0, Q.AC, Q.CxtI, Q.DT)) + if (!XKnown.One.isZero() || isKnownNonZero(X, /*Depth=*/0, Q)) return new ICmpInst(Pred, Y, Cmp.getOperand(1)); // if Y non-zero and NoOverflow(X * Y) // (icmp eq/ne X) - if (!YKnown.One.isZero() || isKnownNonZero(Y, DL, 0, Q.AC, Q.CxtI, Q.DT)) + if (!YKnown.One.isZero() || isKnownNonZero(Y, /*Depth=*/0, Q)) return new ICmpInst(Pred, X, Cmp.getOperand(1)); } // Note, we are skipping cases: @@ -3087,7 +3087,7 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp, // (X + -1) X <=u C (if X is never null) if (Pred == CmpInst::ICMP_ULT && C2->isAllOnes()) { const SimplifyQuery Q = SQ.getWithInstruction(&Cmp); - if (llvm::isKnownNonZero(X, DL, 0, Q.AC, Q.CxtI, Q.DT)) + if (llvm::isKnownNonZero(X, /*Depth=*/0, Q)) return new ICmpInst(ICmpInst::ICMP_ULE, X, ConstantInt::get(Ty, C)); } @@ -4275,8 +4275,7 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0, // Look for: x & ~Mask pred ~Mask if (isMaskOrZero(X, /*Not=*/true, Q)) { - return !ICmpInst::isSigned(Pred) || - isKnownNonZero(X, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT); + return !ICmpInst::isSigned(Pred) || isKnownNonZero(X, /*Depth=*/0, Q); } return false; } @@ -4780,8 +4779,7 @@ static Instruction *foldICmpXorXX(ICmpInst &I, const SimplifyQuery &Q, // icmp (X ^ Y_NonZero) s>= X --> icmp (X ^ Y_NonZero) s> X // icmp (X ^ Y_NonZero) s<= X --> icmp (X ^ Y_NonZero) s< X CmpInst::Predicate PredOut = CmpInst::getStrictPredicate(Pred); - if (PredOut != Pred && - isKnownNonZero(A, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + if (PredOut != Pred && isKnownNonZero(A, /*Depth=*/0, Q)) return new ICmpInst(PredOut, Op0, Op1); return nullptr; @@ -5064,11 +5062,11 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I, return new ICmpInst(Pred, C, D); // (A - B) u>=/u< A --> B u>/u<= A iff B != 0 if (A == Op1 && (Pred == ICmpInst::ICMP_UGE || Pred == ICmpInst::ICMP_ULT) && - isKnownNonZero(B, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + isKnownNonZero(B, /*Depth=*/0, Q)) return new ICmpInst(CmpInst::getFlippedStrictnessPredicate(Pred), B, A); // C u<=/u> (C - D) --> C u= D iff B != 0 if (C == Op0 && (Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_UGT) && - isKnownNonZero(D, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + isKnownNonZero(D, /*Depth=*/0, Q)) return new ICmpInst(CmpInst::getFlippedStrictnessPredicate(Pred), C, D); // icmp (A-B), (C-B) -> icmp A, C for equalities or if there is no overflow. @@ -5110,14 +5108,13 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I, // X * Z eq/ne Y * Z -> X eq/ne Y if (ZKnown.countMaxTrailingZeros() == 0) return new ICmpInst(Pred, X, Y); - NonZero = !ZKnown.One.isZero() || - isKnownNonZero(Z, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT); + NonZero = !ZKnown.One.isZero() || isKnownNonZero(Z, /*Depth=*/0, Q); // if Z != 0 and nsw(X * Z) and nsw(Y * Z) // X * Z eq/ne Y * Z -> X eq/ne Y if (NonZero && BO0 && BO1 && Op0HasNSW && Op1HasNSW) return new ICmpInst(Pred, X, Y); } else - NonZero = isKnownNonZero(Z, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT); + NonZero = isKnownNonZero(Z, /*Depth=*/0, Q); // If Z != 0 and nuw(X * Z) and nuw(Y * Z) // X * Z u{lt/le/gt/ge}/eq/ne Y * Z -> X u{lt/le/gt/ge}/eq/ne Y diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp index 46bca4b722a0..9838e2aa9f3a 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -1537,7 +1537,8 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) { for (unsigned I = 0, E = PN.getNumIncomingValues(); I != E; ++I) { Instruction *CtxI = PN.getIncomingBlock(I)->getTerminator(); Value *VA = PN.getIncomingValue(I); - if (isKnownNonZero(VA, DL, 0, &AC, CtxI, &DT)) { + if (isKnownNonZero(VA, 0, + getSimplifyQuery().getWithInstruction(CtxI))) { if (!NonZeroConst) NonZeroConst = getAnyNonZeroConstInt(PN); if (NonZeroConst != VA) { diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 7c40fb4fc860..4cfafa7ac800 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1431,7 +1431,7 @@ Instruction *InstCombinerImpl::foldFBinOpOfIntCastsFromSign( if (OpsKnown[OpNo].hasKnownBits() && OpsKnown[OpNo].getKnownBits(SQ).isNonZero()) return true; - return isKnownNonZero(IntOps[OpNo], SQ.DL); + return isKnownNonZero(IntOps[OpNo], /*Depth=*/0, SQ); }; auto IsNonNeg = [&](unsigned OpNo) -> bool { diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index ee3531bbd68d..a72b0ee9a08e 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -1281,7 +1281,7 @@ struct MemorySanitizerVisitor : public InstVisitor { // ignored. return; } - if (llvm::isKnownNonZero(ConvertedShadow, DL)) { + if (llvm::isKnownNonZero(ConvertedShadow, /*Depth=*/0, DL)) { // Copy origin as the value is definitely uninitialized. paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize, OriginAlignment); @@ -1427,7 +1427,7 @@ struct MemorySanitizerVisitor : public InstVisitor { // Skip, value is initialized or const shadow is ignored. continue; } - if (llvm::isKnownNonZero(ConvertedShadow, DL)) { + if (llvm::isKnownNonZero(ConvertedShadow, /*Depth=*/0, DL)) { // Report as the value is definitely uninitialized. insertWarningFn(IRB, ShadowData.Origin); if (!MS.Recover) diff --git a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index adcf161b313b..f376b5f7d68d 100644 --- a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -459,7 +459,7 @@ static void convertMetadataToAssumes(LoadInst *LI, Value *Val, // we can only do this if the value is known non-poison. if (AC && LI->getMetadata(LLVMContext::MD_nonnull) && LI->getMetadata(LLVMContext::MD_noundef) && - !isKnownNonZero(Val, DL, 0, AC, LI, DT)) + !isKnownNonZero(Val, /*Depth=*/0, SimplifyQuery(DL, DT, AC, LI))) addAssumeNonNull(AC, LI); } diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 2e68a9c01898..7e9e91606fe2 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -305,7 +305,7 @@ static void annotateNonNullAndDereferenceable(CallInst *CI, ArrayRef A if (ConstantInt *LenC = dyn_cast(Size)) { annotateNonNullNoUndefBasedOnAccess(CI, ArgNos); annotateDereferenceableBytes(CI, ArgNos, LenC->getZExtValue()); - } else if (isKnownNonZero(Size, DL)) { + } else if (isKnownNonZero(Size, /*Depth=*/0, DL)) { annotateNonNullNoUndefBasedOnAccess(CI, ArgNos); const APInt *X, *Y; uint64_t DerefMin = 1; @@ -394,7 +394,7 @@ Value *LibCallSimplifier::optimizeStrNCat(CallInst *CI, IRBuilderBase &B) { Value *Size = CI->getArgOperand(2); uint64_t Len; annotateNonNullNoUndefBasedOnAccess(CI, 0); - if (isKnownNonZero(Size, DL)) + if (isKnownNonZero(Size, /*Depth=*/0, DL)) annotateNonNullNoUndefBasedOnAccess(CI, 1); // We don't do anything if length is not constant. @@ -613,7 +613,7 @@ Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilderBase &B) { if (Str1P == Str2P) // strncmp(x,x,n) -> 0 return ConstantInt::get(CI->getType(), 0); - if (isKnownNonZero(Size, DL)) + if (isKnownNonZero(Size, /*Depth=*/0, DL)) annotateNonNullNoUndefBasedOnAccess(CI, {0, 1}); // Get the length argument if it is constant. uint64_t Length; @@ -749,7 +749,7 @@ Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilderBase &B) { Value *LibCallSimplifier::optimizeStrLCpy(CallInst *CI, IRBuilderBase &B) { Value *Size = CI->getArgOperand(2); - if (isKnownNonZero(Size, DL)) + if (isKnownNonZero(Size, /*Depth=*/0, DL)) // Like snprintf, the function stores into the destination only when // the size argument is nonzero. annotateNonNullNoUndefBasedOnAccess(CI, 0); @@ -833,7 +833,7 @@ Value *LibCallSimplifier::optimizeStringNCpy(CallInst *CI, bool RetEnd, Value *Src = CI->getArgOperand(1); Value *Size = CI->getArgOperand(2); - if (isKnownNonZero(Size, DL)) { + if (isKnownNonZero(Size, /*Depth=*/0, DL)) { // Both st{p,r}ncpy(D, S, N) access the source and destination arrays // only when N is nonzero. annotateNonNullNoUndefBasedOnAccess(CI, 0); @@ -926,7 +926,7 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B, Type *CharTy = B.getIntNTy(CharSize); if (isOnlyUsedInZeroEqualityComparison(CI) && - (!Bound || isKnownNonZero(Bound, DL))) { + (!Bound || isKnownNonZero(Bound, /*Depth=*/0, DL))) { // Fold strlen: // strlen(x) != 0 --> *x != 0 // strlen(x) == 0 --> *x == 0 @@ -1047,7 +1047,7 @@ Value *LibCallSimplifier::optimizeStrNLen(CallInst *CI, IRBuilderBase &B) { if (Value *V = optimizeStringLength(CI, B, 8, Bound)) return V; - if (isKnownNonZero(Bound, DL)) + if (isKnownNonZero(Bound, /*Depth=*/0, DL)) annotateNonNullNoUndefBasedOnAccess(CI, 0); return nullptr; } @@ -1291,7 +1291,7 @@ Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilderBase &B) { Value *SrcStr = CI->getArgOperand(0); Value *Size = CI->getArgOperand(2); - if (isKnownNonZero(Size, DL)) { + if (isKnownNonZero(Size, /*Depth=*/0, DL)) { annotateNonNullNoUndefBasedOnAccess(CI, 0); if (isOnlyUsedInEqualityComparison(CI, SrcStr)) return memChrToCharCompare(CI, Size, B, DL); @@ -2976,7 +2976,7 @@ Value *LibCallSimplifier::optimizeStrToInt(CallInst *CI, IRBuilderBase &B, // It would be readonly too, except that it still may write to errno. CI->addParamAttr(0, Attribute::NoCapture); EndPtr = nullptr; - } else if (!isKnownNonZero(EndPtr, DL)) + } else if (!isKnownNonZero(EndPtr, /*Depth=*/0, DL)) return nullptr; StringRef Str; @@ -3402,7 +3402,7 @@ Value *LibCallSimplifier::optimizeSnPrintF(CallInst *CI, IRBuilderBase &B) { return V; } - if (isKnownNonZero(CI->getOperand(1), DL)) + if (isKnownNonZero(CI->getOperand(1), /*Depth=*/0, DL)) annotateNonNullNoUndefBasedOnAccess(CI, 0); return nullptr; } diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index 653e0ff7a3ec..e0e2f50c89ad 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -885,7 +885,8 @@ bool VectorCombine::scalarizeVPIntrinsic(Instruction &I) { else SafeToSpeculate = isSafeToSpeculativelyExecuteWithOpcode( *FunctionalOpcode, &VPI, nullptr, &AC, &DT); - if (!SafeToSpeculate && !isKnownNonZero(EVL, *DL, 0, &AC, &VPI, &DT)) + if (!SafeToSpeculate && + !isKnownNonZero(EVL, /*Depth=*/0, SimplifyQuery(*DL, &DT, &AC, &VPI))) return false; Value *ScalarVal = diff --git a/llvm/test/Transforms/InstCombine/icmp-dom.ll b/llvm/test/Transforms/InstCombine/icmp-dom.ll index f4b9022d1434..83cedd5ea9cb 100644 --- a/llvm/test/Transforms/InstCombine/icmp-dom.ll +++ b/llvm/test/Transforms/InstCombine/icmp-dom.ll @@ -403,3 +403,134 @@ truelabel: falselabel: ret i8 0 } + +define i1 @and_mask1_eq(i32 %conv) { +; CHECK-LABEL: @and_mask1_eq( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: ret i1 false +; CHECK: else: +; CHECK-NEXT: ret i1 false +; +entry: + %and = and i32 %conv, 1 + %cmp = icmp eq i32 %and, 0 + br i1 %cmp, label %then, label %else + +then: + ret i1 0 + +else: + %and1 = and i32 %conv, 3 + %cmp1 = icmp eq i32 %and1, 0 + ret i1 %cmp1 +} + +define i1 @and_mask1_ne(i32 %conv) { +; CHECK-LABEL: @and_mask1_ne( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: ret i1 false +; CHECK: else: +; CHECK-NEXT: ret i1 true +; +entry: + %and = and i32 %conv, 1 + %cmp = icmp eq i32 %and, 0 + br i1 %cmp, label %then, label %else + +then: + ret i1 0 + +else: + %and1 = and i32 %conv, 3 + %cmp1 = icmp ne i32 %and1, 0 + ret i1 %cmp1 +} + +define i1 @and_mask2(i32 %conv) { +; CHECK-LABEL: @and_mask2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV:%.*]], 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: ret i1 false +; CHECK: else: +; CHECK-NEXT: [[AND1:%.*]] = and i32 [[CONV]], 3 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[AND1]], 0 +; CHECK-NEXT: ret i1 [[CMP1]] +; +entry: + %and = and i32 %conv, 4 + %cmp = icmp eq i32 %and, 0 + br i1 %cmp, label %then, label %else + +then: + ret i1 0 + +else: + %and1 = and i32 %conv, 3 + %cmp1 = icmp eq i32 %and1, 0 + ret i1 %cmp1 +} + +; TODO: %cmp1 can be folded into false. + +define i1 @and_mask3(i32 %conv) { +; CHECK-LABEL: @and_mask3( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV:%.*]], 3 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: ret i1 false +; CHECK: else: +; CHECK-NEXT: [[AND1:%.*]] = and i32 [[CONV]], 7 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[AND1]], 0 +; CHECK-NEXT: ret i1 [[CMP1]] +; +entry: + %and = and i32 %conv, 3 + %cmp = icmp eq i32 %and, 0 + br i1 %cmp, label %then, label %else + +then: + ret i1 0 + +else: + %and1 = and i32 %conv, 7 + %cmp1 = icmp eq i32 %and1, 0 + ret i1 %cmp1 +} + +define i1 @and_mask4(i32 %conv) { +; CHECK-LABEL: @and_mask4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV:%.*]], 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: ret i1 false +; CHECK: else: +; CHECK-NEXT: ret i1 false +; +entry: + %and = and i32 %conv, 4 + %cmp = icmp eq i32 %and, 0 + br i1 %cmp, label %then, label %else + +then: + ret i1 0 + +else: + %and1 = and i32 %conv, 7 + %cmp1 = icmp eq i32 %and1, 0 + ret i1 %cmp1 +} diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index b4d2270d7070..6b1044876d36 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -2055,7 +2055,8 @@ TEST_F(ValueTrackingTest, isNonZeroRecurrence) { )"); const DataLayout &DL = M->getDataLayout(); AssumptionCache AC(*F); - EXPECT_TRUE(isKnownNonZero(A, DL, 0, &AC, CxtI)); + EXPECT_TRUE(isKnownNonZero(A, /*Depth=*/0, + SimplifyQuery(DL, /*DT=*/nullptr, &AC, CxtI))); } TEST_F(ValueTrackingTest, KnownNonZeroFromDomCond) { @@ -2078,8 +2079,10 @@ TEST_F(ValueTrackingTest, KnownNonZeroFromDomCond) { AssumptionCache AC(*F); DominatorTree DT(*F); const DataLayout &DL = M->getDataLayout(); - EXPECT_EQ(isKnownNonZero(A, DL, 0, &AC, CxtI, &DT), true); - EXPECT_EQ(isKnownNonZero(A, DL, 0, &AC, CxtI2, &DT), false); + const SimplifyQuery SQ(DL, &DT, &AC); + EXPECT_EQ(isKnownNonZero(A, /*Depth=*/0, SQ.getWithInstruction(CxtI)), true); + EXPECT_EQ(isKnownNonZero(A, /*Depth=*/0, SQ.getWithInstruction(CxtI2)), + false); } TEST_F(ValueTrackingTest, KnownNonZeroFromDomCond2) { @@ -2102,8 +2105,10 @@ TEST_F(ValueTrackingTest, KnownNonZeroFromDomCond2) { AssumptionCache AC(*F); DominatorTree DT(*F); const DataLayout &DL = M->getDataLayout(); - EXPECT_EQ(isKnownNonZero(A, DL, 0, &AC, CxtI, &DT), true); - EXPECT_EQ(isKnownNonZero(A, DL, 0, &AC, CxtI2, &DT), false); + const SimplifyQuery SQ(DL, &DT, &AC); + EXPECT_EQ(isKnownNonZero(A, /*Depth=*/0, SQ.getWithInstruction(CxtI)), true); + EXPECT_EQ(isKnownNonZero(A, /*Depth=*/0, SQ.getWithInstruction(CxtI2)), + false); } TEST_F(ValueTrackingTest, IsImpliedConditionAnd) { -- GitLab From 6f1e23b47d428d792866993ed26f4173d479d43d Mon Sep 17 00:00:00 2001 From: Kunwar Grover Date: Fri, 12 Apr 2024 17:56:46 +0200 Subject: [PATCH 080/464] [MLIR][Bufferization] Choose default memory space in tensor copy insertion (#88500) Tensor copy insertion currently uses memory_space = 0 when creating a tensor copy using alloc_tensor. This memory space should instead be the default memory space provided in bufferization options. --- .../Dialect/Bufferization/IR/BufferizableOpInterface.cpp | 7 ++++--- .../Bufferization/Transforms/tensor-copy-insertion.mlir | 6 +++--- mlir/test/Dialect/SparseTensor/sparse_sddmm.mlir | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp index 55c9299c58ef..c2b2b99fc008 100644 --- a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp +++ b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp @@ -193,10 +193,11 @@ FailureOr bufferization::allocateTensorForShapedValue( FailureOr copyBufferType = getBufferType(tensor, options); if (failed(copyBufferType)) return failure(); - Attribute memorySpace = copyBufferType->getMemorySpace(); + std::optional memorySpace = copyBufferType->getMemorySpace(); if (!memorySpace) - memorySpace = b.getI64IntegerAttr(0); - allocTensorOp.setMemorySpaceAttr(memorySpace); + memorySpace = options.defaultMemorySpaceFn(tensorType); + if (memorySpace.has_value()) + allocTensorOp.setMemorySpaceAttr(memorySpace.value()); return allocTensorOp.getResult(); } diff --git a/mlir/test/Dialect/Bufferization/Transforms/tensor-copy-insertion.mlir b/mlir/test/Dialect/Bufferization/Transforms/tensor-copy-insertion.mlir index 72cf08df5978..55dcca193cbe 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/tensor-copy-insertion.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/tensor-copy-insertion.mlir @@ -34,7 +34,7 @@ func.func @do_not_copy_undefined_tensor(%f: f32, %idx: index) { // The second alloc_tensor should not have a copy operand. // CHECK: bufferization.alloc_tensor() : tensor<5xf32> - // CHECK: bufferization.alloc_tensor() {memory_space = 0 : i64} : tensor<5xf32> + // CHECK: bufferization.alloc_tensor() : tensor<5xf32> %0 = bufferization.alloc_tensor() : tensor<5xf32> %1 = tensor.insert %f into %0[%idx] : tensor<5xf32> return %0, %1 : tensor<5xf32>, tensor<5xf32> @@ -46,7 +46,7 @@ func.func @do_not_copy_undefined_tensor(%f: f32, %idx: index) func.func @do_not_copy_when_overwritten(%t: tensor<5xf32>, %f: f32) -> (tensor<5xf32>, tensor<5xf32>) { - // CHECK: %[[alloc:.*]] = bufferization.alloc_tensor() {memory_space = 0 : i64} : tensor<5xf32> + // CHECK: %[[alloc:.*]] = bufferization.alloc_tensor() : tensor<5xf32> // CHECK: linalg.generic {{.*}} outs(%[[alloc]] : tensor<5xf32>) %r = linalg.generic { indexing_maps = [affine_map<(d0) -> (d0)>], @@ -65,7 +65,7 @@ func.func @do_not_copy_when_result_not_read(%t: tensor<5xf32>, %f: f32) -> (tensor<3xf32>) { %0 = tensor.extract_slice %t[0][3][1] : tensor<5xf32> to tensor<3xf32> - // CHECK: %[[alloc:.*]] = bufferization.alloc_tensor() {memory_space = 0 : i64} : tensor<3xf32> + // CHECK: %[[alloc:.*]] = bufferization.alloc_tensor() : tensor<3xf32> // CHECK: linalg.generic {{.*}} outs(%[[alloc]] : tensor<3xf32>) %r = linalg.generic { indexing_maps = [affine_map<(d0) -> (d0)>], diff --git a/mlir/test/Dialect/SparseTensor/sparse_sddmm.mlir b/mlir/test/Dialect/SparseTensor/sparse_sddmm.mlir index 6fc2db481c6f..fcd69bea426d 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_sddmm.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_sddmm.mlir @@ -63,7 +63,7 @@ func.func @fold_yield_direct_zero() -> tensor<32xf64> { // CHECK-DAG: %[[VAL_5:.*]] = arith.constant 1 : index // CHECK-DAG: %[[VAL_6:.*]] = arith.constant dense<0.000000e+00> : tensor<8x8xf64> // CHECK-DAG: %[[VAL_7:.*]] = bufferization.alloc_tensor() copy(%[[VAL_6]]) : tensor<8x8xf64> -// CHECK-DAG: %[[VAL_8:.*]] = bufferization.alloc_tensor() copy(%[[VAL_6]]) {memory_space = 0 : i64} : tensor<8x8xf64> +// CHECK-DAG: %[[VAL_8:.*]] = bufferization.alloc_tensor() copy(%[[VAL_6]]) : tensor<8x8xf64> // CHECK-DAG: %[[VAL_9:.*]] = bufferization.to_memref %[[VAL_1]] : memref<8x8xf64> // CHECK-DAG: %[[VAL_10:.*]] = bufferization.to_memref %[[VAL_2]] : memref<8x8xf64> // CHECK-DAG: %[[VAL_11:.*]] = sparse_tensor.positions %[[VAL_0]] {level = 0 : index} : tensor<8x8xf64, #sparse{{[0-9]*}}> to memref -- GitLab From b614e5b0340f783ad355899248c52cb22a04b014 Mon Sep 17 00:00:00 2001 From: Dominik Steenken Date: Fri, 12 Apr 2024 18:03:57 +0200 Subject: [PATCH 081/464] [SystemZ] Add missing (dis-)assembly tests. (#88498) ### Assembly Tests This adds assembly tests for ``` lcdfr, lndfr, lpdfr ``` ### Disassembly Tests This also adds a number of disassembly tests for the following menmonics: ``` cgit, cgrt, cit, clfit, clgit, clgrt, clgt, clrt, clt, crt, lcdfr, lndfr, lpdfr ``` For `cutfu` / `cu12`, it also adds a check for bad register choice. --- llvm/test/MC/Disassembler/SystemZ/insns.txt | 96 +++++++++++++++++++ .../MC/Disassembler/SystemZ/invalid-regs.txt | 7 ++ llvm/test/MC/SystemZ/insn-good.s | 30 ++++++ 3 files changed, 133 insertions(+) diff --git a/llvm/test/MC/Disassembler/SystemZ/insns.txt b/llvm/test/MC/Disassembler/SystemZ/insns.txt index f2f942ed5d36..23714dfc3a8e 100644 --- a/llvm/test/MC/Disassembler/SystemZ/insns.txt +++ b/llvm/test/MC/Disassembler/SystemZ/insns.txt @@ -2956,6 +2956,12 @@ # CHECK: cgib %r0, 0, 15, 0 0xec 0x0f 0x00 0x00 0x00 0xfc +# CHECK: cgit %r0, 0, 0 +0xec 0x00 0x00 0x00 0x00 0x70 + +# CHECK: cgit %r0, 0, 15 +0xec 0x00 0x00 0x00 0xf0 0x70 + # CHECK: cgith %r0, 0 0xec 0x00 0x00 0x00 0x20 0x70 @@ -3052,6 +3058,12 @@ # CHECK: cgrb %r0, %r0, 15, 0 0xec 0x00 0x00 0x00 0xf0 0xe4 +# CHECK: cgrt %r0, %r1, 0 +0xb9 0x60 0x00 0x01 + +# CHECK: cgrt %r0, %r1, 15 +0xb9 0x60 0xf0 0x01 + # CHECK: cgrth %r0, %r1 0xb9 0x60 0x20 0x01 @@ -3430,6 +3442,12 @@ # CHECK: cih %r15, 0 0xcc 0xfd 0x00 0x00 0x00 0x00 +# CHECK: cit %r0, 0, 0 +0xec 0x00 0x00 0x00 0x00 0x72 + +# CHECK: cit %r0, 0, 15 +0xec 0x00 0x00 0x00 0xf0 0x72 + # CHECK: cith %r0, 0 0xec 0x00 0x00 0x00 0x20 0x72 @@ -3862,6 +3880,12 @@ # CHECK: clfi %r15, 0 0xc2 0xff 0x00 0x00 0x00 0x00 +# CHECK: clfit %r0, 0, 0 +0xec 0x00 0x00 0x00 0x00 0x73 + +# CHECK: clfit %r0, 0, 15 +0xec 0x00 0x00 0x00 0xf0 0x73 + # CHECK: clfith %r0, 0 0xec 0x00 0x00 0x00 0x20 0x73 @@ -3910,6 +3934,12 @@ # CHECK: clg %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x21 +# CHECK: clgit %r0, 0, 0 +0xec 0x00 0x00 0x00 0x00 0x71 + +# CHECK: clgit %r0, 0, 15 +0xec 0x00 0x00 0x00 0xf0 0x71 + # CHECK: clgith %r0, 0 0xec 0x00 0x00 0x00 0x20 0x71 @@ -4447,6 +4477,12 @@ # CHECK: clrb %r0, %r0, 15, 0 0xec 0x00 0x00 0x00 0xf0 0xf7 +# CHECK: clgrt %r0, %r1, 0 +0xb9 0x61 0x00 0x01 + +# CHECK: clgrt %r0, %r1, 15 +0xb9 0x61 0xf0 0x01 + # CHECK: clgrth %r0, %r1 0xb9 0x61 0x20 0x01 @@ -4465,6 +4501,12 @@ # CHECK: clgrtle %r0, %r1 0xb9 0x61 0xc0 0x01 +# CHECK: clrt %r0, %r1, 0 +0xb9 0x73 0x00 0x01 + +# CHECK: clrt %r0, %r1, 15 +0xb9 0x73 0xf0 0x01 + # CHECK: clrth %r0, %r1 0xb9 0x73 0x20 0x01 @@ -4483,6 +4525,12 @@ # CHECK: clrtle %r0, %r1 0xb9 0x73 0xc0 0x01 +# CHECK: clt %r0, 0, -524288 +0xeb 0x00 0x00 0x00 0x80 0x23 + +# CHECK: clt %r0, 15, 32768 +0xeb 0x0f 0x00 0x00 0x08 0x23 + # CHECK: clth %r0, -524288 0xeb 0x02 0x00 0x00 0x80 0x23 @@ -4525,6 +4573,12 @@ # CHECK: cltle %r1, 0 0xeb 0x1c 0x00 0x00 0x00 0x23 +# CHECK: clgt %r0, 0, -524288 +0xeb 0x00 0x00 0x00 0x80 0x2b + +# CHECK: clgt %r0, 15, 32768 +0xeb 0x0f 0x00 0x00 0x08 0x2b + # CHECK: clgth %r0, -524288 0xeb 0x02 0x00 0x00 0x80 0x2b @@ -4792,6 +4846,12 @@ # CHECK: crdte %r4, %r5, %r6, 7 0xb9 0x8f 0x57 0x46 +# CHECK: crt %r0, %r1, 0 +0xb9 0x72 0x00 0x01 + +# CHECK: crt %r0, %r1, 15 +0xb9 0x72 0xf0 0x01 + # CHECK: crth %r0, %r1 0xb9 0x72 0x20 0x01 @@ -7972,6 +8032,18 @@ # CHECK: lcdbr %f15, %f9 0xb3 0x13 0x00 0xf9 +# CHECK: lcdfr %f0, %f9 +0xb3 0x73 0x00 0x09 + +# CHECK: lcdfr %f0, %f15 +0xb3 0x73 0x00 0x0f + +# CHECK: lcdfr %f15, %f0 +0xb3 0x73 0x00 0xf0 + +# CHECK: lcdfr %f15, %f9 +0xb3 0x73 0x00 0xf9 + # CHECK: lcdr %f0, %f9 0x23 0x09 @@ -9570,6 +9642,18 @@ # CHECK: lndbr %f15, %f9 0xb3 0x11 0x00 0xf9 +# CHECK: lndfr %f0, %f9 +0xb3 0x71 0x00 0x09 + +# CHECK: lndfr %f0, %f15 +0xb3 0x71 0x00 0x0f + +# CHECK: lndfr %f15, %f0 +0xb3 0x71 0x00 0xf0 + +# CHECK: lndfr %f15, %f9 +0xb3 0x71 0x00 0xf9 + # CHECK: lndr %f0, %f9 0x21 0x09 @@ -9909,6 +9993,18 @@ # CHECK: lpdbr %f15, %f9 0xb3 0x10 0x00 0xf9 +# CHECK: lpdfr %f0, %f9 +0xb3 0x70 0x00 0x09 + +# CHECK: lpdfr %f0, %f15 +0xb3 0x70 0x00 0x0f + +# CHECK: lpdfr %f15, %f0 +0xb3 0x70 0x00 0xf0 + +# CHECK: lpdfr %f15, %f9 +0xb3 0x70 0x00 0xf9 + # CHECK: lpdg %r0, 0, 0 0xc8 0x05 0x00 0x00 0x00 0x00 diff --git a/llvm/test/MC/Disassembler/SystemZ/invalid-regs.txt b/llvm/test/MC/Disassembler/SystemZ/invalid-regs.txt index 12440677ba34..0ce960d5ddcc 100644 --- a/llvm/test/MC/Disassembler/SystemZ/invalid-regs.txt +++ b/llvm/test/MC/Disassembler/SystemZ/invalid-regs.txt @@ -20,3 +20,10 @@ # CHECK-NEXT: 0xb9 0x97 0x00 0x18 # CHECK-NEXT: ^ 0xb9 0x97 0x00 0x18 + +# This would be "cutfu %r1, %r2", but %r1 is invalid. +# +# CHECK-NEXT: warning: invalid instruction encoding +# CHECK-NEXT: 0xb2 0xa7 0x00 0x12 +# CHECK-NEXT: ^ +0xb2 0xa7 0x00 0x12 diff --git a/llvm/test/MC/SystemZ/insn-good.s b/llvm/test/MC/SystemZ/insn-good.s index 91120f7f97aa..f5dd672f9dd8 100644 --- a/llvm/test/MC/SystemZ/insn-good.s +++ b/llvm/test/MC/SystemZ/insn-good.s @@ -9038,6 +9038,36 @@ lcdbr %f15,%f0 lcdbr %f15,%f9 +#CHECK: lcdfr %f0, %f9 # encoding: [0xb3,0x73,0x00,0x09] +#CHECK: lcdfr %f0, %f15 # encoding: [0xb3,0x73,0x00,0x0f] +#CHECK: lcdfr %f15, %f0 # encoding: [0xb3,0x73,0x00,0xf0] +#CHECK: lcdfr %f15, %f9 # encoding: [0xb3,0x73,0x00,0xf9] + + lcdfr %f0,%f9 + lcdfr %f0,%f15 + lcdfr %f15,%f0 + lcdfr %f15,%f9 + +#CHECK: lndfr %f0, %f9 # encoding: [0xb3,0x71,0x00,0x09] +#CHECK: lndfr %f0, %f15 # encoding: [0xb3,0x71,0x00,0x0f] +#CHECK: lndfr %f15, %f0 # encoding: [0xb3,0x71,0x00,0xf0] +#CHECK: lndfr %f15, %f9 # encoding: [0xb3,0x71,0x00,0xf9] + + lndfr %f0,%f9 + lndfr %f0,%f15 + lndfr %f15,%f0 + lndfr %f15,%f9 + +#CHECK: lpdfr %f0, %f9 # encoding: [0xb3,0x70,0x00,0x09] +#CHECK: lpdfr %f0, %f15 # encoding: [0xb3,0x70,0x00,0x0f] +#CHECK: lpdfr %f15, %f0 # encoding: [0xb3,0x70,0x00,0xf0] +#CHECK: lpdfr %f15, %f9 # encoding: [0xb3,0x70,0x00,0xf9] + + lpdfr %f0,%f9 + lpdfr %f0,%f15 + lpdfr %f15,%f0 + lpdfr %f15,%f9 + #CHECK: lcdr %f0, %f9 # encoding: [0x23,0x09] #CHECK: lcdr %f0, %f15 # encoding: [0x23,0x0f] #CHECK: lcdr %f15, %f0 # encoding: [0x23,0xf0] -- GitLab From b794dc23255505dd7735f995b8ff1192305a072e Mon Sep 17 00:00:00 2001 From: Dominik Steenken Date: Fri, 12 Apr 2024 18:05:30 +0200 Subject: [PATCH 082/464] [SystemZ] Add custom handling of legal vectors with reduce-add. (#88495) This commit skips the expansion of the `vector.reduce.add` intrinsic on vector-enabled SystemZ targets in order to introduce custom handling of `vector.reduce.add` for legal vector types using the VSUM instructions. This is limited to full vectors with scalar types up to `i32` due to performance concerns. It also adds testing for the generation of such custom handling, and adapts the related cost computation, as well as the testing for that. The expected result is a performance boost in certain benchmarks that make heavy use of `vector.reduce.add` with other benchmarks remaining constant. For instance, the assembly for `vector.reduce.add<4 x i32>` changes from ```hlasm vmrlg %v0, %v24, %v24 vaf %v0, %v24, %v0 vrepf %v1, %v0, 1 vaf %v0, %v0, %v1 vlgvf %r2, %v0, 0 ``` to ```hlasm vgbm %v0, 0 vsumqf %v0, %v24, %v0 vlgvf %r2, %v0, 3 ``` --- .../Target/SystemZ/SystemZISelLowering.cpp | 43 +++ llvm/lib/Target/SystemZ/SystemZISelLowering.h | 1 + .../SystemZ/SystemZTargetTransformInfo.cpp | 31 +- .../SystemZ/SystemZTargetTransformInfo.h | 2 + .../Analysis/CostModel/SystemZ/reduce-add.ll | 24 +- .../test/CodeGen/SystemZ/vec-reduce-add-01.ll | 289 ++++++++++++++++++ 6 files changed, 373 insertions(+), 17 deletions(-) create mode 100644 llvm/test/CodeGen/SystemZ/vec-reduce-add-01.ll diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index efffd669d268..3b3057f8fe96 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -16,6 +16,7 @@ #include "SystemZMachineFunctionInfo.h" #include "SystemZTargetMachine.h" #include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" @@ -23,6 +24,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsS390.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/KnownBits.h" #include #include @@ -451,6 +453,10 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, setOperationAction(ISD::SRL, VT, Custom); setOperationAction(ISD::ROTL, VT, Custom); + // Add ISD::VECREDUCE_ADD as custom in order to implement + // it with VZERO+VSUM + setOperationAction(ISD::VECREDUCE_ADD, VT, Custom); + // Map SETCCs onto one of VCE, VCH or VCHL, swapping the operands // and inverting the result as necessary. setOperationAction(ISD::SETCC, VT, Custom); @@ -6167,6 +6173,8 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, return lowerOR(Op, DAG); case ISD::CTPOP: return lowerCTPOP(Op, DAG); + case ISD::VECREDUCE_ADD: + return lowerVECREDUCE_ADD(Op, DAG); case ISD::ATOMIC_FENCE: return lowerATOMIC_FENCE(Op, DAG); case ISD::ATOMIC_SWAP: @@ -9600,3 +9608,38 @@ SDValue SystemZTargetLowering::lowerGET_ROUNDING(SDValue Op, return DAG.getMergeValues({RetVal, Chain}, dl); } + +SDValue SystemZTargetLowering::lowerVECREDUCE_ADD(SDValue Op, + SelectionDAG &DAG) const { + EVT VT = Op.getValueType(); + Op = Op.getOperand(0); + EVT OpVT = Op.getValueType(); + + assert(OpVT.isVector() && "Operand type for VECREDUCE_ADD is not a vector."); + + SDLoc DL(Op); + + // load a 0 vector for the third operand of VSUM. + SDValue Zero = DAG.getSplatBuildVector(OpVT, DL, DAG.getConstant(0, DL, VT)); + + // execute VSUM. + switch (OpVT.getScalarSizeInBits()) { + case 8: + case 16: + Op = DAG.getNode(SystemZISD::VSUM, DL, MVT::v4i32, Op, Zero); + LLVM_FALLTHROUGH; + case 32: + case 64: + Op = DAG.getNode(SystemZISD::VSUM, DL, MVT::i128, Op, + DAG.getBitcast(Op.getValueType(), Zero)); + break; + case 128: + break; // VSUM over v1i128 should not happen and would be a noop + default: + llvm_unreachable("Unexpected scalar size."); + } + // Cast to original vector type, retrieve last element. + return DAG.getNode( + ISD::EXTRACT_VECTOR_ELT, DL, VT, DAG.getBitcast(OpVT, Op), + DAG.getConstant(OpVT.getVectorNumElements() - 1, DL, MVT::i32)); +} diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index 7140287a886c..2290a7d62e89 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -696,6 +696,7 @@ private: SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; SDValue lowerOR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerCTPOP(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerVECREDUCE_ADD(SDValue Op, SelectionDAG &DAG) const; SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerATOMIC_LDST_I128(SDValue Op, SelectionDAG &DAG) const; SDValue lowerATOMIC_LOAD_OP(SDValue Op, SelectionDAG &DAG, diff --git a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp index 17e534f405c0..4c9e78c05dbc 100644 --- a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp @@ -19,6 +19,7 @@ #include "llvm/CodeGen/CostTable.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" @@ -1293,18 +1294,14 @@ getVectorIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, if (ID == Intrinsic::vector_reduce_add) { // Retrieve number and size of elements for the vector op. auto *VTy = cast(ParamTys.front()); - unsigned NumElements = VTy->getNumElements(); unsigned ScalarSize = VTy->getScalarSizeInBits(); // For scalar sizes >128 bits, we fall back to the generic cost estimate. if (ScalarSize > SystemZ::VectorBits) return -1; - // A single vector register can hold this many elements. - unsigned MaxElemsPerVector = SystemZ::VectorBits / ScalarSize; // This many vector regs are needed to represent the input elements (V). unsigned VectorRegsNeeded = getNumVectorRegs(VTy); // This many instructions are needed for the final sum of vector elems (S). - unsigned LastVectorHandling = - 2 * Log2_32_Ceil(std::min(NumElements, MaxElemsPerVector)); + unsigned LastVectorHandling = (ScalarSize < 32) ? 3 : 2; // We use vector adds to create a sum vector, which takes // V/2 + V/4 + ... = V - 1 operations. // Then, we need S operations to sum up the elements of that sum vector, @@ -1324,3 +1321,27 @@ SystemZTTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, return Cost; return BaseT::getIntrinsicInstrCost(ICA, CostKind); } + +bool SystemZTTIImpl::shouldExpandReduction(const IntrinsicInst *II) const { + // Always expand on Subtargets without vector instructions + if (!ST->hasVector()) + return true; + + // Always expand for operands that do not fill one vector reg + auto *Type = cast(II->getOperand(0)->getType()); + unsigned NumElts = Type->getNumElements(); + unsigned ScalarSize = Type->getScalarSizeInBits(); + unsigned MaxElts = SystemZ::VectorBits / ScalarSize; + if (NumElts < MaxElts) + return true; + + // Otherwise + switch (II->getIntrinsicID()) { + // Do not expand vector.reduce.add + case Intrinsic::vector_reduce_add: + // Except for i64, since the performance benefit is dubious there + return ScalarSize >= 64; + default: + return true; + } +} diff --git a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.h b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.h index 1d824d353d8f..696d887c1d5d 100644 --- a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.h @@ -127,6 +127,8 @@ public: InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind); + + bool shouldExpandReduction(const IntrinsicInst *II) const; /// @} }; diff --git a/llvm/test/Analysis/CostModel/SystemZ/reduce-add.ll b/llvm/test/Analysis/CostModel/SystemZ/reduce-add.ll index 061e5ece44a4..90b5b746c914 100644 --- a/llvm/test/Analysis/CostModel/SystemZ/reduce-add.ll +++ b/llvm/test/Analysis/CostModel/SystemZ/reduce-add.ll @@ -7,19 +7,19 @@ define void @reduce(ptr %src, ptr %dst) { ; CHECK: Cost Model: Found an estimated cost of 5 for instruction: %R8_64 = call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> %V8_64) ; CHECK: Cost Model: Found an estimated cost of 9 for instruction: %R16_64 = call i64 @llvm.vector.reduce.add.v16i64(<16 x i64> %V16_64) ; CHECK: Cost Model: Found an estimated cost of 2 for instruction: %R2_32 = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %V2_32) -; CHECK: Cost Model: Found an estimated cost of 4 for instruction: %R4_32 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %V4_32) -; CHECK: Cost Model: Found an estimated cost of 5 for instruction: %R8_32 = call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> %V8_32) -; CHECK: Cost Model: Found an estimated cost of 7 for instruction: %R16_32 = call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %V16_32) -; CHECK: Cost Model: Found an estimated cost of 2 for instruction: %R2_16 = call i16 @llvm.vector.reduce.add.v2i16(<2 x i16> %V2_16) -; CHECK: Cost Model: Found an estimated cost of 4 for instruction: %R4_16 = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> %V4_16) -; CHECK: Cost Model: Found an estimated cost of 6 for instruction: %R8_16 = call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %V8_16) -; CHECK: Cost Model: Found an estimated cost of 7 for instruction: %R16_16 = call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %V16_16) -; CHECK: Cost Model: Found an estimated cost of 2 for instruction: %R2_8 = call i8 @llvm.vector.reduce.add.v2i8(<2 x i8> %V2_8) -; CHECK: Cost Model: Found an estimated cost of 4 for instruction: %R4_8 = call i8 @llvm.vector.reduce.add.v4i8(<4 x i8> %V4_8) -; CHECK: Cost Model: Found an estimated cost of 6 for instruction: %R8_8 = call i8 @llvm.vector.reduce.add.v8i8(<8 x i8> %V8_8) -; CHECK: Cost Model: Found an estimated cost of 8 for instruction: %R16_8 = call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %V16_8) +; CHECK: Cost Model: Found an estimated cost of 2 for instruction: %R4_32 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %V4_32) +; CHECK: Cost Model: Found an estimated cost of 3 for instruction: %R8_32 = call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> %V8_32) +; CHECK: Cost Model: Found an estimated cost of 5 for instruction: %R16_32 = call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %V16_32) +; CHECK: Cost Model: Found an estimated cost of 3 for instruction: %R2_16 = call i16 @llvm.vector.reduce.add.v2i16(<2 x i16> %V2_16) +; CHECK: Cost Model: Found an estimated cost of 3 for instruction: %R4_16 = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> %V4_16) +; CHECK: Cost Model: Found an estimated cost of 3 for instruction: %R8_16 = call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %V8_16) +; CHECK: Cost Model: Found an estimated cost of 4 for instruction: %R16_16 = call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %V16_16) +; CHECK: Cost Model: Found an estimated cost of 3 for instruction: %R2_8 = call i8 @llvm.vector.reduce.add.v2i8(<2 x i8> %V2_8) +; CHECK: Cost Model: Found an estimated cost of 3 for instruction: %R4_8 = call i8 @llvm.vector.reduce.add.v4i8(<4 x i8> %V4_8) +; CHECK: Cost Model: Found an estimated cost of 3 for instruction: %R8_8 = call i8 @llvm.vector.reduce.add.v8i8(<8 x i8> %V8_8) +; CHECK: Cost Model: Found an estimated cost of 3 for instruction: %R16_8 = call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %V16_8) ; -; CHECK: Cost Model: Found an estimated cost of 15 for instruction: %R128_8 = call i8 @llvm.vector.reduce.add.v128i8(<128 x i8> %V128_8) +; CHECK: Cost Model: Found an estimated cost of 10 for instruction: %R128_8 = call i8 @llvm.vector.reduce.add.v128i8(<128 x i8> %V128_8) ; CHECK: Cost Model: Found an estimated cost of 20 for instruction: %R4_256 = call i256 @llvm.vector.reduce.add.v4i256(<4 x i256> %V4_256) ; REDUCEADD64 diff --git a/llvm/test/CodeGen/SystemZ/vec-reduce-add-01.ll b/llvm/test/CodeGen/SystemZ/vec-reduce-add-01.ll new file mode 100644 index 000000000000..56b151d7f941 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/vec-reduce-add-01.ll @@ -0,0 +1,289 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; Test vector add reduction instrinsic +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z16 | FileCheck %s + +; 1 vector length +declare i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %a) +declare i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %a) +declare i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a) +declare i64 @llvm.vector.reduce.add.v2i64(<2 x i64> %a) +declare i128 @llvm.vector.reduce.add.v1i128(<1 x i128> %a) +; 2 vector lengths +declare i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %a) +declare i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %a) +declare i32 @llvm.vector.reduce.add.v8i32(<8 x i32> %a) +declare i64 @llvm.vector.reduce.add.v4i64(<4 x i64> %a) +declare i128 @llvm.vector.reduce.add.v2i128(<2 x i128> %a) +; ; TODO +; ; 4 vector lengths +declare i8 @llvm.vector.reduce.add.v64i8(<64 x i8> %a) +declare i16 @llvm.vector.reduce.add.v32i16(<32 x i16> %a) +declare i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %a) +declare i64 @llvm.vector.reduce.add.v8i64(<8 x i64> %a) +declare i128 @llvm.vector.reduce.add.v4i128(<4 x i128> %a) +; ; Subvector lengths +declare i8 @llvm.vector.reduce.add.v8i8(<8 x i8> %a) +declare i16 @llvm.vector.reduce.add.v4i16(<4 x i16> %a) +declare i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %a) +declare i64 @llvm.vector.reduce.add.v1i64(<1 x i64> %a) + +define i8 @f1_1(<16 x i8> %a) { +; CHECK-LABEL: f1_1: +; CHECK: # %bb.0: +; CHECK-NEXT: vgbm %v0, 0 +; CHECK-NEXT: vsumb %v1, %v24, %v0 +; CHECK-NEXT: vsumqf %v0, %v1, %v0 +; CHECK-NEXT: vlgvf %r2, %v0, 3 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + %redadd = call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %a) + ret i8 %redadd +} + +define i16 @f1_2(<8 x i16> %a) { +; CHECK-LABEL: f1_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vgbm %v0, 0 +; CHECK-NEXT: vsumh %v1, %v24, %v0 +; CHECK-NEXT: vsumqf %v0, %v1, %v0 +; CHECK-NEXT: vlgvf %r2, %v0, 3 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + %redadd = call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %a) + ret i16 %redadd +} + +define i32 @f1_3(<4 x i32> %a) { +; CHECK-LABEL: f1_3: +; CHECK: # %bb.0: +; CHECK-NEXT: vgbm %v0, 0 +; CHECK-NEXT: vsumqf %v0, %v24, %v0 +; CHECK-NEXT: vlgvf %r2, %v0, 3 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + + %redadd = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a) + ret i32 %redadd +} + +define i64 @f1_4(<2 x i64> %a) { +; CHECK-LABEL: f1_4: +; CHECK: # %bb.0: +; CHECK-NEXT: vrepg %v0, %v24, 1 +; CHECK-NEXT: vag %v0, %v24, %v0 +; CHECK-NEXT: vlgvg %r2, %v0, 0 +; CHECK-NEXT: br %r14 + + %redadd = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> %a) + ret i64 %redadd +} + +define i128 @f1_5(<1 x i128> %a) { +; CHECK-LABEL: f1_5: +; CHECK: # %bb.0: +; CHECK-NEXT: vst %v24, 0(%r2), 3 +; CHECK-NEXT: br %r14 + %redadd = call i128 @llvm.vector.reduce.add.v1i128(<1 x i128> %a) + ret i128 %redadd +} + +define i8 @f2_1(<32 x i8> %a) { +; CHECK-LABEL: f2_1: +; CHECK: # %bb.0: +; CHECK-NEXT: vab %v0, %v24, %v26 +; CHECK-NEXT: vgbm %v1, 0 +; CHECK-NEXT: vsumb %v0, %v0, %v1 +; CHECK-NEXT: vsumqf %v0, %v0, %v1 +; CHECK-NEXT: vlgvf %r2, %v0, 3 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + %redadd = call i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %a) + ret i8 %redadd +} + +define i16 @f2_2(<16 x i16> %a) { +; CHECK-LABEL: f2_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vah %v0, %v24, %v26 +; CHECK-NEXT: vgbm %v1, 0 +; CHECK-NEXT: vsumh %v0, %v0, %v1 +; CHECK-NEXT: vsumqf %v0, %v0, %v1 +; CHECK-NEXT: vlgvf %r2, %v0, 3 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + %redadd = call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %a) + ret i16 %redadd +} + +define i32 @f2_3(<8 x i32> %a) { +; CHECK-LABEL: f2_3: +; CHECK: # %bb.0: +; CHECK-NEXT: vaf %v0, %v24, %v26 +; CHECK-NEXT: vgbm %v1, 0 +; CHECK-NEXT: vsumqf %v0, %v0, %v1 +; CHECK-NEXT: vlgvf %r2, %v0, 3 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + + %redadd = call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> %a) + ret i32 %redadd +} + +define i64 @f2_4(<4 x i64> %a) { +; CHECK-LABEL: f2_4: +; CHECK: # %bb.0: +; CHECK-NEXT: vag %v0, %v24, %v26 +; CHECK-NEXT: vrepg %v1, %v0, 1 +; CHECK-NEXT: vag %v0, %v0, %v1 +; CHECK-NEXT: vlgvg %r2, %v0, 0 +; CHECK-NEXT: br %r14 + + %redadd = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> %a) + ret i64 %redadd +} + +define i128 @f2_5(<2 x i128> %a) { +; CHECK-LABEL: f2_5: +; CHECK: # %bb.0: +; CHECK-NEXT: vl %v0, 16(%r3), 3 +; CHECK-NEXT: vl %v1, 0(%r3), 3 +; CHECK-NEXT: vaq %v0, %v1, %v0 +; CHECK-NEXT: vst %v0, 0(%r2), 3 +; CHECK-NEXT: br %r14 + %redadd = call i128 @llvm.vector.reduce.add.v2i128(<2 x i128> %a) + ret i128 %redadd +} + +define i8 @f3_1(<64 x i8> %a) { +; CHECK-LABEL: f3_1: +; CHECK: # %bb.0: +; CHECK-NEXT: vab %v0, %v26, %v30 +; CHECK-NEXT: vab %v1, %v24, %v28 +; CHECK-NEXT: vab %v0, %v1, %v0 +; CHECK-NEXT: vgbm %v1, 0 +; CHECK-NEXT: vsumb %v0, %v0, %v1 +; CHECK-NEXT: vsumqf %v0, %v0, %v1 +; CHECK-NEXT: vlgvf %r2, %v0, 3 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + %redadd = call i8 @llvm.vector.reduce.add.v64i8(<64 x i8> %a) + ret i8 %redadd +} + +define i16 @f3_2(<32 x i16> %a) { +; CHECK-LABEL: f3_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vah %v0, %v26, %v30 +; CHECK-NEXT: vah %v1, %v24, %v28 +; CHECK-NEXT: vah %v0, %v1, %v0 +; CHECK-NEXT: vgbm %v1, 0 +; CHECK-NEXT: vsumh %v0, %v0, %v1 +; CHECK-NEXT: vsumqf %v0, %v0, %v1 +; CHECK-NEXT: vlgvf %r2, %v0, 3 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + %redadd = call i16 @llvm.vector.reduce.add.v32i16(<32 x i16> %a) + ret i16 %redadd +} + +define i32 @f3_3(<16 x i32> %a) { +; CHECK-LABEL: f3_3: +; CHECK: # %bb.0: +; CHECK-NEXT: vaf %v0, %v26, %v30 +; CHECK-NEXT: vaf %v1, %v24, %v28 +; CHECK-NEXT: vaf %v0, %v1, %v0 +; CHECK-NEXT: vgbm %v1, 0 +; CHECK-NEXT: vsumqf %v0, %v0, %v1 +; CHECK-NEXT: vlgvf %r2, %v0, 3 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + + %redadd = call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %a) + ret i32 %redadd +} + +define i64 @f3_4(<8 x i64> %a) { +; CHECK-LABEL: f3_4: +; CHECK: # %bb.0: +; CHECK-NEXT: vag %v0, %v26, %v30 +; CHECK-NEXT: vag %v1, %v24, %v28 +; CHECK-NEXT: vag %v0, %v1, %v0 +; CHECK-NEXT: vrepg %v1, %v0, 1 +; CHECK-NEXT: vag %v0, %v0, %v1 +; CHECK-NEXT: vlgvg %r2, %v0, 0 +; CHECK-NEXT: br %r14 + + %redadd = call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> %a) + ret i64 %redadd +} + +define i128 @f3_5(<4 x i128> %a) { +; CHECK-LABEL: f3_5: +; CHECK: # %bb.0: +; CHECK-NEXT: vl %v0, 32(%r3), 3 +; CHECK-NEXT: vl %v1, 0(%r3), 3 +; CHECK-NEXT: vl %v2, 48(%r3), 3 +; CHECK-NEXT: vl %v3, 16(%r3), 3 +; CHECK-NEXT: vaq %v2, %v3, %v2 +; CHECK-NEXT: vaq %v0, %v1, %v0 +; CHECK-NEXT: vaq %v0, %v0, %v2 +; CHECK-NEXT: vst %v0, 0(%r2), 3 +; CHECK-NEXT: br %r14 + %redadd = call i128 @llvm.vector.reduce.add.v4i128(<4 x i128> %a) + ret i128 %redadd +} + + +define i8 @f4_1(<8 x i8> %a) { +; CHECK-LABEL: f4_1: +; CHECK: # %bb.0: +; CHECK-NEXT: vpkg %v0, %v24, %v24 +; CHECK-NEXT: vab %v0, %v24, %v0 +; CHECK-NEXT: vpkf %v1, %v0, %v0 +; CHECK-NEXT: vab %v0, %v0, %v1 +; CHECK-NEXT: vrepb %v1, %v0, 1 +; CHECK-NEXT: vab %v0, %v0, %v1 +; CHECK-NEXT: vlgvb %r2, %v0, 0 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + %redadd = call i8 @llvm.vector.reduce.add.v8i8(<8 x i8> %a) + ret i8 %redadd +} + +define i16 @f4_2(<4 x i16> %a) { +; CHECK-LABEL: f4_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vpkg %v0, %v24, %v24 +; CHECK-NEXT: vah %v0, %v24, %v0 +; CHECK-NEXT: vreph %v1, %v0, 1 +; CHECK-NEXT: vah %v0, %v0, %v1 +; CHECK-NEXT: vlgvh %r2, %v0, 0 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + %redadd = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> %a) + ret i16 %redadd +} + +define i32 @f4_3(<2 x i32> %a) { +; CHECK-LABEL: f4_3: +; CHECK: # %bb.0: +; CHECK-NEXT: vrepf %v0, %v24, 1 +; CHECK-NEXT: vaf %v0, %v24, %v0 +; CHECK-NEXT: vlgvf %r2, %v0, 0 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 + + %redadd = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %a) + ret i32 %redadd +} + +define i64 @f4_4(<1 x i64> %a) { +; CHECK-LABEL: f4_4: +; CHECK: # %bb.0: +; CHECK-NEXT: vlgvg %r2, %v24, 0 +; CHECK-NEXT: br %r14 + + %redadd = call i64 @llvm.vector.reduce.add.v1i64(<1 x i64> %a) + ret i64 %redadd +} -- GitLab From 8d468c132eed7ffe34d601b224220efd51655eb3 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Fri, 12 Apr 2024 09:05:59 -0700 Subject: [PATCH 083/464] NFC: Make clang resource headers an interface library (#88317) Making the clang resource headers into an interface library instead of a custom target means that we can attach the header search paths to the library. Targets that "link" against this library will automatically have the appropriate paths added to their header search paths to find them. Then downstream projects that embed a copy of clang can query the generated `ClangTargets.cmake` file for the header location instead of attempting to compute them. --- clang/lib/Headers/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 97104ccd8db5..e6ae4e19e81d 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -437,14 +437,14 @@ foreach( f ${generated_files} ) endforeach( f ) function(add_header_target target_name file_list) - add_custom_target(${target_name} DEPENDS ${file_list}) + add_library(${target_name} INTERFACE ${file_list}) set_target_properties(${target_name} PROPERTIES FOLDER "Misc" RUNTIME_OUTPUT_DIRECTORY "${output_dir}") endfunction() # The catch-all clang-resource-headers target -add_custom_target("clang-resource-headers" ALL DEPENDS ${out_files}) +add_library(clang-resource-headers INTERFACE ${out_files}) set_target_properties("clang-resource-headers" PROPERTIES FOLDER "Misc" RUNTIME_OUTPUT_DIRECTORY "${output_dir}") @@ -501,6 +501,10 @@ add_header_target("windows-resource-headers" ${windows_only_files}) add_header_target("utility-resource-headers" ${utility_files}) get_clang_resource_dir(header_install_dir SUBDIR include) +target_include_directories(clang-resource-headers INTERFACE + $ + $) +set_property(GLOBAL APPEND PROPERTY CLANG_EXPORTS clang-resource-headers) ############################################################# # Install rules for the catch-all clang-resource-headers target -- GitLab From 05d8b5e62d7a1cf2f94582346d6fd2d39667a26b Mon Sep 17 00:00:00 2001 From: JOSTAR <52376093+shenjunjiekoda@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:15:33 +0800 Subject: [PATCH 084/464] [analyzer] Support `PointerType` in `getCXXRecordDecl` for `ContainerModeling` (#87787) --- .../lib/StaticAnalyzer/Checkers/ContainerModeling.cpp | 4 ++++ clang/test/Analysis/invalidated-iterator.cpp | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp index 65a2ec4076fd..009c0d3fb936 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp @@ -770,6 +770,10 @@ const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State, Type = RefT->getPointeeType(); } + if (const auto *PtrT = Type->getAs()) { + Type = PtrT->getPointeeType(); + } + return Type->getUnqualifiedDesugaredType()->getAsCXXRecordDecl(); } diff --git a/clang/test/Analysis/invalidated-iterator.cpp b/clang/test/Analysis/invalidated-iterator.cpp index 778a8e01d993..c940dbf7276d 100644 --- a/clang/test/Analysis/invalidated-iterator.cpp +++ b/clang/test/Analysis/invalidated-iterator.cpp @@ -130,6 +130,14 @@ struct cont_with_ptr_iterator { T* erase(T*); }; +void invalidated_access_via_end_iterator_after_push_back() { + cont_with_ptr_iterator C; + C.push_back(1); + auto i = C.end(); + C.push_back(2); + auto j = i[-1]; // expected-warning{{Invalidated iterator accessed}} +} + void invalidated_dereference_end_ptr_iterator(cont_with_ptr_iterator &C) { auto i = C.begin(); C.erase(i); @@ -196,4 +204,4 @@ void invalidated_subscript_end_ptr_iterator(cont_with_ptr_iterator &C) { auto i = C.begin(); C.erase(i); (void) i[1]; // expected-warning{{Invalidated iterator accessed}} -} +} \ No newline at end of file -- GitLab From 37575f5262d0e37a1e0b10c59fb8f59182cfe951 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Fri, 12 Apr 2024 16:27:53 +0000 Subject: [PATCH 085/464] [NFC][ValueTracking] Fix Wunused-variable For e0a628715a8464e220c8ba9e9aaaf2561139198a --- llvm/lib/Analysis/InstructionSimplify.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index e83657df20f2..4e6e66692267 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2713,8 +2713,6 @@ static Constant *computePointerICmp(CmpInst::Predicate Pred, Value *LHS, assert(LHS->getType() == RHS->getType() && "Must have same types"); const DataLayout &DL = Q.DL; const TargetLibraryInfo *TLI = Q.TLI; - const DominatorTree *DT = Q.DT; - const Instruction *CxtI = Q.CxtI; // We can only fold certain predicates on pointer comparisons. switch (Pred) { -- GitLab From 54a6798e0a3630e705ed32dbbd63414a16331085 Mon Sep 17 00:00:00 2001 From: Edwin Vane Date: Fri, 12 Apr 2024 12:49:25 -0400 Subject: [PATCH 086/464] [clang-tidy] Simplify RenamerClangTidyCheck API (#88268) Some functions allow a null SourceManager, no SourceManager, or a SourceManager in an inconsistent argument position. Since SourceManager is generally not null and it doesn't make sense to apply renaming without one, these inconsistencies are now gone. --- .../utils/RenamerClangTidyCheck.cpp | 46 +++++++++++-------- .../clang-tidy/utils/RenamerClangTidyCheck.h | 11 +++-- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp index ad8048e2a92b..962a243ce94d 100644 --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp @@ -169,14 +169,14 @@ public: return; if (SM.isWrittenInCommandLineFile(MacroNameTok.getLocation())) return; - Check->checkMacro(SM, MacroNameTok, Info); + Check->checkMacro(MacroNameTok, Info, SM); } /// MacroExpands calls expandMacro for macros in the main file void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange /*Range*/, const MacroArgs * /*Args*/) override { - Check->expandMacro(MacroNameTok, MD.getMacroInfo()); + Check->expandMacro(MacroNameTok, MD.getMacroInfo(), SM); } private: @@ -187,7 +187,7 @@ private: class RenamerClangTidyVisitor : public RecursiveASTVisitor { public: - RenamerClangTidyVisitor(RenamerClangTidyCheck *Check, const SourceManager *SM, + RenamerClangTidyVisitor(RenamerClangTidyCheck *Check, const SourceManager &SM, bool AggressiveDependentMemberLookup) : Check(Check), SM(SM), AggressiveDependentMemberLookup(AggressiveDependentMemberLookup) {} @@ -258,7 +258,7 @@ public: // Fix overridden methods if (const auto *Method = dyn_cast(Decl)) { if (const CXXMethodDecl *Overridden = getOverrideMethod(Method)) { - Check->addUsage(Overridden, Method->getLocation()); + Check->addUsage(Overridden, Method->getLocation(), SM); return true; // Don't try to add the actual decl as a Failure. } } @@ -268,7 +268,7 @@ public: if (isa(Decl)) return true; - Check->checkNamedDecl(Decl, *SM); + Check->checkNamedDecl(Decl, SM); return true; } @@ -385,7 +385,7 @@ public: private: RenamerClangTidyCheck *Check; - const SourceManager *SM; + const SourceManager &SM; const bool AggressiveDependentMemberLookup; }; @@ -415,7 +415,7 @@ void RenamerClangTidyCheck::registerPPCallbacks( void RenamerClangTidyCheck::addUsage( const RenamerClangTidyCheck::NamingCheckId &Decl, SourceRange Range, - const SourceManager *SourceMgr) { + const SourceManager &SourceMgr) { // Do nothing if the provided range is invalid. if (Range.isInvalid()) return; @@ -425,8 +425,7 @@ void RenamerClangTidyCheck::addUsage( // spelling location to different source locations, and we only want to fix // the token once, before it is expanded by the macro. SourceLocation FixLocation = Range.getBegin(); - if (SourceMgr) - FixLocation = SourceMgr->getSpellingLoc(FixLocation); + FixLocation = SourceMgr.getSpellingLoc(FixLocation); if (FixLocation.isInvalid()) return; @@ -440,15 +439,15 @@ void RenamerClangTidyCheck::addUsage( if (!Failure.shouldFix()) return; - if (SourceMgr && SourceMgr->isWrittenInScratchSpace(FixLocation)) + if (SourceMgr.isWrittenInScratchSpace(FixLocation)) Failure.FixStatus = RenamerClangTidyCheck::ShouldFixStatus::InsideMacro; - if (!utils::rangeCanBeFixed(Range, SourceMgr)) + if (!utils::rangeCanBeFixed(Range, &SourceMgr)) Failure.FixStatus = RenamerClangTidyCheck::ShouldFixStatus::InsideMacro; } void RenamerClangTidyCheck::addUsage(const NamedDecl *Decl, SourceRange Range, - const SourceManager *SourceMgr) { + const SourceManager &SourceMgr) { // Don't keep track for non-identifier names. auto *II = Decl->getIdentifier(); if (!II) @@ -489,18 +488,24 @@ void RenamerClangTidyCheck::checkNamedDecl(const NamedDecl *Decl, } Failure.Info = std::move(Info); - addUsage(Decl, Range, &SourceMgr); + addUsage(Decl, Range, SourceMgr); } void RenamerClangTidyCheck::check(const MatchFinder::MatchResult &Result) { - RenamerClangTidyVisitor Visitor(this, Result.SourceManager, + if (!Result.SourceManager) { + // In principle SourceManager is not null but going only by the definition + // of MatchResult it must be handled. Cannot rename anything without a + // SourceManager. + return; + } + RenamerClangTidyVisitor Visitor(this, *Result.SourceManager, AggressiveDependentMemberLookup); Visitor.TraverseAST(*Result.Context); } -void RenamerClangTidyCheck::checkMacro(const SourceManager &SourceMgr, - const Token &MacroNameTok, - const MacroInfo *MI) { +void RenamerClangTidyCheck::checkMacro(const Token &MacroNameTok, + const MacroInfo *MI, + const SourceManager &SourceMgr) { std::optional MaybeFailure = getMacroFailureInfo(MacroNameTok, SourceMgr); if (!MaybeFailure) @@ -515,11 +520,12 @@ void RenamerClangTidyCheck::checkMacro(const SourceManager &SourceMgr, Failure.FixStatus = ShouldFixStatus::FixInvalidIdentifier; Failure.Info = std::move(Info); - addUsage(ID, Range); + addUsage(ID, Range, SourceMgr); } void RenamerClangTidyCheck::expandMacro(const Token &MacroNameTok, - const MacroInfo *MI) { + const MacroInfo *MI, + const SourceManager &SourceMgr) { StringRef Name = MacroNameTok.getIdentifierInfo()->getName(); NamingCheckId ID(MI->getDefinitionLoc(), Name); @@ -528,7 +534,7 @@ void RenamerClangTidyCheck::expandMacro(const Token &MacroNameTok, return; SourceRange Range(MacroNameTok.getLocation(), MacroNameTok.getEndLoc()); - addUsage(ID, Range); + addUsage(ID, Range, SourceMgr); } static std::string diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h index 38228fb59bf6..be5b6f0c7f76 100644 --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h @@ -108,18 +108,19 @@ public: llvm::DenseMap; /// Check Macros for style violations. - void checkMacro(const SourceManager &SourceMgr, const Token &MacroNameTok, - const MacroInfo *MI); + void checkMacro(const Token &MacroNameTok, const MacroInfo *MI, + const SourceManager &SourceMgr); /// Add a usage of a macro if it already has a violation. - void expandMacro(const Token &MacroNameTok, const MacroInfo *MI); + void expandMacro(const Token &MacroNameTok, const MacroInfo *MI, + const SourceManager &SourceMgr); void addUsage(const RenamerClangTidyCheck::NamingCheckId &Decl, - SourceRange Range, const SourceManager *SourceMgr = nullptr); + SourceRange Range, const SourceManager &SourceMgr); /// Convenience method when the usage to be added is a NamedDecl. void addUsage(const NamedDecl *Decl, SourceRange Range, - const SourceManager *SourceMgr = nullptr); + const SourceManager &SourceMgr); void checkNamedDecl(const NamedDecl *Decl, const SourceManager &SourceMgr); -- GitLab From 3652b2a877c3691b524a19bc38b338f1ba1dde37 Mon Sep 17 00:00:00 2001 From: Mike Rice Date: Fri, 12 Apr 2024 10:01:01 -0700 Subject: [PATCH 087/464] [clang][CodeGen][OpenMP] Fix casting of atomic update of ptr types (#88215) In 4d5e834c5b7f0ccccd90a6d543e182df602f6bc8, casts were removed for pointers but one case was missed. Add missing check. --- clang/lib/CodeGen/CGAtomic.cpp | 6 +++++- clang/test/OpenMP/atomic_update_codegen.cpp | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index d35ce0409d72..07452b18a85e 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -1806,7 +1806,11 @@ void AtomicInfo::EmitAtomicUpdateOp( /*NumReservedValues=*/2); PHI->addIncoming(OldVal, CurBB); Address NewAtomicAddr = CreateTempAlloca(); - Address NewAtomicIntAddr = castToAtomicIntPointer(NewAtomicAddr); + Address NewAtomicIntAddr = + shouldCastToInt(NewAtomicAddr.getElementType(), /*CmpXchg=*/true) + ? castToAtomicIntPointer(NewAtomicAddr) + : NewAtomicAddr; + if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) || requiresMemSetZero(getAtomicAddress().getElementType())) { CGF.Builder.CreateStore(PHI, NewAtomicIntAddr); diff --git a/clang/test/OpenMP/atomic_update_codegen.cpp b/clang/test/OpenMP/atomic_update_codegen.cpp index ce0765118922..fe745590a9f9 100644 --- a/clang/test/OpenMP/atomic_update_codegen.cpp +++ b/clang/test/OpenMP/atomic_update_codegen.cpp @@ -27,6 +27,7 @@ long double ldv, ldx; _Complex int civ, cix; _Complex float cfv, cfx; _Complex double cdv, cdx; +char *cpx; typedef int int4 __attribute__((__vector_size__(16))); int4 int4x; @@ -851,6 +852,16 @@ int main(void) { // CHECK: call{{.*}} @__kmpc_flush( #pragma omp atomic seq_cst rix = dv / rix; + +// CHECK: [[LD_CPX:%.+]] = load atomic ptr, ptr @cpx monotonic +// CHECK: br label %[[CONT:.+]] +// CHECK: [[CONT]] +// CHECK: [[PHI:%.+]] = phi ptr +// CHECK: [[RES:%.+]] = cmpxchg ptr @cpx, +// CHECK: br i1 %{{.+}}, label %[[EXIT:.+]], label %[[CONT]] + #pragma omp atomic update + cpx += 1; + return 0; } -- GitLab From d61edecbfd099143e0e2617505fec921524938f8 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 12 Apr 2024 10:12:24 -0700 Subject: [PATCH 088/464] [clang-format] Fix a regression in ContinuationIndenter (#88414) Commit d06b92391513 caused a regression that breaks after a block comment adjacent to a function paramter that follows. Fixes #86573. --- clang/lib/Format/ContinuationIndenter.cpp | 8 +++++++- clang/unittests/Format/FormatTestComments.cpp | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 700bce35c868..ad0e2c3c620c 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -684,7 +684,13 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, // arguments to function calls. We do this by ensuring that either all // arguments (including any lambdas) go on the same line as the function // call, or we break before the first argument. - auto PrevNonComment = Current.getPreviousNonComment(); + const auto *Prev = Current.Previous; + if (!Prev) + return false; + // For example, `/*Newline=*/false`. + if (Prev->is(TT_BlockComment) && Current.SpacesRequiredBefore == 0) + return false; + const auto *PrevNonComment = Current.getPreviousNonComment(); if (!PrevNonComment || PrevNonComment->isNot(tok::l_paren)) return false; if (Current.isOneOf(tok::comment, tok::l_paren, TT_LambdaLSquare)) diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp index d705cf34d8af..d2baace6a7d8 100644 --- a/clang/unittests/Format/FormatTestComments.cpp +++ b/clang/unittests/Format/FormatTestComments.cpp @@ -376,6 +376,10 @@ TEST_F(FormatTestComments, RemovesTrailingWhitespaceOfComments) { TEST_F(FormatTestComments, UnderstandsBlockComments) { verifyFormat("f(/*noSpaceAfterParameterNamingComment=*/true);"); verifyFormat("void f() { g(/*aaa=*/x, /*bbb=*/!y, /*c=*/::c); }"); + verifyFormat("fooooooooooooooooooooooooooooo(\n" + " /*qq_=*/move(q), [this, b](bar b) {},\n" + " c);", + getLLVMStyleWithColumns(60)); EXPECT_EQ("f(aaaaaaaaaaaaaaaaaaaaaaaaa, /* Trailing comment for aa... */\n" " bbbbbbbbbbbbbbbbbbbbbbbbb);", format("f(aaaaaaaaaaaaaaaaaaaaaaaaa , \\\n" -- GitLab From dcd097c475163b9bd41ff009a9157e86c6f2f171 Mon Sep 17 00:00:00 2001 From: Stanislav Mekhanoshin Date: Fri, 12 Apr 2024 10:15:59 -0700 Subject: [PATCH 089/464] Add IIT_V6 to support 6-element vectors in intrinsics. (#88196) Needed for the future patch. --- llvm/include/llvm/IR/Intrinsics.td | 1 + llvm/lib/IR/Function.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index f0723a633f0f..bdd8465883fc 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -319,6 +319,7 @@ def IIT_FUNCREF : IIT_VT; def IIT_I2 : IIT_Int<2, 57>; def IIT_I4 : IIT_Int<4, 58>; def IIT_AARCH64_SVCOUNT : IIT_VT; +def IIT_V6 : IIT_Vec<6, 60>; } defvar IIT_all_FixedTypes = !filter(iit, IIT_all, diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index b5fda9bb3d12..96953ac49c19 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1172,6 +1172,10 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, OutputTable.push_back(IITDescriptor::getVector(4, IsScalableVector)); DecodeIITType(NextElt, Infos, Info, OutputTable); return; + case IIT_V6: + OutputTable.push_back(IITDescriptor::getVector(6, IsScalableVector)); + DecodeIITType(NextElt, Infos, Info, OutputTable); + return; case IIT_V8: OutputTable.push_back(IITDescriptor::getVector(8, IsScalableVector)); DecodeIITType(NextElt, Infos, Info, OutputTable); -- GitLab From 6a85cf8fc0437d4885fc829948befe32c1e5a21d Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 12 Apr 2024 10:22:21 -0700 Subject: [PATCH 090/464] [SelectionDAG] Verify SPLAT_VECTOR nodes when they are created. (#88305) This applies the same rules we have for the scalar operands of a BUILD_VECTOR where the scalar type must match the element type or for integer vectors we allow the scalar type to be larger than the element type. Hexagon uses i32 for an FP zero vector so we allow that as an exception. --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index ddb12a101e02..412e1de9fc41 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -6032,6 +6032,17 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, if (N1.getValueType().getScalarType() == MVT::i1) return getNode(ISD::VECREDUCE_AND, DL, VT, N1); break; + case ISD::SPLAT_VECTOR: + assert(VT.isVector() && "Wrong return type!"); + // FIXME: Hexagon uses i32 scalar for a floating point zero vector so allow + // that for now. + assert((VT.getVectorElementType() == N1.getValueType() || + (VT.isFloatingPoint() && N1.getValueType() == MVT::i32) || + (VT.getVectorElementType().isInteger() && + N1.getValueType().isInteger() && + VT.getVectorElementType().bitsLE(N1.getValueType()))) && + "Wrong operand type!"); + break; } SDNode *N; -- GitLab From 7cafe04e0d74c1e9f7e3871a0bcdf4ccb1c89f0c Mon Sep 17 00:00:00 2001 From: Xiaoyang Liu Date: Fri, 12 Apr 2024 13:25:22 -0400 Subject: [PATCH 091/464] [libc++] P3029R1: Better `mdspan`'s CTAD (#87873) ## Abstract This pull request implements [P3029R1](https://wg21.link/P3029R1). The paper discusses the current behavior of `mdspan`'s most common pointer-indices CTAD, where the `Extents` template parameter is deduced as `dextents` (dynamic extents), even when passing compile-time constant values. The author believes this behavior is suboptimal, as it doesn't take advantage of the compile-time information. The proposed change suggests deducing static extents if `integral_constant`-like constants are passed, resulting in more intuitive syntax and less error-prone code. ## Reference - [P3029R1](https://wg21.link/P3029R1) - [Draft C++ Standard: [span.syn]](https://eel.is/c++draft/span.syn) - [Draft C++ Standard: [mdspan.syn]](https://eel.is/c++draft/mdspan.syn) --- libcxx/docs/ReleaseNotes/19.rst | 1 + libcxx/docs/Status/Cxx2cPapers.csv | 2 +- libcxx/include/__mdspan/mdspan.h | 7 +++ libcxx/include/mdspan | 6 ++- libcxx/include/span | 44 ++++++++++++++++++- .../views/mdspan/mdspan/deduction.pass.cpp | 18 +++++++- .../views.span/span.cons/deduct.pass.cpp | 11 +++++ 7 files changed, 84 insertions(+), 5 deletions(-) diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 81c05b9112bd..7bc0148c9ff0 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -47,6 +47,7 @@ Implemented Papers - P3142R0 - Printing Blank Lines with ``println`` (as DR against C++23) - P2302R4 - ``std::ranges::contains`` - P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with`` +- P3029R1 - Better ``mdspan``'s CTAD Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index fa11da62bc08..8516070c72b8 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -61,5 +61,5 @@ "`P1068R11 `__","LWG","Vector API for random number generation","Tokyo March 2024","","","" "`P2944R3 `__","LWG","Comparisons for ``reference_wrapper``","Tokyo March 2024","","","" "`P2642R6 `__","LWG","Padded ``mdspan`` layouts","Tokyo March 2024","","","" -"`P3029R1 `__","LWG","Better ``mdspan``'s CTAD","Tokyo March 2024","","","" +"`P3029R1 `__","LWG","Better ``mdspan``'s CTAD","Tokyo March 2024","|Complete|","19.0","" "","","","","","","" diff --git a/libcxx/include/__mdspan/mdspan.h b/libcxx/include/__mdspan/mdspan.h index d9a0108d6d35..09665af316e7 100644 --- a/libcxx/include/__mdspan/mdspan.h +++ b/libcxx/include/__mdspan/mdspan.h @@ -266,10 +266,17 @@ private: friend class mdspan; }; +# if _LIBCPP_STD_VER >= 26 +template + requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0)) +explicit mdspan(_ElementType*, + _OtherIndexTypes...) -> mdspan<_ElementType, extents...>>; +# else template requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0)) explicit mdspan(_ElementType*, _OtherIndexTypes...) -> mdspan<_ElementType, dextents>; +# endif template requires(is_pointer_v>) diff --git a/libcxx/include/mdspan b/libcxx/include/mdspan index c13d9eef001a..8d443f4acd1d 100644 --- a/libcxx/include/mdspan +++ b/libcxx/include/mdspan @@ -370,7 +370,11 @@ namespace std { template requires((is_convertible_v && ...) && sizeof...(Integrals) > 0) explicit mdspan(ElementType*, Integrals...) - -> mdspan>; + -> mdspan>; // until C++26 + template + requires((is_convertible_v && ...) && sizeof...(Integrals) > 0) + explicit mdspan(ElementType*, Integrals...) + -> mdspan...>>; // since C++26 template mdspan(ElementType*, span) diff --git a/libcxx/include/span b/libcxx/include/span index c0fe25ddb4be..0307edcb55c3 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -18,6 +18,20 @@ namespace std { // constants inline constexpr size_t dynamic_extent = numeric_limits::max(); +template + concept integral-constant-like = // exposition only, since C++26 + is_integral_v && + !is_same_v> && + convertible_to && + equality_comparable_with && + bool_constant::value && + bool_constant(T()) == T::value>::value; + +template + constexpr size_t maybe-static-ext = dynamic_extent; // exposition only, since C++26 +template + constexpr size_t maybe-static-ext = {T::value}; + // [views.span], class template span template class span; @@ -110,7 +124,9 @@ private: }; template - span(It, EndOrSize) -> span>>; + span(It, EndOrSize) -> span>>; // until C++26 +template + span(It, EndOrSize) -> span>, maybe-static-ext>; // since C++26 template span(T (&)[N]) -> span; @@ -129,6 +145,8 @@ template */ #include <__assert> +#include <__concepts/convertible_to.h> +#include <__concepts/equality_comparable.h> #include <__config> #include <__fwd/array.h> #include <__fwd/span.h> @@ -143,15 +161,19 @@ template #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> #include <__ranges/size.h> +#include <__type_traits/integral_constant.h> #include <__type_traits/is_array.h> #include <__type_traits/is_const.h> #include <__type_traits/is_convertible.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_const.h> #include <__type_traits/remove_cv.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/remove_reference.h> #include <__type_traits/type_identity.h> #include <__utility/forward.h> -#include // for byte +#include // for byte #include #include #include @@ -563,8 +585,26 @@ _LIBCPP_HIDE_FROM_ABI auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept { return __s.__as_writable_bytes(); } +# if _LIBCPP_STD_VER >= 26 +template +concept __integral_constant_like = + is_integral_v && !is_same_v> && + convertible_to<_Tp, decltype(_Tp::value)> && equality_comparable_with<_Tp, decltype(_Tp::value)> && + bool_constant<_Tp() == _Tp::value>::value && + bool_constant(_Tp()) == _Tp::value>::value; + +template +inline constexpr size_t __maybe_static_ext = dynamic_extent; + +template <__integral_constant_like _Tp> +inline constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value}; + +template +span(_It, _EndOrSize) -> span>, __maybe_static_ext<_EndOrSize>>; +# else template span(_It, _EndOrSize) -> span>>; +# endif template span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/deduction.pass.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/deduction.pass.cpp index 557829dcbad9..876a3e84d695 100644 --- a/libcxx/test/std/containers/views/mdspan/mdspan/deduction.pass.cpp +++ b/libcxx/test/std/containers/views/mdspan/mdspan/deduction.pass.cpp @@ -22,7 +22,11 @@ // template // requires((is_convertible_v && ...) && sizeof...(Integrals) > 0) // explicit mdspan(ElementType*, Integrals...) -// -> mdspan>; +// -> mdspan>; // until C++26 +// template +// requires((is_convertible_v && ...) && sizeof...(Integrals) > 0) +// explicit mdspan(ElementType*, Integrals...) +// -> mdspan...>>; // since C++26 // // template // mdspan(ElementType*, span) @@ -102,6 +106,18 @@ constexpr bool test_no_layout_deduction_guides(const H& handle, const A&) { // deduction from pointer and integral like ASSERT_SAME_TYPE(decltype(std::mdspan(handle, 5, SizeTIntType(6))), std::mdspan>); +#if _LIBCPP_STD_VER >= 26 + // P3029R1: deduction from `integral_constant` + ASSERT_SAME_TYPE( + decltype(std::mdspan(handle, std::integral_constant{})), std::mdspan>); + ASSERT_SAME_TYPE(decltype(std::mdspan(handle, std::integral_constant{}, std::dynamic_extent)), + std::mdspan>); + ASSERT_SAME_TYPE( + decltype(std::mdspan( + handle, std::integral_constant{}, std::dynamic_extent, std::integral_constant{})), + std::mdspan>); +#endif + std::array exts; // deduction from pointer and array ASSERT_SAME_TYPE(decltype(std::mdspan(handle, exts)), std::mdspan>); diff --git a/libcxx/test/std/containers/views/views.span/span.cons/deduct.pass.cpp b/libcxx/test/std/containers/views/views.span/span.cons/deduct.pass.cpp index 398862dccdb6..92bb7c9caea8 100644 --- a/libcxx/test/std/containers/views/views.span/span.cons/deduct.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.cons/deduct.pass.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "test_macros.h" @@ -48,6 +49,16 @@ void test_iterator_sentinel() { assert(s.size() == std::size(arr)); assert(s.data() == std::data(arr)); } + +#if _LIBCPP_STD_VER >= 26 + // P3029R1: deduction from `integral_constant` + { + std::span s{std::begin(arr), std::integral_constant{}}; + ASSERT_SAME_TYPE(decltype(s), std::span); + assert(s.size() == std::size(arr)); + assert(s.data() == std::data(arr)); + } +#endif } void test_c_array() { -- GitLab From fe59cb256289d9f2f6ebe75571389f3cc90bbdec Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 12 Apr 2024 09:43:10 -0700 Subject: [PATCH 092/464] [clang][deps] NFCI: Extract `FilenameForLookup` into new function This is an NFC change split from https://github.com/llvm/llvm-project/pull/68645. --- .../DependencyScanningFilesystem.h | 4 ++ .../DependencyScanningFilesystem.cpp | 41 ++++++++++++------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 9a522a3e2fe2..4cd0f958fcff 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -402,6 +402,10 @@ private: llvm::ErrorOr WorkingDirForCacheLookup; void updateWorkingDirForCacheLookup(); + + llvm::ErrorOr + tryGetFilenameForLookup(StringRef OriginalFilename, + llvm::SmallVectorImpl &PathBuf) const; }; } // end namespace dependencies diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 9b7812a1adb9..c66780d50fa1 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -233,24 +233,15 @@ DependencyScanningWorkerFilesystem::computeAndStoreResult( llvm::ErrorOr DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( StringRef OriginalFilename) { - StringRef FilenameForLookup; SmallString<256> PathBuf; - if (llvm::sys::path::is_absolute_gnu(OriginalFilename)) { - FilenameForLookup = OriginalFilename; - } else if (!WorkingDirForCacheLookup) { - return WorkingDirForCacheLookup.getError(); - } else { - StringRef RelFilename = OriginalFilename; - RelFilename.consume_front("./"); - PathBuf = *WorkingDirForCacheLookup; - llvm::sys::path::append(PathBuf, RelFilename); - FilenameForLookup = PathBuf.str(); - } - assert(llvm::sys::path::is_absolute_gnu(FilenameForLookup)); + auto FilenameForLookup = tryGetFilenameForLookup(OriginalFilename, PathBuf); + if (!FilenameForLookup) + return FilenameForLookup.getError(); + if (const auto *Entry = - findEntryByFilenameWithWriteThrough(FilenameForLookup)) + findEntryByFilenameWithWriteThrough(*FilenameForLookup)) return EntryRef(OriginalFilename, *Entry).unwrapError(); - auto MaybeEntry = computeAndStoreResult(OriginalFilename, FilenameForLookup); + auto MaybeEntry = computeAndStoreResult(OriginalFilename, *FilenameForLookup); if (!MaybeEntry) return MaybeEntry.getError(); return EntryRef(OriginalFilename, *MaybeEntry).unwrapError(); @@ -351,4 +342,24 @@ void DependencyScanningWorkerFilesystem::updateWorkingDirForCacheLookup() { llvm::sys::path::is_absolute_gnu(*WorkingDirForCacheLookup)); } +llvm::ErrorOr +DependencyScanningWorkerFilesystem::tryGetFilenameForLookup( + StringRef OriginalFilename, llvm::SmallVectorImpl &PathBuf) const { + StringRef FilenameForLookup; + if (llvm::sys::path::is_absolute_gnu(OriginalFilename)) { + FilenameForLookup = OriginalFilename; + } else if (!WorkingDirForCacheLookup) { + return WorkingDirForCacheLookup.getError(); + } else { + StringRef RelFilename = OriginalFilename; + RelFilename.consume_front("./"); + PathBuf.assign(WorkingDirForCacheLookup->begin(), + WorkingDirForCacheLookup->end()); + llvm::sys::path::append(PathBuf, RelFilename); + FilenameForLookup = StringRef{PathBuf.begin(), PathBuf.size()}; + } + assert(llvm::sys::path::is_absolute_gnu(FilenameForLookup)); + return FilenameForLookup; +} + const char DependencyScanningWorkerFilesystem::ID = 0; -- GitLab From edd7fed9da48c0e708cce9bd4d305ae43d8bd77c Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 12 Apr 2024 10:09:04 -0700 Subject: [PATCH 093/464] [llvm][vfs] NFCI: Remove `const` from `VFS::getRealPath()` This is an NFC change split from https://github.com/llvm/llvm-project/pull/68645. --- llvm/include/llvm/Support/VirtualFileSystem.h | 10 ++++----- llvm/lib/Support/FileCollector.cpp | 2 +- llvm/lib/Support/VirtualFileSystem.cpp | 21 ++++++++----------- .../Support/VirtualFileSystemTest.cpp | 2 +- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 770ca8764426..4b1ca0c3d262 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -298,7 +298,7 @@ public: /// symlinks. For real file system, this uses `llvm::sys::fs::real_path`. /// This returns errc::operation_not_permitted if not implemented by subclass. virtual std::error_code getRealPath(const Twine &Path, - SmallVectorImpl &Output) const; + SmallVectorImpl &Output); /// Check whether a file exists. Provided for convenience. bool exists(const Twine &Path); @@ -393,7 +393,7 @@ public: std::error_code setCurrentWorkingDirectory(const Twine &Path) override; std::error_code isLocal(const Twine &Path, bool &Result) override; std::error_code getRealPath(const Twine &Path, - SmallVectorImpl &Output) const override; + SmallVectorImpl &Output) override; using iterator = FileSystemList::reverse_iterator; using const_iterator = FileSystemList::const_reverse_iterator; @@ -453,7 +453,7 @@ public: return FS->setCurrentWorkingDirectory(Path); } std::error_code getRealPath(const Twine &Path, - SmallVectorImpl &Output) const override { + SmallVectorImpl &Output) override { return FS->getRealPath(Path, Output); } std::error_code isLocal(const Twine &Path, bool &Result) override { @@ -622,7 +622,7 @@ public: /// This doesn't resolve symlinks as they are not supported in in-memory file /// system. std::error_code getRealPath(const Twine &Path, - SmallVectorImpl &Output) const override; + SmallVectorImpl &Output) override; std::error_code isLocal(const Twine &Path, bool &Result) override; std::error_code setCurrentWorkingDirectory(const Twine &Path) override; @@ -1047,7 +1047,7 @@ public: ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, - SmallVectorImpl &Output) const override; + SmallVectorImpl &Output) override; llvm::ErrorOr getCurrentWorkingDirectory() const override; diff --git a/llvm/lib/Support/FileCollector.cpp b/llvm/lib/Support/FileCollector.cpp index 92bcdf00b8a8..be0b06b0aff8 100644 --- a/llvm/lib/Support/FileCollector.cpp +++ b/llvm/lib/Support/FileCollector.cpp @@ -281,7 +281,7 @@ public: } std::error_code getRealPath(const Twine &Path, - SmallVectorImpl &Output) const override { + SmallVectorImpl &Output) override { auto EC = FS->getRealPath(Path, Output); if (!EC) { Collector->addFile(Path); diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 057f8eae0552..32b480028e71 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -138,7 +138,7 @@ std::error_code FileSystem::makeAbsolute(SmallVectorImpl &Path) const { } std::error_code FileSystem::getRealPath(const Twine &Path, - SmallVectorImpl &Output) const { + SmallVectorImpl &Output) { return errc::operation_not_permitted; } @@ -275,7 +275,7 @@ public: std::error_code setCurrentWorkingDirectory(const Twine &Path) override; std::error_code isLocal(const Twine &Path, bool &Result) override; std::error_code getRealPath(const Twine &Path, - SmallVectorImpl &Output) const override; + SmallVectorImpl &Output) override; protected: void printImpl(raw_ostream &OS, PrintType Type, @@ -357,9 +357,8 @@ std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) { return llvm::sys::fs::is_local(adjustPath(Path, Storage), Result); } -std::error_code -RealFileSystem::getRealPath(const Twine &Path, - SmallVectorImpl &Output) const { +std::error_code RealFileSystem::getRealPath(const Twine &Path, + SmallVectorImpl &Output) { SmallString<256> Storage; return llvm::sys::fs::real_path(adjustPath(Path, Storage), Output); } @@ -471,9 +470,8 @@ std::error_code OverlayFileSystem::isLocal(const Twine &Path, bool &Result) { return errc::no_such_file_or_directory; } -std::error_code -OverlayFileSystem::getRealPath(const Twine &Path, - SmallVectorImpl &Output) const { +std::error_code OverlayFileSystem::getRealPath(const Twine &Path, + SmallVectorImpl &Output) { for (const auto &FS : FSList) if (FS->exists(Path)) return FS->getRealPath(Path, Output); @@ -1157,9 +1155,8 @@ std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) { return {}; } -std::error_code -InMemoryFileSystem::getRealPath(const Twine &Path, - SmallVectorImpl &Output) const { +std::error_code InMemoryFileSystem::getRealPath(const Twine &Path, + SmallVectorImpl &Output) { auto CWD = getCurrentWorkingDirectory(); if (!CWD || CWD->empty()) return errc::operation_not_permitted; @@ -2535,7 +2532,7 @@ RedirectingFileSystem::openFileForRead(const Twine &OriginalPath) { std::error_code RedirectingFileSystem::getRealPath(const Twine &OriginalPath, - SmallVectorImpl &Output) const { + SmallVectorImpl &Output) { SmallString<256> Path; OriginalPath.toVector(Path); diff --git a/llvm/unittests/Support/VirtualFileSystemTest.cpp b/llvm/unittests/Support/VirtualFileSystemTest.cpp index 695b09343257..49a2e19e4f74 100644 --- a/llvm/unittests/Support/VirtualFileSystemTest.cpp +++ b/llvm/unittests/Support/VirtualFileSystemTest.cpp @@ -82,7 +82,7 @@ public: } // Map any symlink to "/symlink". std::error_code getRealPath(const Twine &Path, - SmallVectorImpl &Output) const override { + SmallVectorImpl &Output) override { auto I = findEntry(Path); if (I == FilesAndDirs.end()) return make_error_code(llvm::errc::no_such_file_or_directory); -- GitLab From c11976f525f3b9b9dc6080f0b23d2ef1ec5fe8fd Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 12 Apr 2024 10:26:58 -0700 Subject: [PATCH 094/464] [clang][deps] Create separate unittest directory This is an NFC change split from https://github.com/llvm/llvm-project/pull/68645. --- clang/unittests/Tooling/CMakeLists.txt | 2 +- .../Tooling/{ => DependencyScanning}/DependencyScannerTest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename clang/unittests/Tooling/{ => DependencyScanning}/DependencyScannerTest.cpp (99%) diff --git a/clang/unittests/Tooling/CMakeLists.txt b/clang/unittests/Tooling/CMakeLists.txt index 5a10a6b28539..2ff493ef5fc3 100644 --- a/clang/unittests/Tooling/CMakeLists.txt +++ b/clang/unittests/Tooling/CMakeLists.txt @@ -13,7 +13,6 @@ add_clang_unittest(ToolingTests CastExprTest.cpp CommentHandlerTest.cpp CompilationDatabaseTest.cpp - DependencyScannerTest.cpp DiagnosticsYamlTest.cpp ExecutionTest.cpp FixItTest.cpp @@ -24,6 +23,7 @@ add_clang_unittest(ToolingTests LookupTest.cpp QualTypeNamesTest.cpp RangeSelectorTest.cpp + DependencyScanning/DependencyScannerTest.cpp RecursiveASTVisitorTests/Attr.cpp RecursiveASTVisitorTests/BitfieldInitializer.cpp RecursiveASTVisitorTests/CallbacksLeaf.cpp diff --git a/clang/unittests/Tooling/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp similarity index 99% rename from clang/unittests/Tooling/DependencyScannerTest.cpp rename to clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp index 8735fcad2004..ec0e143be4a2 100644 --- a/clang/unittests/Tooling/DependencyScannerTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp @@ -1,4 +1,4 @@ -//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===// +//===- DependencyScannerTest.cpp ------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. -- GitLab From a11a4324bb27c01e7a005e1a7f49fb8284098e8c Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 12 Apr 2024 10:34:42 -0700 Subject: [PATCH 095/464] [clang][deps] Cache `VFS::getRealPath()` (#68645) This PR starts caching calls to `DependencyScanningWorkerFilesystem::getRealPath()` that we use whenever we canonicalize module map path. In the case of the real VFS, this functions performs an expensive syscall that we'd like to do as rarely as possible. This PR keeps the real path out of `CachedFileSystemEntry`, since that's **immutable**; populating the real path on creation of this data structure (every stat/open) would be expensive. --- .../DependencyScanningFilesystem.h | 71 +++++++- .../DependencyScanningFilesystem.cpp | 109 +++++++++++-- clang/unittests/Tooling/CMakeLists.txt | 1 + .../DependencyScanningFilesystemTest.cpp | 152 ++++++++++++++++++ 4 files changed, 314 insertions(+), 19 deletions(-) create mode 100644 clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 4cd0f958fcff..8b6f149c7cb2 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -142,6 +142,8 @@ private: CachedFileContents *Contents; }; +using CachedRealPath = llvm::ErrorOr; + /// This class is a shared cache, that caches the 'stat' and 'open' calls to the /// underlying real file system, and the scanned preprocessor directives of /// files. @@ -154,9 +156,11 @@ public: /// The mutex that needs to be locked before mutation of any member. mutable std::mutex CacheLock; - /// Map from filenames to cached entries. - llvm::StringMap - EntriesByFilename; + /// Map from filenames to cached entries and real paths. + llvm::StringMap< + std::pair, + llvm::BumpPtrAllocator> + CacheByFilename; /// Map from unique IDs to cached entries. llvm::DenseMap @@ -168,6 +172,9 @@ public: /// The backing storage for cached contents. llvm::SpecificBumpPtrAllocator ContentsStorage; + /// The backing storage for cached real paths. + llvm::SpecificBumpPtrAllocator RealPathStorage; + /// Returns entry associated with the filename or nullptr if none is found. const CachedFileSystemEntry *findEntryByFilename(StringRef Filename) const; @@ -194,6 +201,17 @@ public: const CachedFileSystemEntry & getOrInsertEntryForFilename(StringRef Filename, const CachedFileSystemEntry &Entry); + + /// Returns the real path associated with the filename or nullptr if none is + /// found. + const CachedRealPath *findRealPathByFilename(StringRef Filename) const; + + /// Returns the real path associated with the filename if there is some. + /// Otherwise, constructs new one with the given one, associates it with the + /// filename and returns the result. + const CachedRealPath & + getOrEmplaceRealPathForFilename(StringRef Filename, + llvm::ErrorOr RealPath); }; DependencyScanningFilesystemSharedCache(); @@ -210,14 +228,17 @@ private: /// This class is a local cache, that caches the 'stat' and 'open' calls to the /// underlying real file system. class DependencyScanningFilesystemLocalCache { - llvm::StringMap Cache; + llvm::StringMap< + std::pair, + llvm::BumpPtrAllocator> + Cache; public: /// Returns entry associated with the filename or nullptr if none is found. const CachedFileSystemEntry *findEntryByFilename(StringRef Filename) const { assert(llvm::sys::path::is_absolute_gnu(Filename)); auto It = Cache.find(Filename); - return It == Cache.end() ? nullptr : It->getValue(); + return It == Cache.end() ? nullptr : It->getValue().first; } /// Associates the given entry with the filename and returns the given entry @@ -226,9 +247,40 @@ public: insertEntryForFilename(StringRef Filename, const CachedFileSystemEntry &Entry) { assert(llvm::sys::path::is_absolute_gnu(Filename)); - const auto *InsertedEntry = Cache.insert({Filename, &Entry}).first->second; - assert(InsertedEntry == &Entry && "entry already present"); - return *InsertedEntry; + auto [It, Inserted] = Cache.insert({Filename, {&Entry, nullptr}}); + auto &[CachedEntry, CachedRealPath] = It->getValue(); + if (!Inserted) { + // The file is already present in the local cache. If we got here, it only + // contains the real path. Let's make sure the entry is populated too. + assert((!CachedEntry && CachedRealPath) && "entry already present"); + CachedEntry = &Entry; + } + return *CachedEntry; + } + + /// Returns real path associated with the filename or nullptr if none is + /// found. + const CachedRealPath *findRealPathByFilename(StringRef Filename) const { + assert(llvm::sys::path::is_absolute_gnu(Filename)); + auto It = Cache.find(Filename); + return It == Cache.end() ? nullptr : It->getValue().second; + } + + /// Associates the given real path with the filename and returns the given + /// entry pointer (for convenience). + const CachedRealPath & + insertRealPathForFilename(StringRef Filename, + const CachedRealPath &RealPath) { + assert(llvm::sys::path::is_absolute_gnu(Filename)); + auto [It, Inserted] = Cache.insert({Filename, {nullptr, &RealPath}}); + auto &[CachedEntry, CachedRealPath] = It->getValue(); + if (!Inserted) { + // The file is already present in the local cache. If we got here, it only + // contains the entry. Let's make sure the real path is populated too. + assert((!CachedRealPath && CachedEntry) && "real path already present"); + CachedRealPath = &RealPath; + } + return *CachedRealPath; } }; @@ -296,6 +348,9 @@ public: llvm::ErrorOr> openFileForRead(const Twine &Path) override; + std::error_code getRealPath(const Twine &Path, + SmallVectorImpl &Output) override; + std::error_code setCurrentWorkingDirectory(const Twine &Path) override; /// Returns entry for the given filename. diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index c66780d50fa1..84185c931b55 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -113,8 +113,8 @@ DependencyScanningFilesystemSharedCache::CacheShard::findEntryByFilename( StringRef Filename) const { assert(llvm::sys::path::is_absolute_gnu(Filename)); std::lock_guard LockGuard(CacheLock); - auto It = EntriesByFilename.find(Filename); - return It == EntriesByFilename.end() ? nullptr : It->getValue(); + auto It = CacheByFilename.find(Filename); + return It == CacheByFilename.end() ? nullptr : It->getValue().first; } const CachedFileSystemEntry * @@ -130,11 +130,16 @@ DependencyScanningFilesystemSharedCache::CacheShard:: getOrEmplaceEntryForFilename(StringRef Filename, llvm::ErrorOr Stat) { std::lock_guard LockGuard(CacheLock); - auto Insertion = EntriesByFilename.insert({Filename, nullptr}); - if (Insertion.second) - Insertion.first->second = + auto [It, Inserted] = CacheByFilename.insert({Filename, {nullptr, nullptr}}); + auto &[CachedEntry, CachedRealPath] = It->getValue(); + if (!CachedEntry) { + // The entry is not present in the shared cache. Either the cache doesn't + // know about the file at all, or it only knows about its real path. + assert((Inserted || CachedRealPath) && "existing file with empty pair"); + CachedEntry = new (EntryStorage.Allocate()) CachedFileSystemEntry(std::move(Stat)); - return *Insertion.first->second; + } + return *CachedEntry; } const CachedFileSystemEntry & @@ -142,16 +147,17 @@ DependencyScanningFilesystemSharedCache::CacheShard::getOrEmplaceEntryForUID( llvm::sys::fs::UniqueID UID, llvm::vfs::Status Stat, std::unique_ptr Contents) { std::lock_guard LockGuard(CacheLock); - auto Insertion = EntriesByUID.insert({UID, nullptr}); - if (Insertion.second) { + auto [It, Inserted] = EntriesByUID.insert({UID, nullptr}); + auto &CachedEntry = It->getSecond(); + if (Inserted) { CachedFileContents *StoredContents = nullptr; if (Contents) StoredContents = new (ContentsStorage.Allocate()) CachedFileContents(std::move(Contents)); - Insertion.first->second = new (EntryStorage.Allocate()) + CachedEntry = new (EntryStorage.Allocate()) CachedFileSystemEntry(std::move(Stat), StoredContents); } - return *Insertion.first->second; + return *CachedEntry; } const CachedFileSystemEntry & @@ -159,7 +165,40 @@ DependencyScanningFilesystemSharedCache::CacheShard:: getOrInsertEntryForFilename(StringRef Filename, const CachedFileSystemEntry &Entry) { std::lock_guard LockGuard(CacheLock); - return *EntriesByFilename.insert({Filename, &Entry}).first->getValue(); + auto [It, Inserted] = CacheByFilename.insert({Filename, {&Entry, nullptr}}); + auto &[CachedEntry, CachedRealPath] = It->getValue(); + if (!Inserted || !CachedEntry) + CachedEntry = &Entry; + return *CachedEntry; +} + +const CachedRealPath * +DependencyScanningFilesystemSharedCache::CacheShard::findRealPathByFilename( + StringRef Filename) const { + assert(llvm::sys::path::is_absolute_gnu(Filename)); + std::lock_guard LockGuard(CacheLock); + auto It = CacheByFilename.find(Filename); + return It == CacheByFilename.end() ? nullptr : It->getValue().second; +} + +const CachedRealPath &DependencyScanningFilesystemSharedCache::CacheShard:: + getOrEmplaceRealPathForFilename(StringRef Filename, + llvm::ErrorOr RealPath) { + std::lock_guard LockGuard(CacheLock); + + const CachedRealPath *&StoredRealPath = CacheByFilename[Filename].second; + if (!StoredRealPath) { + auto OwnedRealPath = [&]() -> CachedRealPath { + if (!RealPath) + return RealPath.getError(); + return RealPath->str(); + }(); + + StoredRealPath = new (RealPathStorage.Allocate()) + CachedRealPath(std::move(OwnedRealPath)); + } + + return *StoredRealPath; } static bool shouldCacheStatFailures(StringRef Filename) { @@ -321,6 +360,54 @@ DependencyScanningWorkerFilesystem::openFileForRead(const Twine &Path) { return DepScanFile::create(Result.get()); } +std::error_code +DependencyScanningWorkerFilesystem::getRealPath(const Twine &Path, + SmallVectorImpl &Output) { + SmallString<256> OwnedFilename; + StringRef OriginalFilename = Path.toStringRef(OwnedFilename); + + SmallString<256> PathBuf; + auto FilenameForLookup = tryGetFilenameForLookup(OriginalFilename, PathBuf); + if (!FilenameForLookup) + return FilenameForLookup.getError(); + + auto HandleCachedRealPath = + [&Output](const CachedRealPath &RealPath) -> std::error_code { + if (!RealPath) + return RealPath.getError(); + Output.assign(RealPath->begin(), RealPath->end()); + return {}; + }; + + // If we already have the result in local cache, no work required. + if (const auto *RealPath = + LocalCache.findRealPathByFilename(*FilenameForLookup)) + return HandleCachedRealPath(*RealPath); + + // If we have the result in the shared cache, cache it locally. + auto &Shard = SharedCache.getShardForFilename(*FilenameForLookup); + if (const auto *ShardRealPath = + Shard.findRealPathByFilename(*FilenameForLookup)) { + const auto &RealPath = LocalCache.insertRealPathForFilename( + *FilenameForLookup, *ShardRealPath); + return HandleCachedRealPath(RealPath); + } + + // If we don't know the real path, compute it... + std::error_code EC = getUnderlyingFS().getRealPath(OriginalFilename, Output); + llvm::ErrorOr ComputedRealPath = EC; + if (!EC) + ComputedRealPath = StringRef{Output.data(), Output.size()}; + + // ...and try to write it into the shared cache. In case some other thread won + // this race and already wrote its own result there, just adopt it. Write + // whatever is in the shared cache into the local one. + const auto &RealPath = Shard.getOrEmplaceRealPathForFilename( + *FilenameForLookup, ComputedRealPath); + return HandleCachedRealPath( + LocalCache.insertRealPathForFilename(*FilenameForLookup, RealPath)); +} + std::error_code DependencyScanningWorkerFilesystem::setCurrentWorkingDirectory( const Twine &Path) { std::error_code EC = ProxyFileSystem::setCurrentWorkingDirectory(Path); diff --git a/clang/unittests/Tooling/CMakeLists.txt b/clang/unittests/Tooling/CMakeLists.txt index 2ff493ef5fc3..0eb612f8d949 100644 --- a/clang/unittests/Tooling/CMakeLists.txt +++ b/clang/unittests/Tooling/CMakeLists.txt @@ -24,6 +24,7 @@ add_clang_unittest(ToolingTests QualTypeNamesTest.cpp RangeSelectorTest.cpp DependencyScanning/DependencyScannerTest.cpp + DependencyScanning/DependencyScanningFilesystemTest.cpp RecursiveASTVisitorTests/Attr.cpp RecursiveASTVisitorTests/BitfieldInitializer.cpp RecursiveASTVisitorTests/CallbacksLeaf.cpp diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp new file mode 100644 index 000000000000..50cad72d223e --- /dev/null +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp @@ -0,0 +1,152 @@ +//===- DependencyScanningFilesystemTest.cpp -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "gtest/gtest.h" + +using namespace clang::tooling::dependencies; + +namespace { +struct InstrumentingFilesystem + : llvm::RTTIExtends { + unsigned NumStatusCalls = 0; + unsigned NumGetRealPathCalls = 0; + + using llvm::RTTIExtends::RTTIExtends; + + llvm::ErrorOr status(const llvm::Twine &Path) override { + ++NumStatusCalls; + return ProxyFileSystem::status(Path); + } + + std::error_code getRealPath(const llvm::Twine &Path, + llvm::SmallVectorImpl &Output) override { + ++NumGetRealPathCalls; + return ProxyFileSystem::getRealPath(Path, Output); + } +}; +} // namespace + +TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) { + auto InMemoryFS = llvm::makeIntrusiveRefCnt(); + + auto InstrumentingFS = + llvm::makeIntrusiveRefCnt(InMemoryFS); + + DependencyScanningFilesystemSharedCache SharedCache; + DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS); + DependencyScanningWorkerFilesystem DepFS2(SharedCache, InstrumentingFS); + + DepFS.status("/foo.c"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u); + + DepFS.status("/foo.c"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u); // Cached, no increase. + + DepFS.status("/bar.c"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); + + DepFS2.status("/foo.c"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); // Shared cache. +} + +TEST(DependencyScanningFilesystem, CacheGetRealPath) { + auto InMemoryFS = llvm::makeIntrusiveRefCnt(); + InMemoryFS->setCurrentWorkingDirectory("/"); + InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer("")); + InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer("")); + + auto InstrumentingFS = + llvm::makeIntrusiveRefCnt(InMemoryFS); + + DependencyScanningFilesystemSharedCache SharedCache; + DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS); + DependencyScanningWorkerFilesystem DepFS2(SharedCache, InstrumentingFS); + + { + llvm::SmallString<128> Result; + DepFS.getRealPath("/foo", Result); + EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 1u); + } + + { + llvm::SmallString<128> Result; + DepFS.getRealPath("/foo", Result); + EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 1u); // Cached, no increase. + } + + { + llvm::SmallString<128> Result; + DepFS.getRealPath("/bar", Result); + EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 2u); + } + + { + llvm::SmallString<128> Result; + DepFS2.getRealPath("/foo", Result); + EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 2u); // Shared cache. + } +} + +TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) { + auto InMemoryFS = llvm::makeIntrusiveRefCnt(); + InMemoryFS->setCurrentWorkingDirectory("/"); + InMemoryFS->addFile("/foo.c", 0, llvm::MemoryBuffer::getMemBuffer("")); + InMemoryFS->addFile("/bar.c", 0, llvm::MemoryBuffer::getMemBuffer("")); + + auto InstrumentingFS = + llvm::makeIntrusiveRefCnt(InMemoryFS); + + DependencyScanningFilesystemSharedCache SharedCache; + DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS); + + // Success. + { + DepFS.status("/foo.c"); + + llvm::SmallString<128> Result; + DepFS.getRealPath("/foo.c", Result); + } + { + llvm::SmallString<128> Result; + DepFS.getRealPath("/bar.c", Result); + + DepFS.status("/bar.c"); + } + + // Failure. + { + DepFS.status("/foo.m"); + + llvm::SmallString<128> Result; + DepFS.getRealPath("/foo.m", Result); + } + { + llvm::SmallString<128> Result; + DepFS.getRealPath("/bar.m", Result); + + DepFS.status("/bar.m"); + } + + // Failure without caching. + { + DepFS.status("/foo"); + + llvm::SmallString<128> Result; + DepFS.getRealPath("/foo", Result); + } + { + llvm::SmallString<128> Result; + DepFS.getRealPath("/bar", Result); + + DepFS.status("/bar"); + } +} -- GitLab From 2620ccc3cdebcaa53b96b5f4d79ffe3951534e07 Mon Sep 17 00:00:00 2001 From: Kalesh Singh Date: Fri, 12 Apr 2024 10:43:59 -0700 Subject: [PATCH 096/464] ANDROID: x86_64: Set default max-page-size to 16kB (#87413) Android now supports both 4kB and 16kB page sizes. The vast majority of android apps are developed on x86_64 machines. In order to provide emulators that support larger page sizes, Android emulates the page-size in x86_64 to support testing apps for large page size support. For this reason, update Android x86_64 ELFs default max-page-size to 16384 to support both 4kB and 16kB page-size devices. Increase max-page-size raises concerns of increased disk space and extra VMA slab memory. In Android, RO partitions use sparse images, so that the holes on ELFs don't allocate blocks on disk; and PackageManager ensures to punch holes in ELF-paddings on the /data partition when apps are installed. Extra VMA slab memory is addressed by the bionic loader, which extends segment VMAs to cover the gaps between consecutive segment mappings, to avoid the extra VMAs needed for the gap PROT_NONE mappings (---p). This optimization is done in the crt_pad_segment note [1] is present in the ELF. [1] https://cs.android.com/android/platform/superproject/main/+/189e480390ef13199d59e1fb54078e8b78ea6f79:bionic/libc/arch-common/bionic/crt_pad_segment.S --------- Signed-off-by: Kalesh Singh Co-authored-by: Kalesh Singh --- clang/lib/Driver/ToolChains/Linux.cpp | 3 ++- clang/test/Driver/android-link.cpp | 38 +++++++++++++++++---------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 6c2f23e57bce..fb65881061ef 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -244,8 +244,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // Android ARM uses max-page-size=4096 to reduce VMA usage. ExtraOpts.push_back("-z"); ExtraOpts.push_back("max-page-size=4096"); - } else if (Triple.isAArch64()) { + } else if (Triple.isAArch64() || Triple.getArch() == llvm::Triple::x86_64) { // Android AArch64 uses max-page-size=16384 to support 4k/16k page sizes. + // Android emulates a 16k page size for app testing on x86_64 machines. ExtraOpts.push_back("-z"); ExtraOpts.push_back("max-page-size=16384"); } diff --git a/clang/test/Driver/android-link.cpp b/clang/test/Driver/android-link.cpp index f9bdd00507d7..ab7dae540558 100644 --- a/clang/test/Driver/android-link.cpp +++ b/clang/test/Driver/android-link.cpp @@ -1,26 +1,36 @@ -// Check that we add relevant linker flags for Android ARM/AArch64. +// Check that we add relevant linker flags for Android ARM/AArch64/i386/x86_64. -// RUN: %clang -### -target arm-linux-androideabi %s 2>&1 | \ -// RUN: FileCheck --check-prefix=MAX-PAGE-SIZE %s +// RUN: %clang -### --target=arm-linux-androideabi %s 2>&1 | \ +// RUN: FileCheck --check-prefix=MAX-PAGE-SIZE-4KB %s -// RUN: %clang -target aarch64-none-linux-android \ +// RUN: %clang --target=aarch64-none-linux-android \ // RUN: -### -v %s 2> %t // RUN: FileCheck -check-prefix=GENERIC-ARM < %t %s -// -// RUN: %clang -target aarch64-none-linux-android \ + +// RUN: %clang --target=aarch64-none-linux-android \ // RUN: -mcpu=cortex-a53 -### -v %s 2> %t // RUN: FileCheck -check-prefix=CORTEX-A53 < %t %s -// -// RUN: %clang -target aarch64-none-linux-android \ + +// RUN: %clang --target=aarch64-none-linux-android \ // RUN: -mcpu=cortex-a57 -### -v %s 2> %t // RUN: FileCheck -check-prefix=CORTEX-A57 < %t %s -// -// RUN: %clang -target aarch64-none-linux-android \ + +// RUN: %clang --target=aarch64-none-linux-android \ // RUN: -### -v %s 2> %t -// RUN: FileCheck -check-prefix=MAX-PAGE-SIZE-AARCH64 < %t %s -// +// RUN: FileCheck -check-prefix=MAX-PAGE-SIZE-16KB < %t %s + +// RUN: %clang -### --target=i386-none-linux-android %s 2>&1 | \ +// RUN: FileCheck --check-prefix=NO-MAX-PAGE-SIZE-16KB %s + +// RUN: %clang -### --target=x86_64-none-linux-gnu %s 2>&1 | \ +// RUN: FileCheck --check-prefix=NO-MAX-PAGE-SIZE-16KB %s + +// RUN: %clang -### --target=x86_64-none-linux-android %s 2>&1 | \ +// RUN: FileCheck --check-prefix=MAX-PAGE-SIZE-16KB %s + // GENERIC-ARM: --fix-cortex-a53-843419 // CORTEX-A53: --fix-cortex-a53-843419 // CORTEX-A57-NOT: --fix-cortex-a53-843419 -// MAX-PAGE-SIZE: "-z" "max-page-size=4096" -// MAX-PAGE-SIZE-AARCH64: "-z" "max-page-size=16384" +// MAX-PAGE-SIZE-4KB: "-z" "max-page-size=4096" +// MAX-PAGE-SIZE-16KB: "-z" "max-page-size=16384" +// NO-MAX-PAGE-SIZE-16KB-NOT: "-z" "max-page-size=16384" -- GitLab From 446d38c65f72fd5d242a64182b05683577f683d3 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 12 Apr 2024 10:48:54 -0700 Subject: [PATCH 097/464] [lldb] Fix test build failure Caused by commit edd7fed9da48c0e708cce9bd4d305ae43d8bd77c --- lldb/unittests/Host/FileSystemTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/unittests/Host/FileSystemTest.cpp b/lldb/unittests/Host/FileSystemTest.cpp index 4ed9beff4d30..3b5ee7c8bc22 100644 --- a/lldb/unittests/Host/FileSystemTest.cpp +++ b/lldb/unittests/Host/FileSystemTest.cpp @@ -74,7 +74,7 @@ public: } // Map any symlink to "/symlink". std::error_code getRealPath(const Twine &Path, - SmallVectorImpl &Output) const override { + SmallVectorImpl &Output) override { auto I = FilesAndDirs.find(Path.str()); if (I == FilesAndDirs.end()) return make_error_code(llvm::errc::no_such_file_or_directory); -- GitLab From 9022d9c102a8c47616fbeb6a45b015db6bd2c17a Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 12 Apr 2024 10:49:39 -0700 Subject: [PATCH 098/464] [xray] Apply default visibility to __xray_CustomEvent/__xray_TypedEvent `__xray_customevent` and `__xray_typedevent` are built-in functions in Clang. With -fxray-instrument, they are lowered to `__xray_CustomEvent` (with 2 arguments) or `__xray_TypedEvent` (with 3 arguments). xray patching is supported for shared objects, but they may contain `__xray_customevent` and `__xray_typedevent` references that need to be satisfied by default visibility definitions exported by the executable. lld since df54f627fad789ccb11c72a9fddf116decbeba0e, like GNU ld, catches the scenario at link time. --- compiler-rt/lib/xray/xray_trampoline_AArch64.S | 4 ++-- compiler-rt/lib/xray/xray_trampoline_x86_64.S | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler-rt/lib/xray/xray_trampoline_AArch64.S b/compiler-rt/lib/xray/xray_trampoline_AArch64.S index 6f10dda3602b..536a79e0d150 100644 --- a/compiler-rt/lib/xray/xray_trampoline_AArch64.S +++ b/compiler-rt/lib/xray/xray_trampoline_AArch64.S @@ -138,8 +138,9 @@ ASM_SYMBOL(__xray_ArgLoggerEntry): ret ASM_SIZE(__xray_ArgLoggerEntry) +// __xray_*Event have default visibility so that they can be referenced by user +// DSOs that do not link against the runtime. .global ASM_SYMBOL(__xray_CustomEvent) -ASM_HIDDEN(__xray_CustomEvent) ASM_TYPE_FUNCTION(__xray_CustomEvent) ASM_SYMBOL(__xray_CustomEvent): SAVE_REGISTERS @@ -153,7 +154,6 @@ ASM_SYMBOL(__xray_CustomEvent): ASM_SIZE(__xray_CustomEvent) .global ASM_SYMBOL(__xray_TypedEvent) -ASM_HIDDEN(__xray_TypedEvent) ASM_TYPE_FUNCTION(__xray_TypedEvent) ASM_SYMBOL(__xray_TypedEvent): SAVE_REGISTERS diff --git a/compiler-rt/lib/xray/xray_trampoline_x86_64.S b/compiler-rt/lib/xray/xray_trampoline_x86_64.S index 0f00bcc41508..ff3ac91071a6 100644 --- a/compiler-rt/lib/xray/xray_trampoline_x86_64.S +++ b/compiler-rt/lib/xray/xray_trampoline_x86_64.S @@ -257,8 +257,9 @@ LOCAL_LABEL(arg1entryFail): //===----------------------------------------------------------------------===// +// __xray_*Event have default visibility so that they can be referenced by user +// DSOs that do not link against the runtime. .global ASM_SYMBOL(__xray_CustomEvent) - ASM_HIDDEN(__xray_CustomEvent) .align 16, 0x90 ASM_TYPE_FUNCTION(__xray_CustomEvent) # LLVM-MCA-BEGIN __xray_CustomEvent @@ -284,7 +285,6 @@ LOCAL_LABEL(customEventCleanup): //===----------------------------------------------------------------------===// .global ASM_SYMBOL(__xray_TypedEvent) - ASM_HIDDEN(__xray_TypedEvent) .align 16, 0x90 ASM_TYPE_FUNCTION(__xray_TypedEvent) # LLVM-MCA-BEGIN __xray_TypedEvent -- GitLab From 4b0beb4f5ec42aea58461df7994e2fa40f335bb6 Mon Sep 17 00:00:00 2001 From: jimingham Date: Fri, 12 Apr 2024 10:51:49 -0700 Subject: [PATCH 099/464] =?UTF-8?q?Reapply=20"Fix=20error=20in=20unrecogni?= =?UTF-8?q?zed=20register=20name=20handling=20for=20"SBFram=E2=80=A6e.regi?= =?UTF-8?q?ster""=20(#88468)"=20(#88535)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only change is a fix for the "register" iterator test to not rely on particular register names. I mistook where the artificial "pc" register is generated. It isn't added to the register list or the register sets (except on arm where that's the name of the actual register), so I can't use it in this test. I instead just assert that the "register" generator produces the same list as flattening the register sets from "registers". This reverts commit 9f14914753599f3879e4c273191959e2f1b3632c. --- lldb/bindings/interface/SBFrameExtensions.i | 12 +++++++++++- lldb/test/API/python_api/frame/TestFrames.py | 16 ++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lldb/bindings/interface/SBFrameExtensions.i b/lldb/bindings/interface/SBFrameExtensions.i index 43b22ed7a6b3..e0472280666a 100644 --- a/lldb/bindings/interface/SBFrameExtensions.i +++ b/lldb/bindings/interface/SBFrameExtensions.i @@ -44,6 +44,16 @@ STRING_EXTENSION_OUTSIDE(SBFrame) def __init__(self, regs): self.regs = regs + def __iter__(self): + return self.get_registers() + + def get_registers(self): + for i in range(0,len(self.regs)): + rs = self.regs[i] + for j in range (0,rs.num_children): + reg = rs.GetChildAtIndex(j) + yield reg + def __getitem__(self, key): if type(key) is str: for i in range(0,len(self.regs)): @@ -52,7 +62,7 @@ STRING_EXTENSION_OUTSIDE(SBFrame) reg = rs.GetChildAtIndex(j) if reg.name == key: return reg else: - return lldb.SBValue() + return SBValue() return registers_access(self.registers) diff --git a/lldb/test/API/python_api/frame/TestFrames.py b/lldb/test/API/python_api/frame/TestFrames.py index a82b129bc809..0ec12206024a 100644 --- a/lldb/test/API/python_api/frame/TestFrames.py +++ b/lldb/test/API/python_api/frame/TestFrames.py @@ -73,10 +73,12 @@ class FrameAPITestCase(TestBase): gpr_reg_set = lldbutil.get_GPRs(frame) pc_value = gpr_reg_set.GetChildMemberWithName("pc") self.assertTrue(pc_value, "We should have a valid PC.") - pc_value_int = int(pc_value.GetValue(), 0) + + # Make sure on arm targets we dont mismatch PC value on the basis of thumb bit. # Frame PC will not have thumb bit set in case of a thumb # instruction as PC. + pc_value_int = int(pc_value.GetValue(), 0) if self.getArchitecture() in ["arm", "armv7", "armv7k"]: pc_value_int &= ~1 self.assertEqual( @@ -91,7 +93,17 @@ class FrameAPITestCase(TestBase): frame.GetSP(), "SP gotten as a value should equal frame's GetSP", ) - + # Test that the "register" property's flat list matches the list from + # the "registers" property that returns register sets: + register_regs = set() + flattened_regs = set() + for reg_set in frame.registers: + for reg in reg_set: + flattened_regs.add(reg.name) + for reg in frame.register: + register_regs.add(reg.name) + self.assertEqual(register_regs, flattened_regs, "register matches registers") + print("---", file=session) process.Continue() -- GitLab From 83dc41992dc602070f5429e2717352f60aad931c Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Fri, 12 Apr 2024 11:14:20 -0700 Subject: [PATCH 100/464] [memprof] Clean up writer traits (NFC) (#88549) RecordWriter does not live past the end of writeMemProfRecords, so it can be safely on stack. The constructor of FrameWriter does not take any parameter, so we can let OnDiskChainedHashTableGenerator::Emit (with a single parameter) default-construct an instance of the writer trait inside Emit. --- llvm/lib/ProfileData/InstrProfWriter.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index 7c56cde3e6ce..ede042dd6b9c 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -428,14 +428,13 @@ static uint64_t writeMemProfRecords( llvm::MapVector &MemProfRecordData, memprof::MemProfSchema *Schema) { - auto RecordWriter = - std::make_unique(memprof::Version1); - RecordWriter->Schema = Schema; + memprof::RecordWriterTrait RecordWriter(memprof::Version1); + RecordWriter.Schema = Schema; OnDiskChainedHashTableGenerator RecordTableGenerator; for (auto &[GUID, Record] : MemProfRecordData) { // Insert the key (func hash) and value (memprof record). - RecordTableGenerator.insert(GUID, Record, *RecordWriter.get()); + RecordTableGenerator.insert(GUID, Record, RecordWriter); } // Release the memory of this MapVector as it is no longer needed. MemProfRecordData.clear(); @@ -443,14 +442,13 @@ static uint64_t writeMemProfRecords( // The call to Emit invokes RecordWriterTrait::EmitData which destructs // the memprof record copies owned by the RecordTableGenerator. This works // because the RecordTableGenerator is not used after this point. - return RecordTableGenerator.Emit(OS.OS, *RecordWriter); + return RecordTableGenerator.Emit(OS.OS, RecordWriter); } // Serialize MemProfFrameData. Return FrameTableOffset. static uint64_t writeMemProfFrames( ProfOStream &OS, llvm::MapVector &MemProfFrameData) { - auto FrameWriter = std::make_unique(); OnDiskChainedHashTableGenerator FrameTableGenerator; for (auto &[FrameId, Frame] : MemProfFrameData) { @@ -460,7 +458,7 @@ static uint64_t writeMemProfFrames( // Release the memory of this MapVector as it is no longer needed. MemProfFrameData.clear(); - return FrameTableGenerator.Emit(OS.OS, *FrameWriter); + return FrameTableGenerator.Emit(OS.OS); } static Error writeMemProfV0( -- GitLab From 0318ce8552896df7b180ee5481463eada65c755e Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Fri, 12 Apr 2024 14:15:22 -0400 Subject: [PATCH 101/464] [C99] Claim conformance for _Complex support (#88161) There's so much overlap between the cited papers so this condenses the status page into a single entry rather than trying to test conformance against multiple papers doing conflicting things. --- clang/test/C/C99/n809.c | 122 ++++++++++++++++++++++++++++++++++++++ clang/test/C/C99/n809_2.c | 64 ++++++++++++++++++++ clang/test/C/C99/n809_3.c | 12 ++++ clang/www/c_status.html | 37 +++++------- 4 files changed, 213 insertions(+), 22 deletions(-) create mode 100644 clang/test/C/C99/n809.c create mode 100644 clang/test/C/C99/n809_2.c create mode 100644 clang/test/C/C99/n809_3.c diff --git a/clang/test/C/C99/n809.c b/clang/test/C/C99/n809.c new file mode 100644 index 000000000000..7297443a777c --- /dev/null +++ b/clang/test/C/C99/n809.c @@ -0,0 +1,122 @@ +// RUN: %clang_cc1 -verify -std=c99 %s + +/* WG14 N620, N638, N657, N694, N809: Partial + * Complex and imaginary support in + * + * NB: Clang supports _Complex but not _Imaginary. In C99, _Complex support is + * required outside of freestanding, but _Imaginary support is fully optional. + * In C11, both are made fully optional. + * + * NB: _Complex support requires an underlying support library such as + * compiler-rt to provide functions like __divsc3. Compiler-rt is not supported + * on Windows. + * + * Because the functionality is so intertwined between the various papers, + * we're testing all of the functionality in one file. + */ + +// Demonstrate that we support spelling complex floating-point objects. +float _Complex f1; +_Complex float f2; + +double _Complex d1; +_Complex double d2; + +long double _Complex ld1; +_Complex long double ld2; + +// Show that we don't support spelling imaginary types. +float _Imaginary fi1; // expected-error {{imaginary types are not supported}} +_Imaginary float fi2; // expected-error {{imaginary types are not supported}} + +double _Imaginary di1; // expected-error {{imaginary types are not supported}} +_Imaginary double di2; // expected-error {{imaginary types are not supported}} + +long double _Imaginary ldi1; // expected-error {{imaginary types are not supported}} +_Imaginary long double ldi2; // expected-error {{imaginary types are not supported}} + +// Each complex type has the same representation and alignment as an array +// containing two elements of the corresponding real type. Note, it is not +// mandatory that the alignment of a structure containing an array of two +// elements has the same alignment as an array of two elements outside of a +// structure, but this is a property Clang supports. +_Static_assert(sizeof(float _Complex) == sizeof(struct { float mem[2]; }), ""); +_Static_assert(_Alignof(float _Complex) == _Alignof(struct { float mem[2]; }), ""); + +_Static_assert(sizeof(double _Complex) == sizeof(struct { double mem[2]; }), ""); +_Static_assert(_Alignof(double _Complex) == _Alignof(struct { double mem[2]; }), ""); + +_Static_assert(sizeof(long double _Complex) == sizeof(struct { long double mem[2]; }), ""); +_Static_assert(_Alignof(long double _Complex) == _Alignof(struct { long double mem[2]; }), ""); + +// The first element corresponds to the real part and the second element +// corresponds to the imaginary part. +_Static_assert(__real((float _Complex){ 1.0f, 2.0f }) == 1.0f, ""); +_Static_assert(__imag((float _Complex){ 1.0f, 2.0f }) == 2.0f, ""); + +_Static_assert(__real((double _Complex){ 1.0, 2.0 }) == 1.0, ""); +_Static_assert(__imag((double _Complex){ 1.0, 2.0 }) == 2.0, ""); + +_Static_assert(__real((long double _Complex){ 1.0L, 2.0L }) == 1.0L, ""); +_Static_assert(__imag((long double _Complex){ 1.0L, 2.0L }) == 2.0L, ""); + +// When a real value is converted to a complex value, the real part follows the +// usual conversion rules and the imaginary part should be zero. +_Static_assert(__real((float _Complex)1.0f) == 1.0f, ""); +_Static_assert(__imag((float _Complex)1.0f) == 0.0f, ""); + +_Static_assert(__real((double _Complex)1.0f) == 1.0, ""); +_Static_assert(__imag((double _Complex)1.0f) == 0.0, ""); + +_Static_assert(__real((long double _Complex)1.0f) == 1.0L, ""); +_Static_assert(__imag((long double _Complex)1.0f) == 0.0L, ""); + +// When a complex value is converted to a real value, the real part follows the +// usual conversion rules and the imaginary part is discarded. +_Static_assert((float)(float _Complex){ 1.0f, 2.0f } == 1.0f, ""); +_Static_assert((double)(float _Complex){ 1.0f, 2.0f } == 1.0, ""); +_Static_assert((long double)(float _Complex){ 1.0f, 2.0f } == 1.0L, ""); + +// Complex values are only equal if both the real and imaginary parts are equal. +_Static_assert((float _Complex){ 1.0f, 2.0f } == (float _Complex){ 1.0f, 2.0f }, ""); +_Static_assert((double _Complex){ 1.0, 2.0 } == (double _Complex){ 1.0, 2.0 }, ""); +_Static_assert((long double _Complex){ 1.0L, 2.0L } == (long double _Complex){ 1.0L, 2.0L }, ""); + +_Static_assert((float _Complex){ 1.0f, 2.0f } != (float _Complex){ 2.0f, 0.0f }, ""); +_Static_assert((double _Complex){ 1.0, 2.0 } != (double _Complex){ 2.0, 0.0 }, ""); +_Static_assert((long double _Complex){ 1.0L, 2.0L } != (long double _Complex){ 2.0L, 0.0L }, ""); + +// You cannot use relational operator on complex values. +int i1 = (float _Complex){ 1.0f, 2.0f } < 10; // expected-error {{invalid operands to binary expression}} +int i2 = (double _Complex){ 1.0f, 2.0f } > 10; // expected-error {{invalid operands to binary expression}} +int i3 = (long double _Complex){ 1.0f, 2.0f } <= 10; // expected-error {{invalid operands to binary expression}} +int i4 = (float _Complex){ 1.0f, 2.0f } >= 10; // expected-error {{invalid operands to binary expression}} + +// As a type specifier, _Complex cannot appear alone; however, we support it as +// an extension by assuming _Complex double. +_Complex c = 1.0f; // expected-warning {{plain '_Complex' requires a type specifier; assuming '_Complex double'}} +// Because we don't support imaginary types, we don't extend the extension to +// that type specifier. +// FIXME: the warning diagnostic here is incorrect and should not be emitted. +_Imaginary i = 1.0f; // expected-warning {{plain '_Complex' requires a type specifier; assuming '_Complex double'}} \ + expected-error {{imaginary types are not supported}} + +void func(void) { +#pragma clang diagnostic push +#pragma clang diagnostic warning "-Wpedantic" + // Increment and decrement operators have a constraint that their operand be + // a real type; Clang supports this as an extension on complex types as well. + _Complex float cf = 0.0f; + + cf++; // expected-warning {{'++' on an object of complex type is a Clang extension}} + ++cf; // expected-warning {{'++' on an object of complex type is a Clang extension}} + + cf--; // expected-warning {{'--' on an object of complex type is a Clang extension}} + --cf; // expected-warning {{'--' on an object of complex type is a Clang extension}} + + // However, unary + and - are fine, as is += 1. + (void)-cf; + (void)+cf; + cf += 1; +#pragma clang diagnostic pop +} diff --git a/clang/test/C/C99/n809_2.c b/clang/test/C/C99/n809_2.c new file mode 100644 index 000000000000..3bf163126521 --- /dev/null +++ b/clang/test/C/C99/n809_2.c @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -ast-dump -std=c99 %s | FileCheck %s + +void variadic(int i, ...); + +void func(void) { + // CHECK: FunctionDecl {{.*}} func 'void (void)' + + // Show that we correctly convert between two complex domains. + _Complex float cf = 1.0f; + _Complex double cd; + + cd = cf; + // CHECK: BinaryOperator {{.*}} '_Complex double' '=' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cd' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex double' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' + + cf = cd; + // CHECK: BinaryOperator {{.*}} '_Complex float' '=' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex double' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cd' + + // Show that we correctly convert to the common type of a complex and real. + // This should convert the _Complex float to a _Complex double ("without + // change of domain" c.f. C99 6.3.1.8p1). + (void)(cf + 1.0); + // CHECK: BinaryOperator {{.*}} '_Complex double' '+' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex double' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' + // CHECK-NEXT: FloatingLiteral {{.*}} 'double' 1.0 + + // This should convert the float constant to double, then produce a + // _Complex double. + (void)(cd + 1.0f); + // CHECK: BinaryOperator {{.*}} '_Complex double' '+' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex double' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cd' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' + // CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.0 + + // This should convert the int constant to float, then produce a + // _Complex float. + (void)(cf + 1); + // CHECK: BinaryOperator {{.*}} '_Complex float' '+' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 + + // Show that we do not promote a _Complex float to _Complex double as part of + // the default argument promotions when passing to a variadic function. + variadic(1, cf); + // CHECK: CallExpr + // CHECK-NEXT: ImplicitCastExpr {{.*}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'variadic' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' +} + diff --git a/clang/test/C/C99/n809_3.c b/clang/test/C/C99/n809_3.c new file mode 100644 index 000000000000..f1283f5fe163 --- /dev/null +++ b/clang/test/C/C99/n809_3.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -emit-llvm -std=c99 %s -o - | FileCheck %s + +// Demonstrate that statics are properly zero initialized. +static _Complex float f_global; +void func(void) { + static _Complex double d_local; + d_local = f_global; +} + +// CHECK-DAG: @func.d_local = internal global { double, double } zeroinitializer +// CHECK-DAG: @f_global = internal global { float, float } zeroinitializer + diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 411f55447be7..9893170ae847 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -132,29 +132,22 @@ conformance.

Unknown Yes - - complex and imaginary support in <complex.h> + + complex and imaginary support in <complex.h> + N693 + +
Partial + Clang supports _Complex type specifiers but does not + support _Imaginary type specifiers. Support for + _Imaginary is optional in C99 and Clang does not claim + conformance to Annex G.
+
+ _Complex support requires an underlying support library + such as compiler-rt to provide functions like __divsc3, + but compiler-rt is not supported on Windows. +
+ - - N620 - Unknown - - - N638 - Unknown - - - N657 - Unknown - - - N694 - Unknown - - - N809 - Unknown - type-generic math macros in <tgmath.h> N693 -- GitLab From b074f25329501487e312b59e463a2d5f743090f8 Mon Sep 17 00:00:00 2001 From: elizabethandrews Date: Fri, 12 Apr 2024 14:41:49 -0400 Subject: [PATCH 102/464] [NFC][Clang] Fix static analyzer concern (#88179) Fix static analyzer concerns about dereferencing null values. --- clang/lib/AST/Interp/InterpState.h | 6 +++++- clang/lib/Sema/SemaAPINotes.cpp | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/InterpState.h b/clang/lib/AST/Interp/InterpState.h index 8f84bf6ed2ea..c17cfad11b1e 100644 --- a/clang/lib/AST/Interp/InterpState.h +++ b/clang/lib/AST/Interp/InterpState.h @@ -89,7 +89,11 @@ public: /// Delegates source mapping to the mapper. SourceInfo getSource(const Function *F, CodePtr PC) const override { - return M ? M->getSource(F, PC) : F->getSource(PC); + if (M) + return M->getSource(F, PC); + + assert(F && "Function cannot be null"); + return F->getSource(PC); } Context &getContext() const { return Ctx; } diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index a3128306c664..4c445f28bba8 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -463,6 +463,8 @@ static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc, D = MD; } + assert((FD || MD) && "Expecting Function or ObjCMethod"); + // Nullability of return type. if (Info.NullabilityAudited) applyNullability(S, D, Info.getReturnTypeInfo(), Metadata); -- GitLab From c777c011a709dffd4fa5e79cad7947b7c3405d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= Date: Fri, 12 Apr 2024 21:10:19 +0200 Subject: [PATCH 103/464] [GlobalIsel] Import vscale (#88240) https://github.com/llvm/llvm-project/pull/84542 --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 4 ++ .../AArch64/GlobalISel/irtranslator-vscale.ll | 52 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vscale.ll diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 312e564f5d80..9b4575f7f34d 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2550,6 +2550,10 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, MIRBuilder.buildInstr(TargetOpcode::G_RESET_FPMODE, {}, {}); return true; } + case Intrinsic::vscale: { + MIRBuilder.buildVScale(getOrCreateVReg(CI), 1); + return true; + } case Intrinsic::prefetch: { Value *Addr = CI.getOperand(0); unsigned RW = cast(CI.getOperand(1))->getZExtValue(); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vscale.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vscale.ll new file mode 100644 index 000000000000..d06e2c64c245 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vscale.ll @@ -0,0 +1,52 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -O0 -mtriple=aarch64-linux-gnu -global-isel -stop-after=irtranslator %s -o - | FileCheck %s + +define i64 @call_vscale_i64() { + ; CHECK-LABEL: name: call_vscale_i64 + ; CHECK: bb.1.entry: + ; CHECK-NEXT: [[VSCALE:%[0-9]+]]:_(s64) = G_VSCALE i64 1 + ; CHECK-NEXT: $x0 = COPY [[VSCALE]](s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 +entry: + %vscale = call i64 @llvm.vscale.64() + ret i64 %vscale +} + +define i64 @call_vscale_i32() { + ; CHECK-LABEL: name: call_vscale_i32 + ; CHECK: bb.1.entry: + ; CHECK-NEXT: [[VSCALE:%[0-9]+]]:_(s32) = G_VSCALE i32 1 + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[VSCALE]](s32) + ; CHECK-NEXT: $x0 = COPY [[ZEXT]](s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 +entry: + %vscale = call i32 @llvm.vscale.32() + %zext = zext i32 %vscale to i64 + ret i64 %zext +} + +define i64 @call_vscale_i16() { + ; CHECK-LABEL: name: call_vscale_i16 + ; CHECK: bb.1.entry: + ; CHECK-NEXT: [[VSCALE:%[0-9]+]]:_(s16) = G_VSCALE i16 1 + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[VSCALE]](s16) + ; CHECK-NEXT: $x0 = COPY [[ZEXT]](s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 +entry: + %vscale = call i16 @llvm.vscale.16() + %zext = zext i16 %vscale to i64 + ret i64 %zext +} + +define i64 @call_vscale_i8() { + ; CHECK-LABEL: name: call_vscale_i8 + ; CHECK: bb.1.entry: + ; CHECK-NEXT: [[VSCALE:%[0-9]+]]:_(s8) = G_VSCALE i8 1 + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[VSCALE]](s8) + ; CHECK-NEXT: $x0 = COPY [[ZEXT]](s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 +entry: + %vscale = call i8 @llvm.vscale.8() + %zext = zext i8 %vscale to i64 + ret i64 %zext +} -- GitLab From a9111d4a26514e169ca57c11e6533ca7c5408832 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 12 Apr 2024 12:33:19 -0700 Subject: [PATCH 104/464] [clang] Remove unused variable in test --- .../DependencyScanning/DependencyScanningFilesystemTest.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp index 50cad72d223e..697b7d70ff03 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp @@ -102,11 +102,8 @@ TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) { InMemoryFS->addFile("/foo.c", 0, llvm::MemoryBuffer::getMemBuffer("")); InMemoryFS->addFile("/bar.c", 0, llvm::MemoryBuffer::getMemBuffer("")); - auto InstrumentingFS = - llvm::makeIntrusiveRefCnt(InMemoryFS); - DependencyScanningFilesystemSharedCache SharedCache; - DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS); + DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS); // Success. { -- GitLab From 6dbd4bb3b4c00d62bf1552e54e4370c6816ea060 Mon Sep 17 00:00:00 2001 From: Jing Wang <2019426+jingw@users.noreply.github.com> Date: Fri, 12 Apr 2024 12:41:06 -0700 Subject: [PATCH 105/464] Add txtpb to the list of supported TextProto extensions (#88355) According to https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files, txtpb is the canonical extension Co-authored-by: Jing Wang <99jingw@gmail.com> --- clang/docs/ClangFormat.rst | 2 +- clang/lib/Format/Format.cpp | 6 +++++- clang/test/Format/lit.local.cfg | 1 + clang/tools/clang-format/ClangFormat.cpp | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst index 80dc38a075c8..dbd9c91ae508 100644 --- a/clang/docs/ClangFormat.rst +++ b/clang/docs/ClangFormat.rst @@ -54,7 +54,7 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code. Objective-C: .m .mm Proto: .proto .protodevel TableGen: .td - TextProto: .textpb .pb.txt .textproto .asciipb + TextProto: .txtpb .textpb .pb.txt .textproto .asciipb Verilog: .sv .svh .v .vh --cursor= - The position of the cursor when invoking clang-format from an editor integration diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 89e6c19b0af4..ccb2c9190e2e 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3891,7 +3891,11 @@ static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { FileName.ends_with_insensitive(".protodevel")) { return FormatStyle::LK_Proto; } - if (FileName.ends_with_insensitive(".textpb") || + // txtpb is the canonical extension, and textproto is the legacy canonical + // extension + // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files + if (FileName.ends_with_insensitive(".txtpb") || + FileName.ends_with_insensitive(".textpb") || FileName.ends_with_insensitive(".pb.txt") || FileName.ends_with_insensitive(".textproto") || FileName.ends_with_insensitive(".asciipb")) { diff --git a/clang/test/Format/lit.local.cfg b/clang/test/Format/lit.local.cfg index 3851397a3f7c..3eb0f54ceaa6 100644 --- a/clang/test/Format/lit.local.cfg +++ b/clang/test/Format/lit.local.cfg @@ -12,6 +12,7 @@ config.suffixes = [ ".proto", ".protodevel", ".pb.txt", + ".txtpb", ".textproto", ".textpb", ".asciipb", diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index ed401135ad84..feb733fe3c9e 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -92,7 +92,7 @@ static cl::opt AssumeFileName( " Objective-C: .m .mm\n" " Proto: .proto .protodevel\n" " TableGen: .td\n" - " TextProto: .textpb .pb.txt .textproto .asciipb\n" + " TextProto: .txtpb .textpb .pb.txt .textproto .asciipb\n" " Verilog: .sv .svh .v .vh"), cl::init(""), cl::cat(ClangFormatCategory)); -- GitLab From 4078afc6d23e25df6baedad61b224ef86a94d42f Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Fri, 12 Apr 2024 14:52:24 -0500 Subject: [PATCH 106/464] [LLVM][OpenMP] Add "nowait" clause as valid for "workshare" (#88426) Add the "nowait" clause to the list of allowed clauses for the "workshare" directive. This will make it consistent with other directives (which are shared between C/C++ and Fortran). The parser will still reject "nowait" on "!$omp workshare", so this has no effect on accepting/rejecting Fortran source code. --- flang/lib/Semantics/check-omp-structure.h | 1 + flang/test/Semantics/OpenMP/clause-validity01.f90 | 3 +++ llvm/include/llvm/Frontend/OpenMP/OMP.td | 3 +++ 3 files changed, 7 insertions(+) diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 33243d926cf1..8287653458e1 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -42,6 +42,7 @@ static const OmpDirectiveSet noWaitClauseNotAllowedSet{ Directive::OMPD_do_simd, Directive::OMPD_sections, Directive::OMPD_single, + Directive::OMPD_workshare, }; } // namespace omp } // namespace llvm diff --git a/flang/test/Semantics/OpenMP/clause-validity01.f90 b/flang/test/Semantics/OpenMP/clause-validity01.f90 index 977a52986461..74f154bb0ad6 100644 --- a/flang/test/Semantics/OpenMP/clause-validity01.f90 +++ b/flang/test/Semantics/OpenMP/clause-validity01.f90 @@ -342,6 +342,9 @@ use omp_lib a = 1.0 !ERROR: COPYPRIVATE clause is not allowed on the END WORKSHARE directive !$omp end workshare nowait copyprivate(a) + !$omp workshare nowait + !ERROR: NOWAIT clause is not allowed on the WORKSHARE directive, use it on OMP END WORKSHARE directive + !$omp end workshare !$omp end parallel ! 2.8.1 simd-clause -> safelen-clause | diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index d9a931438b42..e91169e8da1a 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -2115,6 +2115,9 @@ def OMP_scope : Directive<"scope"> { let association = AS_Block; } def OMP_Workshare : Directive<"workshare"> { + let allowedOnceClauses = [ + VersionedClause + ]; let association = AS_Block; } def OMP_ParallelWorkshare : Directive<"parallel workshare"> { -- GitLab From 41ff91e143a72dcd5755c9ad2160cf3c333b50c6 Mon Sep 17 00:00:00 2001 From: OverMighty Date: Fri, 12 Apr 2024 21:01:36 +0100 Subject: [PATCH 107/464] Reapply "[libc][math][c23] Add remaining linux/* entrypoints for {,u}fromfp{,x}* (#86692)" (#88567) This reverts commit 8a071678a9091d536eae29912ca7be6238105956. The test failure on 32-bit Arm should have been fixed by #86892. cc @nickdesaulniers @lntue --- libc/config/linux/aarch64/entrypoints.txt | 16 ++++++++++++++++ libc/config/linux/arm/entrypoints.txt | 12 ++++++++++++ libc/config/linux/riscv/entrypoints.txt | 16 ++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index f5f5c437685a..2952baacdd67 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -398,6 +398,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl + libc.src.math.fromfp + libc.src.math.fromfpf + libc.src.math.fromfpl + libc.src.math.fromfpx + libc.src.math.fromfpxf + libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -480,6 +486,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl + libc.src.math.ufromfp + libc.src.math.ufromfpf + libc.src.math.ufromfpl + libc.src.math.ufromfpx + libc.src.math.ufromfpxf + libc.src.math.ufromfpxl ) if(LIBC_TYPES_HAS_FLOAT128) @@ -502,6 +514,8 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.fminimum_mag_numf128 libc.src.math.fmodf128 libc.src.math.frexpf128 + libc.src.math.fromfpf128 + libc.src.math.fromfpxf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 @@ -519,6 +533,8 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 + libc.src.math.ufromfpf128 + libc.src.math.ufromfpxf128 ) endif() diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index fca50735d320..35fd588a9a6c 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -265,6 +265,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl + libc.src.math.fromfp + libc.src.math.fromfpf + libc.src.math.fromfpl + libc.src.math.fromfpx + libc.src.math.fromfpxf + libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -347,6 +353,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl + libc.src.math.ufromfp + libc.src.math.ufromfpf + libc.src.math.ufromfpl + libc.src.math.ufromfpx + libc.src.math.ufromfpxf + libc.src.math.ufromfpxl ) set(TARGET_LLVMLIBC_ENTRYPOINTS diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 71289789158f..47c03a61c45a 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -406,6 +406,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl + libc.src.math.fromfp + libc.src.math.fromfpf + libc.src.math.fromfpl + libc.src.math.fromfpx + libc.src.math.fromfpxf + libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -488,6 +494,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl + libc.src.math.ufromfp + libc.src.math.ufromfpf + libc.src.math.ufromfpl + libc.src.math.ufromfpx + libc.src.math.ufromfpxf + libc.src.math.ufromfpxl ) if(LIBC_TYPES_HAS_FLOAT128) @@ -510,6 +522,8 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.fminimum_mag_numf128 libc.src.math.fmodf128 libc.src.math.frexpf128 + libc.src.math.fromfpf128 + libc.src.math.fromfpxf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 @@ -527,6 +541,8 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 + libc.src.math.ufromfpf128 + libc.src.math.ufromfpxf128 ) endif() -- GitLab From 5300a6731e98fbcf7bca68374e934de737166698 Mon Sep 17 00:00:00 2001 From: Jonathan Peyton Date: Fri, 12 Apr 2024 15:13:59 -0500 Subject: [PATCH 108/464] [OpenMP] Fix re-locking hang found in issue 86684 (#88539) This was initially reported here (including stacktraces): https://stackoverflow.com/questions/78183545/does-compiling-imagick-with-openmp-enabled-in-freebsd-13-2-cause-sched-yield If `__kmp_register_library_startup()` detects that another instance of the library is present, `__kmp_is_address_mapped()` is eventually called. which uses `kmpc_alloc()` to allocate memory. This function calls `__kmp_entry_thread()` to access the thread-local memory pool, which is a bad idea during initialization. This macro internally calls `__kmp_get_global_thread_id_reg()` which sets the bootstrap lock at the beginning (before calling `__kmp_register_library_startup()`). The fix is to use `KMP_INTERNAL_MALLOC()`/`KMP_INTERNAL_FREE()` instead of `kmpc_malloc()`/`kmpc_free()`. `KMP_INTERNAL_MALLOC` and `KMP_INTERNAL_FREE` do not use any bootstrap locks. They just translate to `malloc()`/`free()` and are meant to be used during library initialization before other library-specific allocators have been initialized. Fixes: #86684 --- openmp/runtime/src/z_Linux_util.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp index be47be0dcec2..11ce083f4801 100644 --- a/openmp/runtime/src/z_Linux_util.cpp +++ b/openmp/runtime/src/z_Linux_util.cpp @@ -2141,10 +2141,10 @@ int __kmp_is_address_mapped(void *addr) { // We pass from number of vm entry's semantic // to size of whole entry map list. lstsz = lstsz * 4 / 3; - buf = reinterpret_cast(kmpc_malloc(lstsz)); + buf = reinterpret_cast(KMP_INTERNAL_MALLOC(lstsz)); rc = sysctl(mib, 4, buf, &lstsz, NULL, 0); if (rc < 0) { - kmpc_free(buf); + KMP_INTERNAL_FREE(buf); return 0; } @@ -2168,7 +2168,7 @@ int __kmp_is_address_mapped(void *addr) { } lw += cursz; } - kmpc_free(buf); + KMP_INTERNAL_FREE(buf); #elif KMP_OS_DRAGONFLY char err[_POSIX2_LINE_MAX]; kinfo_proc *proc; @@ -2234,12 +2234,12 @@ int __kmp_is_address_mapped(void *addr) { return 0; } - buf = kmpc_malloc(sz); + buf = KMP_INTERNAL_MALLOC(sz); while (sz > 0 && (rd = pread(file, buf, sz, 0)) == sz) { void *newbuf; sz <<= 1; - newbuf = kmpc_realloc(buf, sz); + newbuf = KMP_INTERNAL_REALLOC(buf, sz); buf = newbuf; } @@ -2255,7 +2255,7 @@ int __kmp_is_address_mapped(void *addr) { } } - kmpc_free(map); + KMP_INTERNAL_FREE(map); close(file); KMP_INTERNAL_FREE(name); #elif KMP_OS_DARWIN -- GitLab From dfafe3822b1e59f938c256c25a92a7b555f78469 Mon Sep 17 00:00:00 2001 From: Alexander Richardson Date: Fri, 12 Apr 2024 13:20:30 -0700 Subject: [PATCH 109/464] Reland "[compiler-rt] Allow running tests without installing first" Currently, the testsuite uses the default runtimes path to find the runtimes libraries which may or may not match the just-built runtimes. This change uses the `-resource-dir` flag for clang whenever `COMPILER_RT_TEST_STANDALONE_BUILD_LIBS` is set to ensure that we are actually testing the currently built libraries rather than the ones bundled with `${COMPILER_RT_TEST_COMPILER}`. The existing logic works fine when clang and compiler-rt share the same build directory ``-DLLVM_ENABLE_PROJECTS=clang;compiler-rt`, but when building compiler-rt separately we need to tell the compiler used for the tests where it can find the just-built libraries. This reduces the fixes check-all failures to one in my configuration: ``` cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -G Ninja -DCMAKE_C_COMPILER=$HOME/output/upstream-llvm/bin/clang -DCMAKE_CXX_COMPILER=$HOME/output/upstream-llvm/bin/clang++ -DCOMPILER_RT_INCLUDE_TESTS=ON -DLLVM_EXTERNAL_LIT=$HOME/build/upstream-llvm-project-build/bin/llvm-lit -DLLVM_CMAKE_DIR=$HOME/output/upstream-llvm -DCOMPILER_RT_DEBUG=OFF -S $HOME/src/upstream-llvm-project/compiler-rt -B $HOME/src/upstream-llvm-project/compiler-rt/cmake-build-all-sanitizers ``` This relands the previous PR with fixes for Windows. Depends on https://github.com/llvm/llvm-project/pull/88074 to be merged first for GCC buildbots. Pull Request: https://github.com/llvm/llvm-project/pull/88075 --- compiler-rt/CMakeLists.txt | 23 +++++ compiler-rt/cmake/Modules/AddCompilerRT.cmake | 1 + compiler-rt/test/CMakeLists.txt | 8 -- compiler-rt/test/fuzzer/lit.cfg.py | 1 + compiler-rt/test/lit.common.cfg.py | 89 ++++++++++++++----- compiler-rt/test/lit.common.configured.in | 1 + compiler-rt/test/safestack/lit.cfg.py | 10 ++- 7 files changed, 101 insertions(+), 32 deletions(-) diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index f4e92f14db85..8649507ce1c7 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -584,6 +584,29 @@ string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${stdlib_flag}") string(REPLACE " " ";" COMPILER_RT_UNITTEST_CFLAGS "${COMPILER_RT_TEST_COMPILER_CFLAGS}") set(COMPILER_RT_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_CFLAGS}) +option(COMPILER_RT_TEST_STANDALONE_BUILD_LIBS + "When set to ON and testing in a standalone build, test the runtime \ + libraries built by this standalone build rather than the runtime libraries \ + shipped with the compiler (used for testing). When set to OFF and testing \ + in a standalone build, test the runtime libraries shipped with the compiler \ + (used for testing). This option has no effect if the compiler and this \ + build are configured to use the same runtime library path." + ON) +if (COMPILER_RT_TEST_STANDALONE_BUILD_LIBS) + # Ensure that the unit tests can find the sanitizer headers prior to installation. + list(APPEND COMPILER_RT_UNITTEST_CFLAGS "-I${CMAKE_CURRENT_LIST_DIR}/include") + # Ensure that unit tests link against the just-built runtime libraries instead + # of the ones bundled with the compiler by overriding the resource directory. + # + if ("${COMPILER_RT_TEST_COMPILER_ID}" MATCHES "Clang") + list(APPEND COMPILER_RT_UNITTEST_LINK_FLAGS "-resource-dir=${COMPILER_RT_OUTPUT_DIR}") + endif() + get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} rtlib_dir) + if (NOT WIN32) + list(APPEND COMPILER_RT_UNITTEST_LINK_FLAGS "-Wl,-rpath,${rtlib_dir}") + endif() +endif() + if(COMPILER_RT_USE_LLVM_UNWINDER) # We're linking directly against the libunwind that we're building so don't # try to link in the toolchain's default libunwind which may be missing. diff --git a/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/compiler-rt/cmake/Modules/AddCompilerRT.cmake index dc36f16c661c..6e0d9dbff65a 100644 --- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -771,6 +771,7 @@ function(configure_compiler_rt_lit_site_cfg input output) get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir) string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} COMPILER_RT_RESOLVED_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER}) + string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} COMPILER_RT_RESOLVED_OUTPUT_DIR ${COMPILER_RT_OUTPUT_DIR}) string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR ${output_dir}) configure_lit_site_cfg(${input} ${output}) diff --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt index c186be1e44fd..edc007aaf477 100644 --- a/compiler-rt/test/CMakeLists.txt +++ b/compiler-rt/test/CMakeLists.txt @@ -1,14 +1,6 @@ # Needed for lit support in standalone builds. include(AddLLVM) -option(COMPILER_RT_TEST_STANDALONE_BUILD_LIBS - "When set to ON and testing in a standalone build, test the runtime \ - libraries built by this standalone build rather than the runtime libraries \ - shipped with the compiler (used for testing). When set to OFF and testing \ - in a standalone build, test the runtime libraries shipped with the compiler \ - (used for testing). This option has no effect if the compiler and this \ - build are configured to use the same runtime library path." - ON) pythonize_bool(COMPILER_RT_TEST_STANDALONE_BUILD_LIBS) pythonize_bool(LLVM_ENABLE_EXPENSIVE_CHECKS) diff --git a/compiler-rt/test/fuzzer/lit.cfg.py b/compiler-rt/test/fuzzer/lit.cfg.py index 9084254b3b15..0c0550ac729d 100644 --- a/compiler-rt/test/fuzzer/lit.cfg.py +++ b/compiler-rt/test/fuzzer/lit.cfg.py @@ -106,6 +106,7 @@ def generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True, msan_enabled=False): return " ".join( [ compiler_cmd, + config.target_cflags, std_cmd, "-O2 -gline-tables-only", sanitizers_cmd, diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index 0ac20a9831d9..28f126a11b16 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -14,6 +14,27 @@ import lit.formats import lit.util +def get_path_from_clang(args, allow_failure): + clang_cmd = [ + config.clang.strip(), + f"--target={config.target_triple}", + *args, + ] + path = None + try: + result = subprocess.run( + clang_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True + ) + path = result.stdout.decode().strip() + except subprocess.CalledProcessError as e: + msg = f"Failed to run {clang_cmd}\nrc:{e.returncode}\nstdout:{e.stdout}\ne.stderr{e.stderr}" + if allow_failure: + lit_config.warning(msg) + else: + lit_config.fatal(msg) + return path, clang_cmd + + def find_compiler_libdir(): """ Returns the path to library resource directory used @@ -26,26 +47,6 @@ def find_compiler_libdir(): # TODO: Support other compilers. return None - def get_path_from_clang(args, allow_failure): - clang_cmd = [ - config.clang.strip(), - f"--target={config.target_triple}", - ] - clang_cmd.extend(args) - path = None - try: - result = subprocess.run( - clang_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True - ) - path = result.stdout.decode().strip() - except subprocess.CalledProcessError as e: - msg = f"Failed to run {clang_cmd}\nrc:{e.returncode}\nstdout:{e.stdout}\ne.stderr{e.stderr}" - if allow_failure: - lit_config.warning(msg) - else: - lit_config.fatal(msg) - return path, clang_cmd - # Try using `-print-runtime-dir`. This is only supported by very new versions of Clang. # so allow failure here. runtime_dir, clang_cmd = get_path_from_clang( @@ -130,6 +131,7 @@ if execute_external: config.available_features.add("shell") target_is_msvc = bool(re.match(r".*-windows-msvc$", config.target_triple)) +target_is_windows = bool(re.match(r".*-windows.*$", config.target_triple)) compiler_id = getattr(config, "compiler_id", None) if compiler_id == "Clang": @@ -168,10 +170,53 @@ if config.enable_per_target_runtime_dir: r"/i386(?=-[^/]+$)", "/x86_64", config.compiler_rt_libdir ) + +# Check if the test compiler resource dir matches the local build directory +# (which happens with -DLLVM_ENABLE_PROJECTS=clang;compiler-rt) or if we are +# using an installed clang to test compiler-rt standalone. In the latter case +# we may need to override the resource dir to match the path of the just-built +# compiler-rt libraries. +test_cc_resource_dir, _ = get_path_from_clang( + shlex.split(config.target_cflags) + ["-print-resource-dir"], allow_failure=True +) +# Normalize the path for comparison +if test_cc_resource_dir is not None: + test_cc_resource_dir = os.path.realpath(test_cc_resource_dir) +if lit_config.debug: + lit_config.note(f"Resource dir for {config.clang} is {test_cc_resource_dir}") +local_build_resource_dir = os.path.realpath(config.compiler_rt_output_dir) +if test_cc_resource_dir != local_build_resource_dir and config.test_standalone_build_libs: + if config.compiler_id == "Clang": + if lit_config.debug: + lit_config.note( + f"Overriding test compiler resource dir to use " + f'libraries in "{config.compiler_rt_libdir}"' + ) + # Ensure that we use the just-built static libraries when linking by + # overriding the Clang resource directory. Additionally, we want to use + # the builtin headers shipped with clang (e.g. stdint.h), so we + # explicitly add this as an include path (since the headers are not + # going to be in the current compiler-rt build directory). + # We also tell the linker to add an RPATH entry for the local library + # directory so that the just-built shared libraries are used. + config.target_cflags += f" -nobuiltininc" + config.target_cflags += f" -I{config.compiler_rt_src_root}/include" + config.target_cflags += f" -idirafter {test_cc_resource_dir}/include" + config.target_cflags += f" -resource-dir={config.compiler_rt_output_dir}" + if not target_is_windows: + # Avoid passing -rpath on Windows where it is not supported. + config.target_cflags += f" -Wl,-rpath,{config.compiler_rt_libdir}" + else: + lit_config.warning( + f"Cannot override compiler-rt library directory with non-Clang " + f"compiler: {config.compiler_id}" + ) + + # Ask the compiler for the path to libraries it is going to use. If this # doesn't match config.compiler_rt_libdir then it means we might be testing the # compiler's own runtime libraries rather than the ones we just built. -# Warn about about this and handle appropriately. +# Warn about this and handle appropriately. compiler_libdir = find_compiler_libdir() if compiler_libdir: compiler_rt_libdir_real = os.path.realpath(config.compiler_rt_libdir) @@ -182,7 +227,7 @@ if compiler_libdir: f'compiler-rt libdir: "{compiler_rt_libdir_real}"' ) if config.test_standalone_build_libs: - # Use just built runtime libraries, i.e. the the libraries this built just built. + # Use just built runtime libraries, i.e. the libraries this build just built. if not config.test_suite_supports_overriding_runtime_lib_path: # Test suite doesn't support this configuration. # TODO(dliew): This should be an error but it seems several bots are diff --git a/compiler-rt/test/lit.common.configured.in b/compiler-rt/test/lit.common.configured.in index fff5dc6cc750..8889b816b149 100644 --- a/compiler-rt/test/lit.common.configured.in +++ b/compiler-rt/test/lit.common.configured.in @@ -27,6 +27,7 @@ set_default("compiler_id", "@COMPILER_RT_TEST_COMPILER_ID@") set_default("python_executable", "@Python3_EXECUTABLE@") set_default("compiler_rt_debug", @COMPILER_RT_DEBUG_PYBOOL@) set_default("compiler_rt_intercept_libdispatch", @COMPILER_RT_INTERCEPT_LIBDISPATCH_PYBOOL@) +set_default("compiler_rt_output_dir", "@COMPILER_RT_RESOLVED_OUTPUT_DIR@") set_default("compiler_rt_libdir", "@COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR@") set_default("emulator", "@COMPILER_RT_EMULATOR@") set_default("asan_shadow_scale", "@COMPILER_RT_ASAN_SHADOW_SCALE@") diff --git a/compiler-rt/test/safestack/lit.cfg.py b/compiler-rt/test/safestack/lit.cfg.py index adf27a0d7e5e..aadb8bf0d5c7 100644 --- a/compiler-rt/test/safestack/lit.cfg.py +++ b/compiler-rt/test/safestack/lit.cfg.py @@ -13,10 +13,16 @@ config.suffixes = [".c", ".cpp", ".m", ".mm", ".ll", ".test"] # Add clang substitutions. config.substitutions.append( - ("%clang_nosafestack ", config.clang + " -O0 -fno-sanitize=safe-stack ") + ( + "%clang_nosafestack ", + config.clang + config.target_cflags + " -O0 -fno-sanitize=safe-stack ", + ) ) config.substitutions.append( - ("%clang_safestack ", config.clang + " -O0 -fsanitize=safe-stack ") + ( + "%clang_safestack ", + config.clang + config.target_cflags + " -O0 -fsanitize=safe-stack ", + ) ) if config.lto_supported: -- GitLab From 588987405a979f724ab0aa7ad788cc5e87af3649 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Fri, 12 Apr 2024 13:34:47 -0700 Subject: [PATCH 110/464] [llvm][vfs] Make vfs::FileSystem::exists() virtual NFC (#88575) Allow a `vfs::FileSystem` to provide a more efficient implementation of `exists()` if they are able to. The existing `FileSystem` implementations continue to default to using `status()` except that overlay, proxy, and redirecting filesystems are taught to forward calls to `exists()` correctly to their wrapped/external filesystem. Co-authored-by: Ben Langmuir --- llvm/include/llvm/Support/VirtualFileSystem.h | 8 +- llvm/lib/Support/VirtualFileSystem.cpp | 56 ++++++ .../Support/VirtualFileSystemTest.cpp | 165 ++++++++++++++++++ 3 files changed, 227 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 4b1ca0c3d262..0113d6b7da25 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -300,8 +300,9 @@ public: virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output); - /// Check whether a file exists. Provided for convenience. - bool exists(const Twine &Path); + /// Check whether \p Path exists. By default this uses \c status(), but + /// filesystems may provide a more efficient implementation if available. + virtual bool exists(const Twine &Path); /// Is the file mounted on a local filesystem? virtual std::error_code isLocal(const Twine &Path, bool &Result); @@ -386,6 +387,7 @@ public: void pushOverlay(IntrusiveRefCntPtr FS); llvm::ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -439,6 +441,7 @@ public: llvm::ErrorOr status(const Twine &Path) override { return FS->status(Path); } + bool exists(const Twine &Path) override { return FS->exists(Path); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { return FS->openFileForRead(Path); @@ -1044,6 +1047,7 @@ public: bool UseExternalNames, FileSystem &ExternalFS); ErrorOr status(const Twine &Path) override; + bool exists(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 32b480028e71..921af30bfcde 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -438,6 +438,15 @@ ErrorOr OverlayFileSystem::status(const Twine &Path) { return make_error_code(llvm::errc::no_such_file_or_directory); } +bool OverlayFileSystem::exists(const Twine &Path) { + // FIXME: handle symlinks that cross file systems + for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { + if ((*I)->exists(Path)) + return true; + } + return false; +} + ErrorOr> OverlayFileSystem::openFileForRead(const llvm::Twine &Path) { // FIXME: handle symlinks that cross file systems @@ -2428,6 +2437,53 @@ ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { return S; } +bool RedirectingFileSystem::exists(const Twine &OriginalPath) { + SmallString<256> Path; + OriginalPath.toVector(Path); + + if (makeAbsolute(Path)) + return false; + + if (Redirection == RedirectKind::Fallback) { + // Attempt to find the original file first, only falling back to the + // mapped file if that fails. + if (ExternalFS->exists(Path)) + return true; + } + + ErrorOr Result = lookupPath(Path); + if (!Result) { + // Was not able to map file, fallthrough to using the original path if + // that was the specified redirection type. + if (Redirection == RedirectKind::Fallthrough && + isFileNotFound(Result.getError())) + return ExternalFS->exists(Path); + return false; + } + + std::optional ExtRedirect = Result->getExternalRedirect(); + if (!ExtRedirect) { + assert(isa(Result->E)); + return true; + } + + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (makeAbsolute(RemappedPath)) + return false; + + if (ExternalFS->exists(RemappedPath)) + return true; + + if (Redirection == RedirectKind::Fallthrough) { + // Mapped the file but it wasn't found in the underlying filesystem, + // fallthrough to using the original path if that was the specified + // redirection type. + return ExternalFS->exists(Path); + } + + return false; +} + namespace { /// Provide a file wrapper with an overriden status. diff --git a/llvm/unittests/Support/VirtualFileSystemTest.cpp b/llvm/unittests/Support/VirtualFileSystemTest.cpp index 49a2e19e4f74..e9b4ac3d92e1 100644 --- a/llvm/unittests/Support/VirtualFileSystemTest.cpp +++ b/llvm/unittests/Support/VirtualFileSystemTest.cpp @@ -201,6 +201,21 @@ class ErrorDummyFileSystem : public DummyFileSystem { } }; +/// A version of \c DummyFileSystem that aborts on \c status() to test that +/// \c exists() is being used. +class NoStatusDummyFileSystem : public DummyFileSystem { +public: + ErrorOr status(const Twine &Path) override { + llvm::report_fatal_error( + "unexpected call to NoStatusDummyFileSystem::status"); + } + + bool exists(const Twine &Path) override { + auto Status = DummyFileSystem::status(Path); + return Status && Status->exists(); + } +}; + /// Replace back-slashes by front-slashes. std::string getPosixPath(const Twine &S) { SmallString<128> Result; @@ -968,6 +983,30 @@ TEST(OverlayFileSystemTest, PrintOutput) { Output); } +TEST(OverlayFileSystemTest, Exists) { + IntrusiveRefCntPtr Lower(new NoStatusDummyFileSystem()); + IntrusiveRefCntPtr Upper(new NoStatusDummyFileSystem()); + IntrusiveRefCntPtr O( + new vfs::OverlayFileSystem(Lower)); + O->pushOverlay(Upper); + + Lower->addDirectory("/both"); + Upper->addDirectory("/both"); + Lower->addRegularFile("/both/lower_file"); + Upper->addRegularFile("/both/upper_file"); + Lower->addDirectory("/lower"); + Upper->addDirectory("/upper"); + + EXPECT_TRUE(O->exists("/both")); + EXPECT_TRUE(O->exists("/both")); + EXPECT_TRUE(O->exists("/both/lower_file")); + EXPECT_TRUE(O->exists("/both/upper_file")); + EXPECT_TRUE(O->exists("/lower")); + EXPECT_TRUE(O->exists("/upper")); + EXPECT_FALSE(O->exists("/both/nope")); + EXPECT_FALSE(O->exists("/nope")); +} + TEST(ProxyFileSystemTest, Basic) { IntrusiveRefCntPtr Base( new vfs::InMemoryFileSystem()); @@ -3364,6 +3403,11 @@ TEST(RedirectingFileSystemTest, ExternalPaths) { SeenPaths.push_back(Dir.str()); return ProxyFileSystem::dir_begin(Dir, EC); } + + bool exists(const Twine &Path) override { + SeenPaths.push_back(Path.str()); + return ProxyFileSystem::exists(Path); + } }; std::error_code EC; @@ -3395,3 +3439,124 @@ TEST(RedirectingFileSystemTest, ExternalPaths) { EXPECT_EQ(CheckFS->SeenPaths, Expected); } + +TEST(RedirectingFileSystemTest, Exists) { + IntrusiveRefCntPtr Dummy(new NoStatusDummyFileSystem()); + auto YAML = + MemoryBuffer::getMemBuffer("{\n" + " 'version': 0,\n" + " 'roots': [\n" + " {\n" + " 'type': 'directory-remap',\n" + " 'name': '/dremap',\n" + " 'external-contents': '/a',\n" + " }," + " {\n" + " 'type': 'directory-remap',\n" + " 'name': '/dmissing',\n" + " 'external-contents': '/dmissing',\n" + " }," + " {\n" + " 'type': 'directory',\n" + " 'name': '/both',\n" + " 'contents': [\n" + " {\n" + " 'type': 'file',\n" + " 'name': 'vfile',\n" + " 'external-contents': '/c'\n" + " }\n" + " ]\n" + " },\n" + " {\n" + " 'type': 'directory',\n" + " 'name': '/vdir',\n" + " 'contents': [" + " {\n" + " 'type': 'directory-remap',\n" + " 'name': 'dremap',\n" + " 'external-contents': '/b'\n" + " },\n" + " {\n" + " 'type': 'file',\n" + " 'name': 'missing',\n" + " 'external-contents': '/missing'\n" + " },\n" + " {\n" + " 'type': 'file',\n" + " 'name': 'vfile',\n" + " 'external-contents': '/c'\n" + " }]\n" + " }]\n" + "}"); + + Dummy->addDirectory("/a"); + Dummy->addRegularFile("/a/foo"); + Dummy->addDirectory("/b"); + Dummy->addRegularFile("/c"); + Dummy->addRegularFile("/both/foo"); + + auto Redirecting = vfs::RedirectingFileSystem::create( + std::move(YAML), nullptr, "", nullptr, Dummy); + + EXPECT_TRUE(Redirecting->exists("/dremap")); + EXPECT_FALSE(Redirecting->exists("/dmissing")); + EXPECT_FALSE(Redirecting->exists("/unknown")); + EXPECT_TRUE(Redirecting->exists("/both")); + EXPECT_TRUE(Redirecting->exists("/both/foo")); + EXPECT_TRUE(Redirecting->exists("/both/vfile")); + EXPECT_TRUE(Redirecting->exists("/vdir")); + EXPECT_TRUE(Redirecting->exists("/vdir/dremap")); + EXPECT_FALSE(Redirecting->exists("/vdir/missing")); + EXPECT_TRUE(Redirecting->exists("/vdir/vfile")); + EXPECT_FALSE(Redirecting->exists("/vdir/unknown")); +} + +TEST(RedirectingFileSystemTest, ExistsFallback) { + IntrusiveRefCntPtr Dummy(new NoStatusDummyFileSystem()); + auto YAML = + MemoryBuffer::getMemBuffer("{\n" + " 'version': 0,\n" + " 'redirecting-with': 'fallback',\n" + " 'roots': [\n" + " {\n" + " 'type': 'file',\n" + " 'name': '/fallback',\n" + " 'external-contents': '/missing',\n" + " }," + " ]\n" + "}"); + + Dummy->addRegularFile("/fallback"); + + auto Redirecting = vfs::RedirectingFileSystem::create( + std::move(YAML), nullptr, "", nullptr, Dummy); + + EXPECT_TRUE(Redirecting->exists("/fallback")); + EXPECT_FALSE(Redirecting->exists("/missing")); +} + +TEST(RedirectingFileSystemTest, ExistsRedirectOnly) { + IntrusiveRefCntPtr Dummy(new NoStatusDummyFileSystem()); + auto YAML = + MemoryBuffer::getMemBuffer("{\n" + " 'version': 0,\n" + " 'redirecting-with': 'redirect-only',\n" + " 'roots': [\n" + " {\n" + " 'type': 'file',\n" + " 'name': '/vfile',\n" + " 'external-contents': '/a',\n" + " }," + " ]\n" + "}"); + + Dummy->addRegularFile("/a"); + Dummy->addRegularFile("/b"); + + auto Redirecting = vfs::RedirectingFileSystem::create( + std::move(YAML), nullptr, "", nullptr, Dummy); + + EXPECT_FALSE(Redirecting->exists("/a")); + EXPECT_FALSE(Redirecting->exists("/b")); + EXPECT_TRUE(Redirecting->exists("/vfile")); +} -- GitLab From 62624a4bfed4ea468dcb677b799aee3518a24bf7 Mon Sep 17 00:00:00 2001 From: "Harrison,Hao" <57025411+TSWorld1314@users.noreply.github.com> Date: Sat, 13 Apr 2024 04:43:58 +0800 Subject: [PATCH 111/464] [Support] Fix the issue where the character being saved in Unicode causes a warning to be treated as an error in Visual Studio 2022. (#88513) Fix the issue where the character being saved in Unicode causes a warning to be treated as an error in Visual Studio 2022. ![image](https://github.com/llvm/llvm-project/assets/57025411/07353525-6520-4b74-b4f5-5b3f5afc47e1) --- llvm/lib/Support/Parallel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Support/Parallel.cpp b/llvm/lib/Support/Parallel.cpp index 9b14b05b5211..af35947192c0 100644 --- a/llvm/lib/Support/Parallel.cpp +++ b/llvm/lib/Support/Parallel.cpp @@ -57,7 +57,7 @@ public: Threads.resize(1); std::lock_guard Lock(Mutex); // Use operator[] before creating the thread to avoid data race in .size() - // in “safe libc++” mode. + // in 'safe libc++' mode. auto &Thread0 = Threads[0]; Thread0 = std::thread([this, S] { for (unsigned I = 1; I < ThreadCount; ++I) { -- GitLab From 8a4b7de91dc334c828674aa2cad927c6ffb9cf37 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 12 Apr 2024 12:45:47 -0700 Subject: [PATCH 112/464] [SLP][NFC]Make TTIRef capture argument instead of outer declaration. --- llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index df891371fdf7..7b5b0efca8d3 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -4895,14 +4895,10 @@ void BoUpSLP::reorderTopToBottom() { // Maps a TreeEntry to the reorder indices of external users. DenseMap> ExternalUserReorderMap; - // FIXME: Workaround for syntax error reported by MSVC buildbots. - TargetTransformInfo &TTIRef = *TTI; // Find all reorderable nodes with the given VF. // Currently the are vectorized stores,loads,extracts + some gathering of // extracts. - for_each(VectorizableTree, [this, &TTIRef, &VFToOrderedEntries, - &GathersToOrders, &ExternalUserReorderMap, - &AltShufflesToOrders, &PhisToOrders]( + for_each(VectorizableTree, [&, &TTIRef = *TTI]( const std::unique_ptr &TE) { // Look for external users that will probably be vectorized. SmallVector ExternalUserReorderIndices = @@ -9288,11 +9284,9 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, (void)E; return TTI->getInstructionCost(VI, CostKind); }; - // FIXME: Workaround for syntax error reported by MSVC buildbots. - TargetTransformInfo &TTIRef = *TTI; // Need to clear CommonCost since the final shuffle cost is included into // vector cost. - auto GetVectorCost = [&](InstructionCost) { + auto GetVectorCost = [&, &TTIRef = *TTI](InstructionCost) { // VecCost is equal to sum of the cost of creating 2 vectors // and the cost of creating shuffle. InstructionCost VecCost = 0; -- GitLab From 0f82469314f34a086669dfcd190a9f89260fbee5 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Fri, 12 Apr 2024 22:07:29 +0100 Subject: [PATCH 113/464] [Passes] Run SimpleLoopUnswitch after introducing invariant branches. (#81271) IndVars may be able to replace a loop dependent condition with a loop invariant one, but loop-unswitch runs before IndVars, so the invariant check remains in the loop. For an example, consider a read-only loop with a bounds check: https://godbolt.org/z/8cdj4qhbG This patch uses a approach similar to the way extra cleanup passes are run on demand after vectorization (added in acea6e9cfa4c4a0e8678c7). It introduces a new ShouldRunExtraSimpleLoopUnswitch analysis marker, which IndVars can use to indicate that extra unswitching is beneficial. ExtraSimpleLoopUnswitchPassManager uses this analysis to determine whether to run its passes on a loop. Compile-time impact (geomean) ranges from +0.0% to 0.02% https://llvm-compile-time-tracker.com/compare.php?from=138c0beb109ffe47f75a0fe8c4dc2cdabe8a6532&to=19e6e99eeb280d426907ea73a21b139ba7225627&stat=instructions%3Au Compile-time impact (geomean) of unconditionally running SimpleLoopUnswitch ranges from +0.05% - +0.16% https://llvm-compile-time-tracker.com/compare.php?from=138c0beb109ffe47f75a0fe8c4dc2cdabe8a6532&to=2930dfd5accdce2e6f8d5146ae4d626add2065a2&stat=instructions:u Unconditionally running SimpleLoopUnswitch seems to indicate that there are multiple other scenarios where we fail to run unswitching when opportunities remain. Fixes https://github.com/llvm/llvm-project/issues/85551. PR: https://github.com/llvm/llvm-project/pull/81271 --- .../Transforms/Scalar/SimpleLoopUnswitch.h | 35 ++++++ .../llvm/Transforms/Utils/SimplifyIndVar.h | 17 ++- llvm/lib/Passes/PassBuilderPipelines.cpp | 7 ++ llvm/lib/Passes/PassRegistry.def | 3 + llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 17 ++- .../Transforms/Scalar/SimpleLoopUnswitch.cpp | 1 + llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 20 +++- .../AArch64/hoist-runtime-checks.ll | 106 ++++++++++++++---- 8 files changed, 169 insertions(+), 37 deletions(-) diff --git a/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h b/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h index b97ee23fc0e6..a40b0a2a9ab7 100644 --- a/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h +++ b/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h @@ -12,6 +12,7 @@ #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { @@ -20,6 +21,40 @@ class Loop; class StringRef; class raw_ostream; +struct ShouldRunExtraSimpleLoopUnswitch + : public AnalysisInfoMixin { + static AnalysisKey Key; + struct Result { + bool invalidate(Loop &L, const PreservedAnalyses &PA, + LoopAnalysisManager::Invalidator &) { + // Check whether the analysis has been explicitly invalidated. Otherwise, + // it remains preserved. + auto PAC = PA.getChecker(); + return !PAC.preservedWhenStateless(); + } + }; + + Result run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR) { + return Result(); + } + + static bool isRequired() { return true; } +}; + +struct ExtraSimpleLoopUnswitchPassManager : public LoopPassManager { + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U) { + auto PA = PreservedAnalyses::all(); + if (AM.getCachedResult(L)) + PA.intersect(LoopPassManager::run(L, AM, AR, U)); + PA.abandon(); + return PA; + } + + static bool isRequired() { return true; } +}; + /// This pass transforms loops that contain branches or switches on loop- /// invariant conditions to have multiple loops. For example, it turns the left /// into the right code: diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h b/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h index ff60811b6168..bd1718dd8cad 100644 --- a/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h +++ b/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h @@ -15,6 +15,8 @@ #ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H #define LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H +#include + namespace llvm { class Type; @@ -46,11 +48,16 @@ public: }; /// simplifyUsersOfIV - Simplify instructions that use this induction variable -/// by using ScalarEvolution to analyze the IV's recurrence. -bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT, - LoopInfo *LI, const TargetTransformInfo *TTI, - SmallVectorImpl &Dead, - SCEVExpander &Rewriter, IVVisitor *V = nullptr); +/// by using ScalarEvolution to analyze the IV's recurrence. Returns a pair +/// where the first entry indicates that the function makes changes and the +/// second entry indicates that it introduced new opportunities for loop +/// unswitching. +std::pair simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, + DominatorTree *DT, LoopInfo *LI, + const TargetTransformInfo *TTI, + SmallVectorImpl &Dead, + SCEVExpander &Rewriter, + IVVisitor *V = nullptr); /// SimplifyLoopIVs - Simplify users of induction variables within this /// loop. This does not actually change or add IVs. diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index cb892e30c4a0..3bb2ce0ae346 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -651,6 +651,13 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, LPM2.addPass(LoopIdiomRecognizePass()); LPM2.addPass(IndVarSimplifyPass()); + { + ExtraSimpleLoopUnswitchPassManager ExtraPasses; + ExtraPasses.addPass(SimpleLoopUnswitchPass(/* NonTrivial */ Level == + OptimizationLevel::O3)); + LPM2.addPass(std::move(ExtraPasses)); + } + invokeLateLoopOptimizationsEPCallbacks(LPM2, Level); LPM2.addPass(LoopDeletionPass()); diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index d15f58d7adfa..2fbc7f7d88ba 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -587,6 +587,9 @@ LOOP_ANALYSIS("ddg", DDGAnalysis()) LOOP_ANALYSIS("iv-users", IVUsersAnalysis()) LOOP_ANALYSIS("no-op-loop", NoOpLoopAnalysis()) LOOP_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC)) +LOOP_ANALYSIS("should-run-extra-simple-loop-unswitch", + ShouldRunExtraSimpleLoopUnswitch()) + #undef LOOP_ANALYSIS #ifndef LOOP_PASS diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index 38104afa7f78..ba392e187b8b 100644 --- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -70,6 +70,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/LoopUtils.h" @@ -137,6 +138,8 @@ class IndVarSimplify { SmallVector DeadInsts; bool WidenIndVars; + bool RunUnswitching = false; + bool handleFloatingPointIV(Loop *L, PHINode *PH); bool rewriteNonIntegerIVs(Loop *L); @@ -170,6 +173,8 @@ public: } bool run(Loop *L); + + bool runUnswitching() const { return RunUnswitching; } }; } // end anonymous namespace @@ -615,9 +620,11 @@ bool IndVarSimplify::simplifyAndExtend(Loop *L, // Information about sign/zero extensions of CurrIV. IndVarSimplifyVisitor Visitor(CurrIV, SE, TTI, DT); - Changed |= simplifyUsersOfIV(CurrIV, SE, DT, LI, TTI, DeadInsts, Rewriter, - &Visitor); + const auto &[C, U] = simplifyUsersOfIV(CurrIV, SE, DT, LI, TTI, DeadInsts, + Rewriter, &Visitor); + Changed |= C; + RunUnswitching |= U; if (Visitor.WI.WidestNativeType) { WideIVs.push_back(Visitor.WI); } @@ -1874,6 +1881,7 @@ bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) { if (OldCond->use_empty()) DeadInsts.emplace_back(OldCond); Changed = true; + RunUnswitching = true; } return Changed; @@ -2059,6 +2067,11 @@ PreservedAnalyses IndVarSimplifyPass::run(Loop &L, LoopAnalysisManager &AM, auto PA = getLoopPassPreservedAnalyses(); PA.preserveSet(); + if (IVS.runUnswitching()) { + AM.getResult(L, AR); + PA.preserve(); + } + if (AR.MSSA) PA.preserve(); return PA; diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp index 64b850a6a5c2..d763b1ee0aa1 100644 --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -133,6 +133,7 @@ static cl::opt InjectInvariantConditionHotnesThreshold( "not-taken 1/ times or less."), cl::init(16)); +AnalysisKey ShouldRunExtraSimpleLoopUnswitch::Key; namespace { struct CompareDesc { BranchInst *Term; diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index f6d72265305d..440fe0790d79 100644 --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -60,6 +60,7 @@ namespace { SmallVectorImpl &DeadInsts; bool Changed = false; + bool RunUnswitching = false; public: SimplifyIndvar(Loop *Loop, ScalarEvolution *SE, DominatorTree *DT, @@ -72,6 +73,7 @@ namespace { } bool hasChanged() const { return Changed; } + bool runUnswitching() const { return RunUnswitching; } /// Iteratively perform simplification on a worklist of users of the /// specified induction variable. This is the top-level driver that applies @@ -233,6 +235,7 @@ bool SimplifyIndvar::makeIVComparisonInvariant(ICmpInst *ICmp, ICmp->setPredicate(InvariantPredicate); ICmp->setOperand(0, NewLHS); ICmp->setOperand(1, NewRHS); + RunUnswitching = true; return true; } @@ -993,14 +996,18 @@ void IVVisitor::anchor() { } /// Simplify instructions that use this induction variable /// by using ScalarEvolution to analyze the IV's recurrence. -bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT, - LoopInfo *LI, const TargetTransformInfo *TTI, - SmallVectorImpl &Dead, - SCEVExpander &Rewriter, IVVisitor *V) { +/// Returns a pair where the first entry indicates that the function makes +/// changes and the second entry indicates that it introduced new opportunities +/// for loop unswitching. +std::pair simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, + DominatorTree *DT, LoopInfo *LI, + const TargetTransformInfo *TTI, + SmallVectorImpl &Dead, + SCEVExpander &Rewriter, IVVisitor *V) { SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, DT, LI, TTI, Rewriter, Dead); SIV.simplifyUsers(CurrIV, V); - return SIV.hasChanged(); + return {SIV.hasChanged(), SIV.runUnswitching()}; } /// Simplify users of induction variables within this @@ -1014,8 +1021,9 @@ bool simplifyLoopIVs(Loop *L, ScalarEvolution *SE, DominatorTree *DT, #endif bool Changed = false; for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) { - Changed |= + const auto &[C, _] = simplifyUsersOfIV(cast(I), SE, DT, LI, TTI, Dead, Rewriter); + Changed |= C; } return Changed; } diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/hoist-runtime-checks.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/hoist-runtime-checks.ll index a140e17a0dd1..55dd28b70170 100644 --- a/llvm/test/Transforms/PhaseOrdering/AArch64/hoist-runtime-checks.ll +++ b/llvm/test/Transforms/PhaseOrdering/AArch64/hoist-runtime-checks.ll @@ -14,24 +14,50 @@ define i32 @read_only_loop_with_runtime_check(ptr noundef %array, i32 noundef %c ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[N]], -1 ; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i32 [[TMP1]], [[COUNT]] +; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[FOR_BODY_PREHEADER10:%.*]], label [[IF_THEN:%.*]] +; CHECK: for.body.preheader10: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 8 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[FOR_BODY_PREHEADER13:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP0]], 4294967288 +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI11:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[ARRAY]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 16 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[WIDE_LOAD12:%.*]] = load <4 x i32>, ptr [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4]] = add <4 x i32> [[WIDE_LOAD]], [[VEC_PHI]] +; CHECK-NEXT: [[TMP5]] = add <4 x i32> [[WIDE_LOAD12]], [[VEC_PHI11]] +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP5]], [[TMP4]] +; CHECK-NEXT: [[TMP7:%.*]] = tail call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[BIN_RDX]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N_VEC]], [[TMP0]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY_PREHEADER13]] +; CHECK: for.body.preheader13: +; CHECK-NEXT: [[INDVARS_IV_PH:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER10]] ], [ [[N_VEC]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: [[SUM_07_PH:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER10]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[IF_END:%.*]] ] +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[IF_END]] ] -; CHECK-NEXT: [[SUM_07:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[ADD]], [[IF_END]] ] -; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[IF_END]], label [[IF_THEN:%.*]] -; CHECK: if.then: -; CHECK-NEXT: tail call void @llvm.trap() -; CHECK-NEXT: unreachable -; CHECK: if.end: +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[INDVARS_IV_PH]], [[FOR_BODY_PREHEADER13]] ] +; CHECK-NEXT: [[SUM_07:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[SUM_07_PH]], [[FOR_BODY_PREHEADER13]] ] ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[ARRAY]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP2]], [[SUM_07]] +; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP8]], [[SUM_07]] ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[TMP0]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK: if.then: +; CHECK-NEXT: tail call void @llvm.trap() +; CHECK-NEXT: unreachable ; entry: %array.addr = alloca ptr, align 8 @@ -103,24 +129,50 @@ define dso_local noundef i32 @sum_prefix_with_sum(ptr %s.coerce0, i64 %s.coerce1 ; CHECK: for.body.preheader: ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1 ; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i64 [[TMP0]], [[S_COERCE1]] +; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[ENTRY:%.*]], label [[COND_FALSE_I:%.*]], !prof [[PROF4:![0-9]+]] +; CHECK: for.body.preheader8: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 8 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[FOR_BODY_PREHEADER11:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[N]], -8 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP3:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI9:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S_COERCE0]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 16 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[WIDE_LOAD10:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3]] = add <4 x i32> [[WIDE_LOAD]], [[VEC_PHI]] +; CHECK-NEXT: [[TMP4]] = add <4 x i32> [[WIDE_LOAD10]], [[VEC_PHI9]] +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP5]], label [[SPAN_CHECKED_ACCESS_EXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP4]], [[TMP3]] +; CHECK-NEXT: [[ADD:%.*]] = tail call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[BIN_RDX]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N_VEC]], [[N]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY_PREHEADER11]] +; CHECK: for.body.preheader11: +; CHECK-NEXT: [[I_07_PH:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[N_VEC]], [[SPAN_CHECKED_ACCESS_EXIT]] ] +; CHECK-NEXT: [[RET_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD]], [[SPAN_CHECKED_ACCESS_EXIT]] ] +; CHECK-NEXT: br label [[FOR_BODY1:%.*]] ; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[RET_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[SPAN_CHECKED_ACCESS_EXIT:%.*]] ] -; CHECK-NEXT: ret i32 [[RET_0_LCSSA]] +; CHECK-NEXT: [[RET_0_LCSSA1:%.*]] = phi i32 [ 0, [[ENTRY1:%.*]] ], [ [[ADD]], [[SPAN_CHECKED_ACCESS_EXIT]] ], [ [[ADD1:%.*]], [[FOR_BODY1]] ] +; CHECK-NEXT: ret i32 [[RET_0_LCSSA1]] ; CHECK: for.body: -; CHECK-NEXT: [[I_07:%.*]] = phi i64 [ [[INC:%.*]], [[SPAN_CHECKED_ACCESS_EXIT]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[RET_06:%.*]] = phi i32 [ [[ADD]], [[SPAN_CHECKED_ACCESS_EXIT]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[SPAN_CHECKED_ACCESS_EXIT]], label [[COND_FALSE_I:%.*]], !prof [[PROF0:![0-9]+]] -; CHECK: cond.false.i: -; CHECK-NEXT: tail call void @llvm.trap() -; CHECK-NEXT: unreachable -; CHECK: span_checked_access.exit: +; CHECK-NEXT: [[I_07:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY1]] ], [ [[I_07_PH]], [[FOR_BODY_PREHEADER11]] ] +; CHECK-NEXT: [[RET_06:%.*]] = phi i32 [ [[ADD1]], [[FOR_BODY1]] ], [ [[RET_0_LCSSA]], [[FOR_BODY_PREHEADER11]] ] ; CHECK-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds i32, ptr [[S_COERCE0]], i64 [[I_07]] ; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX_I]], align 4 -; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP7]], [[RET_06]] +; CHECK-NEXT: [[ADD1]] = add nsw i32 [[TMP7]], [[RET_06]] ; CHECK-NEXT: [[INC]] = add nuw i64 [[I_07]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INC]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY1]], !llvm.loop [[LOOP6:![0-9]+]] +; CHECK: cond.false.i: +; CHECK-NEXT: tail call void @llvm.trap() +; CHECK-NEXT: unreachable ; entry: %s = alloca %"class.std::__1::span", align 8 @@ -176,7 +228,7 @@ define hidden noundef nonnull align 4 dereferenceable(4) ptr @span_checked_acces ; CHECK-NEXT: [[__SIZE__I:%.*]] = getelementptr inbounds i8, ptr [[THIS]], i64 8 ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[__SIZE__I]], align 8 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[TMP0]], [[__IDX]] -; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]], !prof [[PROF0]] +; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]], !prof [[PROF4]] ; CHECK: cond.false: ; CHECK-NEXT: tail call void @llvm.trap() ; CHECK-NEXT: unreachable @@ -237,5 +289,11 @@ declare void @llvm.trap() declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) ;. -; CHECK: [[PROF0]] = !{!"branch_weights", i32 2000, i32 1} +; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} +; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} +; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} +; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]} +; CHECK: [[PROF4]] = !{!"branch_weights", i32 2000, i32 1} +; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META1]], [[META2]]} +; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META2]], [[META1]]} ;. -- GitLab From c6cd4608c8c4a5356ae41ef05e67df3dc5d9500b Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 12 Apr 2024 14:10:07 -0700 Subject: [PATCH 114/464] IRVerifier: Allow GlobalValue as llvm.threadlocal.address operand (#88321) Loosen `llvm.threadlocal.address` verifier checks to allow any `GlobalValue` with `isThreadLocal()` set to true. --- llvm/docs/LangRef.rst | 3 ++- llvm/lib/IR/Verifier.cpp | 8 +++--- llvm/test/Verifier/threadlocal-pass.ll | 13 ++++++++++ llvm/test/Verifier/threadlocal.ll | 34 ++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 llvm/test/Verifier/threadlocal-pass.ll create mode 100644 llvm/test/Verifier/threadlocal.ll diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index f6ada292b93b..9592929d79fe 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -28130,7 +28130,8 @@ Syntax: Arguments: """""""""" -The first argument is a thread local :ref:`global variable `. +The `llvm.threadlocal.address` intrinsic requires a global value argument (a +:ref:`global variable ` or alias) that is thread local. Semantics: """""""""" diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 4092f0cb12ff..25cb99f0f9bd 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -6226,10 +6226,10 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { } case Intrinsic::threadlocal_address: { const Value &Arg0 = *Call.getArgOperand(0); - Check(isa(Arg0), - "llvm.threadlocal.address first argument must be a GlobalVariable"); - Check(cast(Arg0).isThreadLocal(), - "llvm.threadlocal.address operand isThreadLocal() must no be false"); + Check(isa(Arg0), + "llvm.threadlocal.address first argument must be a GlobalValue"); + Check(cast(Arg0).isThreadLocal(), + "llvm.threadlocal.address operand isThreadLocal() must be true"); break; } }; diff --git a/llvm/test/Verifier/threadlocal-pass.ll b/llvm/test/Verifier/threadlocal-pass.ll new file mode 100644 index 000000000000..0cee4af82439 --- /dev/null +++ b/llvm/test/Verifier/threadlocal-pass.ll @@ -0,0 +1,13 @@ +; RUN: opt -passes=verify -S < %s | FileCheck %s + +@var = thread_local global i32 0 +@alias = thread_local alias i32, ptr @var + +; CHECK-LABEL: @should_pass +define void @should_pass() { + %p0 = call ptr @llvm.threadlocal.address(ptr @var) + store i32 42, ptr %p0, align 4 + %p1 = call ptr @llvm.threadlocal.address(ptr @alias) + store i32 13, ptr %p1, align 4 + ret void +} diff --git a/llvm/test/Verifier/threadlocal.ll b/llvm/test/Verifier/threadlocal.ll new file mode 100644 index 000000000000..8af23c361cc4 --- /dev/null +++ b/llvm/test/Verifier/threadlocal.ll @@ -0,0 +1,34 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +@var = global i32 0 +@tlsvar = thread_local addrspace(1) global i32 0 + +define void @fail0(ptr %arg) { +; CHECK: llvm.threadlocal.address first argument must be a GlobalValue + %p0 = call ptr @llvm.threadlocal.address(ptr %arg) + store i32 42, ptr %p0, align 4 + ret void +} + +define void @fail1() { +; CHECK: llvm.threadlocal.address first argument must be a GlobalValue + %p0 = call ptr @llvm.threadlocal.address.p0(ptr addrspacecast (ptr addrspace(1) @tlsvar to ptr addrspace(0))) + store i32 42, ptr %p0, align 4 + ret void +} + + + +define void @fail2() { +; CHECK: llvm.threadlocal.address operand isThreadLocal() must be true + %p0 = call ptr @llvm.threadlocal.address(ptr @var) + store i32 42, ptr %p0, align 4 + ret void +} + +define void @fail3() { +; CHECK: llvm.threadlocal.address operand isThreadLocal() must be true + %p0 = call ptr @llvm.threadlocal.address(ptr @fail2) + store i32 42, ptr %p0, align 4 + ret void +} -- GitLab From daa88364df15683bfa0e58d62cc96d33cd49d34b Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 12 Apr 2024 14:13:31 -0700 Subject: [PATCH 115/464] [OpenACC] Implement 'if' clause for Compute Constructs (#88411) Like with the 'default' clause, this is being applied to only Compute Constructs for now. The 'if' clause takes a condition expression which is used as a runtime value. This is not a particularly complex semantic implementation, as there isn't much to this clause, other than its interactions with 'self', which will be managed in the patch to implement that. --- clang/include/clang/AST/ASTNodeTraverser.h | 3 +- clang/include/clang/AST/OpenACCClause.h | 81 +++++++++++- clang/include/clang/Basic/OpenACCClauses.def | 21 +++ clang/include/clang/Parse/Parser.h | 5 + clang/include/clang/Sema/SemaOpenACC.h | 28 +++- clang/lib/AST/OpenACCClause.cpp | 39 ++++++ clang/lib/AST/StmtProfile.cpp | 19 ++- clang/lib/AST/TextNodeDumper.cpp | 5 + clang/lib/Parse/ParseOpenACC.cpp | 32 +++-- clang/lib/Sema/SemaOpenACC.cpp | 73 +++++++++-- clang/lib/Sema/TreeTransform.h | 14 ++ clang/lib/Serialization/ASTReader.cpp | 7 +- clang/lib/Serialization/ASTWriter.cpp | 7 +- clang/test/ParserOpenACC/parse-clauses.c | 2 - .../compute-construct-clause-ast.cpp | 120 +++++++++++++++++- .../SemaOpenACC/compute-construct-if-clause.c | 62 +++++++++ .../compute-construct-if-clause.cpp | 33 +++++ clang/tools/libclang/CIndex.cpp | 43 +++++++ 18 files changed, 557 insertions(+), 37 deletions(-) create mode 100644 clang/include/clang/Basic/OpenACCClauses.def create mode 100644 clang/test/SemaOpenACC/compute-construct-if-clause.c create mode 100644 clang/test/SemaOpenACC/compute-construct-if-clause.cpp diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index a6e3b05b0059..f5c47d8a7c21 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -243,7 +243,8 @@ public: void Visit(const OpenACCClause *C) { getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(C); - // TODO OpenACC: Switch on clauses that have children, and add them. + for (const auto *S : C->children()) + Visit(S); }); } diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 27e4e1a12c98..712ad46c0f23 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H #define LLVM_CLANG_AST_OPENACCCLAUSE_H #include "clang/AST/ASTContext.h" +#include "clang/AST/StmtIterator.h" #include "clang/Basic/OpenACCKinds.h" namespace clang { @@ -34,6 +35,17 @@ public: static bool classof(const OpenACCClause *) { return true; } + using child_iterator = StmtIterator; + using const_child_iterator = ConstStmtIterator; + using child_range = llvm::iterator_range; + using const_child_range = llvm::iterator_range; + + child_range children(); + const_child_range children() const { + auto Children = const_cast(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + virtual ~OpenACCClause() = default; }; @@ -49,6 +61,13 @@ protected: public: SourceLocation getLParenLoc() const { return LParenLoc; } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// A 'default' clause, has the optional 'none' or 'present' argument. @@ -81,6 +100,51 @@ public: SourceLocation EndLoc); }; +/// Represents one of the handful of classes that has an optional/required +/// 'condition' expression as an argument. +class OpenACCClauseWithCondition : public OpenACCClauseWithParams { + Expr *ConditionExpr = nullptr; + +protected: + OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *ConditionExpr, + SourceLocation EndLoc) + : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), + ConditionExpr(ConditionExpr) {} + +public: + bool hasConditionExpr() const { return ConditionExpr; } + const Expr *getConditionExpr() const { return ConditionExpr; } + Expr *getConditionExpr() { return ConditionExpr; } + + child_range children() { + if (ConditionExpr) + return child_range(reinterpret_cast(&ConditionExpr), + reinterpret_cast(&ConditionExpr + 1)); + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + if (ConditionExpr) + return const_child_range( + reinterpret_cast(&ConditionExpr), + reinterpret_cast(&ConditionExpr + 1)); + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// An 'if' clause, which has a required condition expression. +class OpenACCIfClause : public OpenACCClauseWithCondition { +protected: + OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + Expr *ConditionExpr, SourceLocation EndLoc); + +public: + static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *ConditionExpr, + SourceLocation EndLoc); +}; + template class OpenACCClauseVisitor { Impl &getDerived() { return static_cast(*this); } @@ -98,6 +162,9 @@ public: case OpenACCClauseKind::Default: VisitOpenACCDefaultClause(*cast(C)); return; + case OpenACCClauseKind::If: + VisitOpenACCIfClause(*cast(C)); + return; case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: @@ -106,7 +173,6 @@ public: case OpenACCClauseKind::Worker: case OpenACCClauseKind::Vector: case OpenACCClauseKind::NoHost: - case OpenACCClauseKind::If: case OpenACCClauseKind::Self: case OpenACCClauseKind::Copy: case OpenACCClauseKind::UseDevice: @@ -145,9 +211,13 @@ public: llvm_unreachable("Invalid Clause kind"); } - void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause) { - return getDerived().VisitOpenACCDefaultClause(Clause); +#define VISIT_CLAUSE(CLAUSE_NAME) \ + void VisitOpenACC##CLAUSE_NAME##Clause( \ + const OpenACC##CLAUSE_NAME##Clause &Clause) { \ + return getDerived().VisitOpenACC##CLAUSE_NAME##Clause(Clause); \ } + +#include "clang/Basic/OpenACCClauses.def" }; class OpenACCClausePrinter final @@ -165,7 +235,10 @@ public: } OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {} - void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause); +#define VISIT_CLAUSE(CLAUSE_NAME) \ + void VisitOpenACC##CLAUSE_NAME##Clause( \ + const OpenACC##CLAUSE_NAME##Clause &Clause); +#include "clang/Basic/OpenACCClauses.def" }; } // namespace clang diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def new file mode 100644 index 000000000000..7fd2720e02ce --- /dev/null +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -0,0 +1,21 @@ +//===-- OpenACCClauses.def - List of implemented OpenACC Clauses -- 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 file defines a list of currently implemented OpenACC Clauses (and +// eventually, the entire list) in a way that makes generating 'visitor' and +// other lists easier. +// +// The primary macro is a single-argument version taking the name of the Clause +// as used in Clang source (so `Default` instead of `default`). +// +// VISIT_CLAUSE(CLAUSE_NAME) + +VISIT_CLAUSE(Default) +VISIT_CLAUSE(If) + +#undef VISIT_CLAUSE diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 3a055c10ffb3..db90d38c7dac 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3611,6 +3611,9 @@ private: OpenACCClauseParseResult OpenACCCannotContinue(); OpenACCClauseParseResult OpenACCSuccess(OpenACCClause *Clause); + using OpenACCConditionExprParseResult = + std::pair; + /// Parses the OpenACC directive (the entire pragma) including the clause /// list, but does not produce the main AST node. OpenACCDirectiveParseInfo ParseOpenACCDirective(); @@ -3657,6 +3660,8 @@ private: bool ParseOpenACCGangArgList(); /// Parses a 'gang-arg', used for the 'gang' clause. bool ParseOpenACCGangArg(); + /// Parses a 'condition' expr, ensuring it results in a + ExprResult ParseOpenACCConditionExpr(); private: //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index 27aaee164a28..c1fe0f5b9c0f 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -40,7 +40,11 @@ public: OpenACCDefaultClauseKind DefaultClauseKind; }; - std::variant Details; + struct ConditionDetails { + Expr *ConditionExpr; + }; + + std::variant Details; public: OpenACCParsedClause(OpenACCDirectiveKind DirKind, @@ -63,6 +67,16 @@ public: return std::get(Details).DefaultClauseKind; } + const Expr *getConditionExpr() const { + return const_cast(this)->getConditionExpr(); + } + + Expr *getConditionExpr() { + assert(ClauseKind == OpenACCClauseKind::If && + "Parsed clause kind does not have a condition expr"); + return std::get(Details).ConditionExpr; + } + void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; } void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); } @@ -71,6 +85,18 @@ public: "Parsed clause is not a default clause"); Details = DefaultDetails{DefKind}; } + + void setConditionDetails(Expr *ConditionExpr) { + assert(ClauseKind == OpenACCClauseKind::If && + "Parsed clause kind does not have a condition expr"); + // In C++ we can count on this being a 'bool', but in C this gets left as + // some sort of scalar that codegen will have to take care of converting. + assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() || + ConditionExpr->getType()->isScalarType()) && + "Condition expression type not scalar/dependent"); + + Details = ConditionDetails{ConditionExpr}; + } }; SemaOpenACC(Sema &S); diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index c83128b60e3a..2bc8d14fa129 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -13,6 +13,7 @@ #include "clang/AST/OpenACCClause.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" using namespace clang; @@ -27,6 +28,40 @@ OpenACCDefaultClause *OpenACCDefaultClause::Create(const ASTContext &C, return new (Mem) OpenACCDefaultClause(K, BeginLoc, LParenLoc, EndLoc); } +OpenACCIfClause *OpenACCIfClause::Create(const ASTContext &C, + SourceLocation BeginLoc, + SourceLocation LParenLoc, + Expr *ConditionExpr, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OpenACCIfClause), alignof(OpenACCIfClause)); + return new (Mem) OpenACCIfClause(BeginLoc, LParenLoc, ConditionExpr, EndLoc); +} + +OpenACCIfClause::OpenACCIfClause(SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *ConditionExpr, + SourceLocation EndLoc) + : OpenACCClauseWithCondition(OpenACCClauseKind::If, BeginLoc, LParenLoc, + ConditionExpr, EndLoc) { + assert(ConditionExpr && "if clause requires condition expr"); + assert((ConditionExpr->isInstantiationDependent() || + ConditionExpr->getType()->isScalarType()) && + "Condition expression type not scalar/dependent"); +} + +OpenACCClause::child_range OpenACCClause::children() { + switch (getClauseKind()) { + default: + assert(false && "Clause children function not implemented"); + break; +#define VISIT_CLAUSE(CLAUSE_NAME) \ + case OpenACCClauseKind::CLAUSE_NAME: \ + return cast(this)->children(); + +#include "clang/Basic/OpenACCClauses.def" + } + return child_range(child_iterator(), child_iterator()); +} + //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// @@ -34,3 +69,7 @@ void OpenACCClausePrinter::VisitOpenACCDefaultClause( const OpenACCDefaultClause &C) { OS << "default(" << C.getDefaultClauseKind() << ")"; } + +void OpenACCClausePrinter::VisitOpenACCIfClause(const OpenACCIfClause &C) { + OS << "if(" << C.getConditionExpr() << ")"; +} diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 01e1d1cc8289..44b635bfb843 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2445,9 +2445,10 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { namespace { class OpenACCClauseProfiler : public OpenACCClauseVisitor { + StmtProfiler &Profiler; public: - OpenACCClauseProfiler() = default; + OpenACCClauseProfiler(StmtProfiler &P) : Profiler(P) {} void VisitOpenACCClauseList(ArrayRef Clauses) { for (const OpenACCClause *Clause : Clauses) { @@ -2456,12 +2457,24 @@ public: Visit(Clause); } } - void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause); + +#define VISIT_CLAUSE(CLAUSE_NAME) \ + void VisitOpenACC##CLAUSE_NAME##Clause( \ + const OpenACC##CLAUSE_NAME##Clause &Clause); + +#include "clang/Basic/OpenACCClauses.def" }; /// Nothing to do here, there are no sub-statements. void OpenACCClauseProfiler::VisitOpenACCDefaultClause( const OpenACCDefaultClause &Clause) {} + +void OpenACCClauseProfiler::VisitOpenACCIfClause( + const OpenACCIfClause &Clause) { + assert(Clause.hasConditionExpr() && + "if clause requires a valid condition expr"); + Profiler.VisitStmt(Clause.getConditionExpr()); +} } // namespace void StmtProfiler::VisitOpenACCComputeConstruct( @@ -2469,7 +2482,7 @@ void StmtProfiler::VisitOpenACCComputeConstruct( // VisitStmt handles children, so the AssociatedStmt is handled. VisitStmt(S); - OpenACCClauseProfiler P; + OpenACCClauseProfiler P{*this}; P.VisitOpenACCClauseList(S->clauses()); } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index f4b2df7730ae..0973e63183bd 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -397,6 +397,11 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { case OpenACCClauseKind::Default: OS << '(' << cast(C)->getDefaultClauseKind() << ')'; break; + case OpenACCClauseKind::If: + // The condition expression will be printed as a part of the 'children', + // but print 'clause' here so it is clear what is happening from the dump. + OS << " clause"; + break; default: // Nothing to do here. break; diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index b487a1968d1e..91f2b8afcf0c 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -535,14 +535,6 @@ bool ClauseHasRequiredParens(OpenACCDirectiveKind DirKind, return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required; } -ExprResult ParseOpenACCConditionalExpr(Parser &P) { - // FIXME: It isn't clear if the spec saying 'condition' means the same as - // it does in an if/while/etc (See ParseCXXCondition), however as it was - // written with Fortran/C in mind, we're going to assume it just means an - // 'expression evaluating to boolean'. - return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression()); -} - // Skip until we see the end of pragma token, but don't consume it. This is us // just giving up on the rest of the pragma so we can continue executing. We // have to do this because 'SkipUntil' considers paren balancing, which isn't @@ -595,6 +587,23 @@ Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) { return {Clause, OpenACCParseCanContinue::Can}; } +ExprResult Parser::ParseOpenACCConditionExpr() { + // FIXME: It isn't clear if the spec saying 'condition' means the same as + // it does in an if/while/etc (See ParseCXXCondition), however as it was + // written with Fortran/C in mind, we're going to assume it just means an + // 'expression evaluating to boolean'. + ExprResult ER = getActions().CorrectDelayedTyposInExpr(ParseExpression()); + + if (!ER.isUsable()) + return ER; + + Sema::ConditionResult R = + getActions().ActOnCondition(getCurScope(), ER.get()->getExprLoc(), + ER.get(), Sema::ConditionKind::Boolean); + + return R.isInvalid() ? ExprError() : R.get().second; +} + // OpenACC 3.3, section 1.7: // To simplify the specification and convey appropriate constraint information, // a pqr-list is a comma-separated list of pdr items. The one exception is a @@ -842,12 +851,15 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( break; } case OpenACCClauseKind::If: { - ExprResult CondExpr = ParseOpenACCConditionalExpr(*this); + ExprResult CondExpr = ParseOpenACCConditionExpr(); + ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get() + : nullptr); if (CondExpr.isInvalid()) { Parens.skipToEnd(); return OpenACCCanContinue(); } + break; } case OpenACCClauseKind::CopyIn: @@ -964,7 +976,7 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( switch (ClauseKind) { case OpenACCClauseKind::Self: { assert(DirKind != OpenACCDirectiveKind::Update); - ExprResult CondExpr = ParseOpenACCConditionalExpr(*this); + ExprResult CondExpr = ParseOpenACCConditionExpr(); if (CondExpr.isInvalid()) { Parens.skipToEnd(); diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index a6f4453e525d..1249136c8765 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -55,12 +55,49 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind, default: return false; } + case OpenACCClauseKind::If: + switch (DirectiveKind) { + case OpenACCDirectiveKind::Parallel: + case OpenACCDirectiveKind::Serial: + case OpenACCDirectiveKind::Kernels: + case OpenACCDirectiveKind::Data: + case OpenACCDirectiveKind::EnterData: + case OpenACCDirectiveKind::ExitData: + case OpenACCDirectiveKind::HostData: + case OpenACCDirectiveKind::Init: + case OpenACCDirectiveKind::Shutdown: + case OpenACCDirectiveKind::Set: + case OpenACCDirectiveKind::Update: + case OpenACCDirectiveKind::Wait: + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::KernelsLoop: + return true; + default: + return false; + } default: // Do nothing so we can go to the 'unimplemented' diagnostic instead. return true; } llvm_unreachable("Invalid clause kind"); } + +bool checkAlreadyHasClauseOfKind( + SemaOpenACC &S, ArrayRef ExistingClauses, + SemaOpenACC::OpenACCParsedClause &Clause) { + const auto *Itr = llvm::find_if(ExistingClauses, [&](const OpenACCClause *C) { + return C->getClauseKind() == Clause.getClauseKind(); + }); + if (Itr != ExistingClauses.end()) { + S.Diag(Clause.getBeginLoc(), diag::err_acc_duplicate_clause_disallowed) + << Clause.getDirectiveKind() << Clause.getClauseKind(); + S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); + return true; + } + return false; +} + } // namespace SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {} @@ -97,22 +134,38 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, // At most one 'default' clause may appear, and it must have a value of // either 'none' or 'present'. // Second half of the sentence is diagnosed during parsing. - auto Itr = llvm::find_if(ExistingClauses, [](const OpenACCClause *C) { - return C->getClauseKind() == OpenACCClauseKind::Default; - }); - - if (Itr != ExistingClauses.end()) { - Diag(Clause.getBeginLoc(), - diag::err_acc_duplicate_clause_disallowed) - << Clause.getDirectiveKind() << Clause.getClauseKind(); - Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); + if (checkAlreadyHasClauseOfKind(*this, ExistingClauses, Clause)) return nullptr; - } return OpenACCDefaultClause::Create( getASTContext(), Clause.getDefaultClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getEndLoc()); } + + case OpenACCClauseKind::If: { + // Restrictions only properly implemented on 'compute' constructs, and + // 'compute' constructs are the only construct that can do anything with + // this yet, so skip/treat as unimplemented in this case. + if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Parallel && + Clause.getDirectiveKind() != OpenACCDirectiveKind::Serial && + Clause.getDirectiveKind() != OpenACCDirectiveKind::Kernels) + break; + + // There is no prose in the standard that says duplicates aren't allowed, + // but this diagnostic is present in other compilers, as well as makes + // sense. + if (checkAlreadyHasClauseOfKind(*this, ExistingClauses, Clause)) + return nullptr; + + // The parser has ensured that we have a proper condition expr, so there + // isn't really much to do here. + + // TODO OpenACC: When we implement 'self', this clauses causes us to + // 'ignore' the self clause, so we should implement a warning here. + return OpenACCIfClause::Create( + getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(), + Clause.getConditionExpr(), Clause.getEndLoc()); + } default: break; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 284c9173e68e..ee6bd228b459 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11103,6 +11103,20 @@ OpenACCClause *TreeTransform::TransformOpenACCClause( ParsedClause.setDefaultDetails( cast(OldClause)->getDefaultClauseKind()); break; + case OpenACCClauseKind::If: { + Expr *Cond = const_cast( + cast(OldClause)->getConditionExpr()); + assert(Cond && "If constructed with invalid Condition"); + Sema::ConditionResult Res = + TransformCondition(Cond->getExprLoc(), /*Var=*/nullptr, Cond, + Sema::ConditionKind::Boolean); + + if (Res.isInvalid() || !Res.get().second) + return nullptr; + + ParsedClause.setConditionDetails(Res.get().second); + break; + } default: assert(false && "Unhandled OpenACC clause in TreeTransform"); return nullptr; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index ce96ce2bdbcc..a47c7a393d63 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11787,6 +11787,12 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { return OpenACCDefaultClause::Create(getContext(), DCK, BeginLoc, LParenLoc, EndLoc); } + case OpenACCClauseKind::If: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *CondExpr = readSubExpr(); + return OpenACCIfClause::Create(getContext(), BeginLoc, LParenLoc, CondExpr, + EndLoc); + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: @@ -11795,7 +11801,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { case OpenACCClauseKind::Worker: case OpenACCClauseKind::Vector: case OpenACCClauseKind::NoHost: - case OpenACCClauseKind::If: case OpenACCClauseKind::Self: case OpenACCClauseKind::Copy: case OpenACCClauseKind::UseDevice: diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index d9ba10ab6087..d45695784354 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7517,6 +7517,12 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeEnum(DC->getDefaultClauseKind()); return; } + case OpenACCClauseKind::If: { + const auto *IC = cast(C); + writeSourceLocation(IC->getLParenLoc()); + AddStmt(const_cast(IC->getConditionExpr())); + return; + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: @@ -7525,7 +7531,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::Worker: case OpenACCClauseKind::Vector: case OpenACCClauseKind::NoHost: - case OpenACCClauseKind::If: case OpenACCClauseKind::Self: case OpenACCClauseKind::Copy: case OpenACCClauseKind::UseDevice: diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index b363a0cb1362..2369df58308a 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -283,11 +283,9 @@ void IfClause() { int i, j; - // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}} #pragma acc serial if(i > j) for(;;){} - // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}} // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} #pragma acc serial if(1+5>3), seq for(;;){} diff --git a/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp index bd8010344502..018f0b68c781 100644 --- a/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp +++ b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp @@ -6,8 +6,10 @@ #ifndef PCH_HELPER #define PCH_HELPER -void NormalFunc() { +void NormalFunc(int i, float f) { // CHECK: FunctionDecl{{.*}}NormalFunc + // CHECK-NEXT: ParmVarDecl + // CHECK-NEXT: ParmVarDecl // CHECK-NEXT: CompoundStmt #pragma acc parallel default(none) while(true); @@ -24,6 +26,20 @@ void NormalFunc() { // CHECK-NEXT: WhileStmt // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: NullStmt + +#pragma acc kernels if( i < f) + while(true); + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: DeclRefExpr{{.*}} 'int' lvalue ParmVar{{.*}} 'i' 'int' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'float' lvalue ParmVar{{.*}} 'f' 'float' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt } template @@ -51,24 +67,120 @@ void TemplFunc() { // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: NullStmt +#pragma acc parallel if(T::SomeFloat < typename T::IntTy{}) + while(true); + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} '' '<' + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'typename T::IntTy' 'typename T::IntTy' + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + +#pragma acc serial if(typename T::IntTy{}) + while(true); + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial + // CHECK-NEXT: if clause + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'typename T::IntTy' 'typename T::IntTy' + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + +#pragma acc kernels if(T::SomeFloat) + while(true); + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + +#pragma acc parallel if(T::BC) + while(true); + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + // Match the instantiation: // CHECK: FunctionDecl{{.*}}TemplFunc{{.*}}implicit_instantiation - // CHECK-NEXT: TemplateArgument type 'int' - // CHECK-NEXT: BuiltinType + // CHECK-NEXT: TemplateArgument type 'InstTy' + // CHECK-NEXT: RecordType{{.*}} 'InstTy' + // CHECK-NEXT: CXXRecord{{.*}} 'InstTy' // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels // CHECK-NEXT: default(none) // CHECK-NEXT: WhileStmt // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: NullStmt + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel // CHECK-NEXT: default(present) // CHECK-NEXT: WhileStmt // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: NullStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy + // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy + // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'bool' + // CHECK-NEXT: CXXMemberCallExpr{{.*}} 'bool' + // CHECK-NEXT: MemberExpr{{.*}} .operator bool + // CHECK-NEXT: DeclRefExpr{{.*}} 'const BoolConversion' lvalue Var{{.*}} 'BC' 'const BoolConversion' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt } +struct BoolConversion{ operator bool() const;}; +struct InstTy { + using IntTy = int; + static constexpr float SomeFloat = 5.0; + static constexpr BoolConversion BC; +}; + void Instantiate() { - TemplFunc(); + TemplFunc(); } #endif diff --git a/clang/test/SemaOpenACC/compute-construct-if-clause.c b/clang/test/SemaOpenACC/compute-construct-if-clause.c new file mode 100644 index 000000000000..767b8414b3a6 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-if-clause.c @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +void BoolExpr(int *I, float *F) { + + typedef struct {} SomeStruct; + int Array[5]; + + struct C{}; + // expected-error@+1{{expected expression}} +#pragma acc parallel if (struct C f()) + while(0); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc serial if (SomeStruct) + while(0); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc serial if (SomeStruct()) + while(0); + + SomeStruct S; + // expected-error@+1{{statement requires expression of scalar type ('SomeStruct' invalid)}} +#pragma acc serial if (S) + while(0); + + // expected-warning@+1{{address of array 'Array' will always evaluate to 'true'}} +#pragma acc kernels if (Array) + while(0); + + // expected-warning@+4{{incompatible pointer types assigning to 'int *' from 'float *'}} + // expected-warning@+3{{using the result of an assignment as a condition without parentheses}} + // expected-note@+2{{place parentheses around the assignment to silence this warning}} + // expected-note@+1{{use '==' to turn this assignment into an equality comparison}} +#pragma acc kernels if (I = F) + while(0); + +#pragma acc parallel if (I) + while(0); + +#pragma acc serial if (F) + while(0); + +#pragma acc kernels if (*I < *F) + while(0); + + // expected-warning@+2{{OpenACC construct 'data' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} +#pragma acc data if (*I < *F) + while(0); + // expected-warning@+2{{OpenACC construct 'parallel loop' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} +#pragma acc parallel loop if (*I < *F) + while(0); + // expected-warning@+2{{OpenACC construct 'serial loop' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} +#pragma acc serial loop if (*I < *F) + while(0); + // expected-warning@+2{{OpenACC construct 'kernels loop' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} +#pragma acc kernels loop if (*I < *F) + while(0); +} diff --git a/clang/test/SemaOpenACC/compute-construct-if-clause.cpp b/clang/test/SemaOpenACC/compute-construct-if-clause.cpp new file mode 100644 index 000000000000..2a9bb8a3d5c4 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-if-clause.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NoBoolConversion{}; +struct BoolConversion{ + operator bool(); +}; + +template +void BoolExpr() { + + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc parallel if (NoBoolConversion{}) + while(0); + + // expected-error@+2{{no member named 'NotValid' in 'NoBoolConversion'}} + // expected-note@#INST{{in instantiation of function template specialization}} +#pragma acc parallel if (T::NotValid) + while(0); + +#pragma acc parallel if (BoolConversion{}) + while(0); + + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc parallel if (T{}) + while(0); + +#pragma acc parallel if (U{}) + while(0); +} + +void Instantiate() { + BoolExpr(); // #INST +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 00ddc4f24500..936e8872513a 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -28,6 +28,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" +#include "clang/AST/OpenACCClause.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/StmtVisitor.h" @@ -2115,6 +2116,7 @@ public: }; class EnqueueVisitor : public ConstStmtVisitor, public ConstAttrVisitor { + friend class OpenACCClauseEnqueue; friend class OMPClauseEnqueue; VisitorWorkList &WL; CXCursor Parent; @@ -2171,6 +2173,7 @@ public: void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E); void VisitRequiresExpr(const RequiresExpr *E); void VisitCXXParenListInitExpr(const CXXParenListInitExpr *E); + void VisitOpenACCComputeConstruct(const OpenACCComputeConstruct *D); void VisitOMPExecutableDirective(const OMPExecutableDirective *D); void VisitOMPLoopBasedDirective(const OMPLoopBasedDirective *D); void VisitOMPLoopDirective(const OMPLoopDirective *D); @@ -2269,6 +2272,7 @@ private: void AddDecl(const Decl *D, bool isFirst = true); void AddTypeLoc(TypeSourceInfo *TI); void EnqueueChildren(const Stmt *S); + void EnqueueChildren(const OpenACCClause *S); void EnqueueChildren(const OMPClause *S); void EnqueueChildren(const AnnotateAttr *A); }; @@ -2771,6 +2775,38 @@ void EnqueueVisitor::EnqueueChildren(const OMPClause *S) { std::reverse(I, E); } +namespace { +class OpenACCClauseEnqueue : public OpenACCClauseVisitor { + EnqueueVisitor &Visitor; + +public: + OpenACCClauseEnqueue(EnqueueVisitor &V) : Visitor(V) {} + +#define VISIT_CLAUSE(CLAUSE_NAME) \ + void VisitOpenACC##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &C); +#include "clang/Basic/OpenACCClauses.def" +}; + +void OpenACCClauseEnqueue::VisitOpenACCDefaultClause( + const OpenACCDefaultClause &C) {} +void OpenACCClauseEnqueue::VisitOpenACCIfClause(const OpenACCIfClause &C) { + Visitor.AddStmt(C.getConditionExpr()); +} +} // namespace + +void EnqueueVisitor::EnqueueChildren(const OpenACCClause *C) { + unsigned size = WL.size(); + OpenACCClauseEnqueue Visitor(*this); + Visitor.Visit(C); + + if (size == WL.size()) + return; + // Now reverse the entries we just added. This will match the DFS + // ordering performed by the worklist. + VisitorWorkList::iterator I = WL.begin() + size, E = WL.end(); + std::reverse(I, E); +} + void EnqueueVisitor::EnqueueChildren(const AnnotateAttr *A) { unsigned size = WL.size(); for (const Expr *Arg : A->args()) { @@ -3386,6 +3422,13 @@ void EnqueueVisitor::VisitOMPTargetTeamsDistributeSimdDirective( VisitOMPLoopDirective(D); } +void EnqueueVisitor::VisitOpenACCComputeConstruct( + const OpenACCComputeConstruct *C) { + EnqueueChildren(C); + for (auto *Clause : C->clauses()) + EnqueueChildren(Clause); +} + void EnqueueVisitor::VisitAnnotateAttr(const AnnotateAttr *A) { EnqueueChildren(A); } -- GitLab From 7b6b023121fe7d612dc571de0ff3dcaaf8477765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Fri, 12 Apr 2024 14:28:05 -0700 Subject: [PATCH 116/464] [flang][cuda] Fix crash in semantic (#88577) Fix for #88451 Do not perform semantic check about data transfer on assignment statement in device context. --- flang/lib/Semantics/check-cuda.cpp | 8 +++++++- flang/test/Semantics/cuf11.cuf | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp index e0a796972441..2cb15437a235 100644 --- a/flang/lib/Semantics/check-cuda.cpp +++ b/flang/lib/Semantics/check-cuda.cpp @@ -480,10 +480,16 @@ void CUDAChecker::Enter(const parser::CUFKernelDoConstruct &x) { } void CUDAChecker::Enter(const parser::AssignmentStmt &x) { + auto lhsLoc{std::get(x.t).GetSource()}; + const auto &scope{context_.FindScope(lhsLoc)}; + const Scope &progUnit{GetProgramUnitContaining(scope)}; + if (IsCUDADeviceContext(&progUnit)) { + return; // Data transfer with assignment is only perform on host. + } + const evaluate::Assignment *assign{semantics::GetAssignment(x)}; int nbLhs{evaluate::GetNbOfCUDASymbols(assign->lhs)}; int nbRhs{evaluate::GetNbOfCUDASymbols(assign->rhs)}; - auto lhsLoc{std::get(x.t).GetSource()}; // device to host transfer with more than one device object on the rhs is not // legal. diff --git a/flang/test/Semantics/cuf11.cuf b/flang/test/Semantics/cuf11.cuf index 96108e2b2455..b915c7246ed9 100644 --- a/flang/test/Semantics/cuf11.cuf +++ b/flang/test/Semantics/cuf11.cuf @@ -1,5 +1,17 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 +module mod1 +contains + attributes(global) subroutine sub1(adev) + real :: adev(10) + integer :: tid + tid = threadIdx%x +! Use to crash the compiler. Make sure we have the proper semantic error. +!ERROR: Actual argument for 'i=' has bad type 'REAL(4)' + adev(tid + 1) = scale(real(tid), 2.0) + end subroutine sub1 +end module + subroutine sub1() real, device :: adev(10), bdev(10) real :: ahost(10) -- GitLab From 900be9013fdc3bab9fce906f8a71e59ecd8873b4 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Fri, 12 Apr 2024 23:33:35 +0200 Subject: [PATCH 117/464] Fix typos (#88565) --- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 2 +- libc/src/__support/str_to_float.h | 8 ++++---- llvm/lib/Analysis/LoopCacheAnalysis.cpp | 2 +- llvm/lib/Support/APInt.cpp | 2 +- llvm/lib/Transforms/Scalar/LoopInterchange.cpp | 2 +- llvm/test/Transforms/JumpThreading/free_instructions.ll | 2 +- llvm/utils/lint/common_lint.py | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 504fd7f05e0f..c50db1e0e2f8 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -229,7 +229,7 @@ SVal ExprEngine::computeObjectUnderConstruction( // We are on the top frame of the analysis. We do not know where is the // object returned to. Conjure a symbolic region for the return value. // TODO: We probably need a new MemRegion kind to represent the storage - // of that SymbolicRegion, so that we cound produce a fancy symbol + // of that SymbolicRegion, so that we could produce a fancy symbol // instead of an anonymous conjured symbol. // TODO: Do we need to track the region to avoid having it dead // too early? It does die too early, at least in C++17, but because diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h index cd0c07629f87..fa466ca8492f 100644 --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -695,10 +695,10 @@ LIBC_INLINE FloatConvertReturn decimal_exp_to_float( // If the mantissa is truncated, then the result may be off by the LSB, so // check if rounding the mantissa up changes the result. If not, then it's // safe, else use the fallback. - auto secound_output = eisel_lemire({mantissa + 1, exp10}, round); - if (secound_output.has_value()) { - if (opt_output->mantissa == secound_output->mantissa && - opt_output->exponent == secound_output->exponent) { + auto second_output = eisel_lemire({mantissa + 1, exp10}, round); + if (second_output.has_value()) { + if (opt_output->mantissa == second_output->mantissa && + opt_output->exponent == second_output->exponent) { return {opt_output.value(), 0}; } } diff --git a/llvm/lib/Analysis/LoopCacheAnalysis.cpp b/llvm/lib/Analysis/LoopCacheAnalysis.cpp index c3a56639b5c8..284d8d16d264 100644 --- a/llvm/lib/Analysis/LoopCacheAnalysis.cpp +++ b/llvm/lib/Analysis/LoopCacheAnalysis.cpp @@ -315,7 +315,7 @@ CacheCostTy IndexedReference::computeRefCost(const Loop &L, RefCost = TripCount; int Index = getSubscriptIndex(L); - assert(Index >= 0 && "Cound not locate a valid Index"); + assert(Index >= 0 && "Could not locate a valid Index"); for (unsigned I = Index + 1; I < getNumSubscripts() - 1; ++I) { const SCEVAddRecExpr *AR = dyn_cast(getSubscript(I)); diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 18feca4c0553..24e136fcb9c7 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2663,7 +2663,7 @@ int APInt::tcDivide(WordType *lhs, const WordType *rhs, return false; } -/// Shift a bignum left Cound bits in-place. Shifted in bits are zero. There are +/// Shift a bignum left Count bits in-place. Shifted in bits are zero. There are /// no restrictions on Count. void APInt::tcShiftLeft(WordType *Dst, unsigned Words, unsigned Count) { // Don't bother performing a no-op shift. diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index 277f530ee25f..400973fd9fc9 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -976,7 +976,7 @@ bool LoopInterchangeLegality::canInterchangeLoops(unsigned InnerLoopId, } if (!findInductions(InnerLoop, InnerLoopInductions)) { - LLVM_DEBUG(dbgs() << "Cound not find inner loop induction variables.\n"); + LLVM_DEBUG(dbgs() << "Could not find inner loop induction variables.\n"); return false; } diff --git a/llvm/test/Transforms/JumpThreading/free_instructions.ll b/llvm/test/Transforms/JumpThreading/free_instructions.ll index 3485bf8c98da..48bedc72c2d3 100644 --- a/llvm/test/Transforms/JumpThreading/free_instructions.ll +++ b/llvm/test/Transforms/JumpThreading/free_instructions.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes=jump-threading -jump-threading-threshold=3 < %s | FileCheck %s -; TODO: In this test case, only the stores in %join should cound towards +; TODO: In this test case, only the stores in %join should count towards ; the jump threading threshold, as everything else are free instructions. define i32 @free_instructions(i1 %c, ptr %p) { ; CHECK-LABEL: @free_instructions( diff --git a/llvm/utils/lint/common_lint.py b/llvm/utils/lint/common_lint.py index 1bf1695659d8..07b8fc5899e5 100644 --- a/llvm/utils/lint/common_lint.py +++ b/llvm/utils/lint/common_lint.py @@ -97,7 +97,7 @@ def RunLintOverAllFiles(linter, filenames): for filename in filenames: file = open(filename, "r") if not file: - print("Cound not open %s" % filename) + print("Could not open %s" % filename) continue lines = file.readlines() lint.extend(linter.RunOnFile(filename, lines)) -- GitLab From 2996cb7970fb536d7db1088d571dc8d2f9ad35fa Mon Sep 17 00:00:00 2001 From: Michael Flanders Date: Fri, 12 Apr 2024 14:35:10 -0700 Subject: [PATCH 118/464] [libc][docs] use docgen to generate stdbit rst docs (#88540) Closes #88066. Compared to before, the function names in the stdbit table are sorted by function name, not order-of-appearance in the standard. Since macros aren't printed by docgen.py and are still a TODO in the code, they are also not printed in the new stdbit.h docs. Adds some checks to docgen.py for conditions that tripped me up. Add code to docgen.py to add the include of the `|check|` rewriter, since all other generated files need it. --- libc/docs/stdbit.rst | 350 +++++++++++++++++++++------------- libc/utils/docgen/docgen.py | 8 + libc/utils/docgen/stdbit.json | 234 +++++++++++++++++++++++ 3 files changed, 461 insertions(+), 131 deletions(-) create mode 100644 libc/utils/docgen/stdbit.json diff --git a/libc/docs/stdbit.rst b/libc/docs/stdbit.rst index d42f79382462..0a12b2b6d7b5 100644 --- a/libc/docs/stdbit.rst +++ b/libc/docs/stdbit.rst @@ -1,135 +1,223 @@ -========================= -Bitwise Utility Functions -========================= - .. include:: check.rst ---------------- -Source Location ---------------- - -- The main source for bitwise utility functions is located at: - ``libc/src/stdbit``. - -- The source for internal helpers used to implement these is located at: - ``libc/src/__support/CPP/bit.h``. - -- The tests are located at: - ``libc/test/src/stdbit/``, ``libc/test/include/stdbit_test.cpp``, and - ``src/__support/CPP/bit_test.cpp``. - ---------------------- -Implementation Status ---------------------- - -Functions -========= - -.. - Do not order these, they are as they appear in the standard. - -============================ ========= -Function Name Available -============================ ========= -stdc_leading_zeros_uc |check| -stdc_leading_zeros_us |check| -stdc_leading_zeros_ui |check| -stdc_leading_zeros_ul |check| -stdc_leading_zeros_ull |check| -stdc_leading_ones_uc |check| -stdc_leading_ones_us |check| -stdc_leading_ones_ui |check| -stdc_leading_ones_ul |check| -stdc_leading_ones_ull |check| -stdc_trailing_zeros_uc |check| -stdc_trailing_zeros_us |check| -stdc_trailing_zeros_ui |check| -stdc_trailing_zeros_ul |check| -stdc_trailing_zeros_ull |check| -stdc_trailing_ones_uc |check| -stdc_trailing_ones_us |check| -stdc_trailing_ones_ui |check| -stdc_trailing_ones_ul |check| -stdc_trailing_ones_ull |check| -stdc_first_leading_zero_uc |check| -stdc_first_leading_zero_us |check| -stdc_first_leading_zero_ui |check| -stdc_first_leading_zero_ul |check| -stdc_first_leading_zero_ull |check| -stdc_first_leading_one_uc |check| -stdc_first_leading_one_us |check| -stdc_first_leading_one_ui |check| -stdc_first_leading_one_ul |check| -stdc_first_leading_one_ull |check| -stdc_first_trailing_zero_uc |check| -stdc_first_trailing_zero_us |check| -stdc_first_trailing_zero_ui |check| -stdc_first_trailing_zero_ul |check| -stdc_first_trailing_zero_ull |check| -stdc_first_trailing_one_uc |check| -stdc_first_trailing_one_us |check| -stdc_first_trailing_one_ui |check| -stdc_first_trailing_one_ul |check| -stdc_first_trailing_one_ull |check| -stdc_count_zeros_uc |check| -stdc_count_zeros_us |check| -stdc_count_zeros_ui |check| -stdc_count_zeros_ul |check| -stdc_count_zeros_ull |check| -stdc_count_ones_uc |check| -stdc_count_ones_us |check| -stdc_count_ones_ui |check| -stdc_count_ones_ul |check| -stdc_count_ones_ull |check| -stdc_has_single_bit_uc |check| -stdc_has_single_bit_us |check| -stdc_has_single_bit_ui |check| -stdc_has_single_bit_ul |check| -stdc_has_single_bit_ull |check| -stdc_bit_width_uc |check| -stdc_bit_width_us |check| -stdc_bit_width_ui |check| -stdc_bit_width_ul |check| -stdc_bit_width_ull |check| -stdc_bit_floor_uc |check| -stdc_bit_floor_us |check| -stdc_bit_floor_ui |check| -stdc_bit_floor_ul |check| -stdc_bit_floor_ull |check| -stdc_bit_ceil_uc |check| -stdc_bit_ceil_us |check| -stdc_bit_ceil_ui |check| -stdc_bit_ceil_ul |check| -stdc_bit_ceil_ull |check| -============================ ========= - - -Macros -====== +stdbit.h Functions +================== -========================= ========= -Macro Name Available -========================= ========= -__STDC_VERSION_STDBIT_H__ |check| -__STDC_ENDIAN_LITTLE__ |check| -__STDC_ENDIAN_BIG__ |check| -__STDC_ENDIAN_NATIVE__ |check| -stdc_leading_zeros |check| -stdc_leading_ones |check| -stdc_trailing_zeros |check| -stdc_trailing_ones |check| -stdc_first_leading_zero |check| -stdc_first_leading_one |check| -stdc_first_trailing_zero |check| -stdc_first_trailing_one |check| -stdc_count_zeros |check| -stdc_count_ones |check| -stdc_has_single_bit |check| -stdc_bit_width |check| -stdc_bit_floor |check| -stdc_bit_ceil |check| -========================= ========= +.. list-table:: + :widths: auto + :align: center + :header-rows: 1 -Standards -========= -stdbit.h was specified as part of C23 in section 7.18 "Bit and byte utilities." + * - Function + - Implemented + - Standard + * - stdc_bit_ceil_uc + - |check| + - 7.18.16 + * - stdc_bit_ceil_ui + - |check| + - 7.18.16 + * - stdc_bit_ceil_ul + - |check| + - 7.18.16 + * - stdc_bit_ceil_ull + - |check| + - 7.18.16 + * - stdc_bit_ceil_us + - |check| + - 7.18.16 + * - stdc_bit_floor_uc + - |check| + - 7.18.15 + * - stdc_bit_floor_ui + - |check| + - 7.18.15 + * - stdc_bit_floor_ul + - |check| + - 7.18.15 + * - stdc_bit_floor_ull + - |check| + - 7.18.15 + * - stdc_bit_floor_us + - |check| + - 7.18.15 + * - stdc_bit_width_uc + - |check| + - 7.18.14 + * - stdc_bit_width_ui + - |check| + - 7.18.14 + * - stdc_bit_width_ul + - |check| + - 7.18.14 + * - stdc_bit_width_ull + - |check| + - 7.18.14 + * - stdc_bit_width_us + - |check| + - 7.18.14 + * - stdc_count_ones_uc + - |check| + - 7.18.12 + * - stdc_count_ones_ui + - |check| + - 7.18.12 + * - stdc_count_ones_ul + - |check| + - 7.18.12 + * - stdc_count_ones_ull + - |check| + - 7.18.12 + * - stdc_count_ones_us + - |check| + - 7.18.12 + * - stdc_count_zeros_uc + - |check| + - 7.18.11 + * - stdc_count_zeros_ui + - |check| + - 7.18.11 + * - stdc_count_zeros_ul + - |check| + - 7.18.11 + * - stdc_count_zeros_ull + - |check| + - 7.18.11 + * - stdc_count_zeros_us + - |check| + - 7.18.11 + * - stdc_first_leading_one_uc + - |check| + - 7.18.8 + * - stdc_first_leading_one_ui + - |check| + - 7.18.8 + * - stdc_first_leading_one_ul + - |check| + - 7.18.8 + * - stdc_first_leading_one_ull + - |check| + - 7.18.8 + * - stdc_first_leading_one_us + - |check| + - 7.18.8 + * - stdc_first_leading_zero_uc + - |check| + - 7.18.7 + * - stdc_first_leading_zero_ui + - |check| + - 7.18.7 + * - stdc_first_leading_zero_ul + - |check| + - 7.18.7 + * - stdc_first_leading_zero_ull + - |check| + - 7.18.7 + * - stdc_first_leading_zero_us + - |check| + - 7.18.7 + * - stdc_first_trailing_one_uc + - |check| + - 7.18.10 + * - stdc_first_trailing_one_ui + - |check| + - 7.18.10 + * - stdc_first_trailing_one_ul + - |check| + - 7.18.10 + * - stdc_first_trailing_one_ull + - |check| + - 7.18.10 + * - stdc_first_trailing_one_us + - |check| + - 7.18.10 + * - stdc_first_trailing_zero_uc + - |check| + - 7.18.9 + * - stdc_first_trailing_zero_ui + - |check| + - 7.18.9 + * - stdc_first_trailing_zero_ul + - |check| + - 7.18.9 + * - stdc_first_trailing_zero_ull + - |check| + - 7.18.9 + * - stdc_first_trailing_zero_us + - |check| + - 7.18.9 + * - stdc_has_single_bit_uc + - |check| + - 7.18.13 + * - stdc_has_single_bit_ui + - |check| + - 7.18.13 + * - stdc_has_single_bit_ul + - |check| + - 7.18.13 + * - stdc_has_single_bit_ull + - |check| + - 7.18.13 + * - stdc_has_single_bit_us + - |check| + - 7.18.13 + * - stdc_leading_ones_uc + - |check| + - 7.18.4 + * - stdc_leading_ones_ui + - |check| + - 7.18.4 + * - stdc_leading_ones_ul + - |check| + - 7.18.4 + * - stdc_leading_ones_ull + - |check| + - 7.18.4 + * - stdc_leading_ones_us + - |check| + - 7.18.4 + * - stdc_leading_zeros_uc + - |check| + - 7.18.3 + * - stdc_leading_zeros_ui + - |check| + - 7.18.3 + * - stdc_leading_zeros_ul + - |check| + - 7.18.3 + * - stdc_leading_zeros_ull + - |check| + - 7.18.3 + * - stdc_leading_zeros_us + - |check| + - 7.18.3 + * - stdc_trailing_ones_uc + - |check| + - 7.18.6 + * - stdc_trailing_ones_ui + - |check| + - 7.18.6 + * - stdc_trailing_ones_ul + - |check| + - 7.18.6 + * - stdc_trailing_ones_ull + - |check| + - 7.18.6 + * - stdc_trailing_ones_us + - |check| + - 7.18.6 + * - stdc_trailing_zeros_uc + - |check| + - 7.18.5 + * - stdc_trailing_zeros_ui + - |check| + - 7.18.5 + * - stdc_trailing_zeros_ul + - |check| + - 7.18.5 + * - stdc_trailing_zeros_ull + - |check| + - 7.18.5 + * - stdc_trailing_zeros_us + - |check| + - 7.18.5 diff --git a/libc/utils/docgen/docgen.py b/libc/utils/docgen/docgen.py index 36eb409421b4..23d45305fe51 100755 --- a/libc/utils/docgen/docgen.py +++ b/libc/utils/docgen/docgen.py @@ -28,6 +28,13 @@ def is_implemented(hname: str, fname: str) -> bool: "src", hname.rstrip(".h") ) + + if not path.exists(): + raise FileNotFoundError(f"implementation dir does not exist: {path}") + + if not path.is_dir(): + raise NotADirectoryError(f"implementation dir is not a dir: {path}") + # Recursively search for the target source file in the subdirectories under # libc/src/{hname}. for _ in path.glob("**/" + fname + ".cpp"): @@ -53,6 +60,7 @@ def print_functions(header: str, functions: Dict): def print_header(header: str, api: Dict): + print(".. include:: check.rst\n") fns = f"{header} Functions" print(fns) print("=" * (len(fns))) diff --git a/libc/utils/docgen/stdbit.json b/libc/utils/docgen/stdbit.json new file mode 100644 index 000000000000..9dda0cb0f538 --- /dev/null +++ b/libc/utils/docgen/stdbit.json @@ -0,0 +1,234 @@ +{ + "macros": [ + "__STDC_VERSION_STDBIT_H__", + "__STDC_ENDIAN_LITTLE__", + "__STDC_ENDIAN_BIG__", + "__STDC_ENDIAN_NATIVE__", + "stdc_leading_zeros", + "stdc_leading_ones", + "stdc_trailing_zeros", + "stdc_trailing_ones", + "stdc_first_leading_zero", + "stdc_first_leading_one", + "stdc_first_trailing_zero", + "stdc_first_trailing_one", + "stdc_count_zeros", + "stdc_count_ones", + "stdc_has_single_bit", + "stdc_bit_width", + "stdc_bit_floor", + "stdc_bit_ceil" + ], + "functions": { + "stdc_leading_zeros_uc": { + "defined": "7.18.3" + }, + "stdc_leading_zeros_us": { + "defined": "7.18.3" + }, + "stdc_leading_zeros_ui": { + "defined": "7.18.3" + }, + "stdc_leading_zeros_ul": { + "defined": "7.18.3" + }, + "stdc_leading_zeros_ull": { + "defined": "7.18.3" + }, + "stdc_leading_ones_uc": { + "defined": "7.18.4" + }, + "stdc_leading_ones_us": { + "defined": "7.18.4" + }, + "stdc_leading_ones_ui": { + "defined": "7.18.4" + }, + "stdc_leading_ones_ul": { + "defined": "7.18.4" + }, + "stdc_leading_ones_ull": { + "defined": "7.18.4" + }, + "stdc_trailing_zeros_uc": { + "defined": "7.18.5" + }, + "stdc_trailing_zeros_us": { + "defined": "7.18.5" + }, + "stdc_trailing_zeros_ui": { + "defined": "7.18.5" + }, + "stdc_trailing_zeros_ul": { + "defined": "7.18.5" + }, + "stdc_trailing_zeros_ull": { + "defined": "7.18.5" + }, + "stdc_trailing_ones_uc": { + "defined": "7.18.6" + }, + "stdc_trailing_ones_us": { + "defined": "7.18.6" + }, + "stdc_trailing_ones_ui": { + "defined": "7.18.6" + }, + "stdc_trailing_ones_ul": { + "defined": "7.18.6" + }, + "stdc_trailing_ones_ull": { + "defined": "7.18.6" + }, + "stdc_first_leading_zero_uc": { + "defined": "7.18.7" + }, + "stdc_first_leading_zero_us": { + "defined": "7.18.7" + }, + "stdc_first_leading_zero_ui": { + "defined": "7.18.7" + }, + "stdc_first_leading_zero_ul": { + "defined": "7.18.7" + }, + "stdc_first_leading_zero_ull": { + "defined": "7.18.7" + }, + "stdc_first_leading_one_uc": { + "defined": "7.18.8" + }, + "stdc_first_leading_one_us": { + "defined": "7.18.8" + }, + "stdc_first_leading_one_ui": { + "defined": "7.18.8" + }, + "stdc_first_leading_one_ul": { + "defined": "7.18.8" + }, + "stdc_first_leading_one_ull": { + "defined": "7.18.8" + }, + "stdc_first_trailing_zero_uc": { + "defined": "7.18.9" + }, + "stdc_first_trailing_zero_us": { + "defined": "7.18.9" + }, + "stdc_first_trailing_zero_ui": { + "defined": "7.18.9" + }, + "stdc_first_trailing_zero_ul": { + "defined": "7.18.9" + }, + "stdc_first_trailing_zero_ull": { + "defined": "7.18.9" + }, + "stdc_first_trailing_one_uc": { + "defined": "7.18.10" + }, + "stdc_first_trailing_one_us": { + "defined": "7.18.10" + }, + "stdc_first_trailing_one_ui": { + "defined": "7.18.10" + }, + "stdc_first_trailing_one_ul": { + "defined": "7.18.10" + }, + "stdc_first_trailing_one_ull": { + "defined": "7.18.10" + }, + "stdc_count_zeros_uc": { + "defined": "7.18.11" + }, + "stdc_count_zeros_us": { + "defined": "7.18.11" + }, + "stdc_count_zeros_ui": { + "defined": "7.18.11" + }, + "stdc_count_zeros_ul": { + "defined": "7.18.11" + }, + "stdc_count_zeros_ull": { + "defined": "7.18.11" + }, + "stdc_count_ones_uc": { + "defined": "7.18.12" + }, + "stdc_count_ones_us": { + "defined": "7.18.12" + }, + "stdc_count_ones_ui": { + "defined": "7.18.12" + }, + "stdc_count_ones_ul": { + "defined": "7.18.12" + }, + "stdc_count_ones_ull": { + "defined": "7.18.12" + }, + "stdc_has_single_bit_uc": { + "defined": "7.18.13" + }, + "stdc_has_single_bit_us": { + "defined": "7.18.13" + }, + "stdc_has_single_bit_ui": { + "defined": "7.18.13" + }, + "stdc_has_single_bit_ul": { + "defined": "7.18.13" + }, + "stdc_has_single_bit_ull": { + "defined": "7.18.13" + }, + "stdc_bit_width_uc": { + "defined": "7.18.14" + }, + "stdc_bit_width_us": { + "defined": "7.18.14" + }, + "stdc_bit_width_ui": { + "defined": "7.18.14" + }, + "stdc_bit_width_ul": { + "defined": "7.18.14" + }, + "stdc_bit_width_ull": { + "defined": "7.18.14" + }, + "stdc_bit_floor_uc": { + "defined": "7.18.15" + }, + "stdc_bit_floor_us": { + "defined": "7.18.15" + }, + "stdc_bit_floor_ui": { + "defined": "7.18.15" + }, + "stdc_bit_floor_ul": { + "defined": "7.18.15" + }, + "stdc_bit_floor_ull": { + "defined": "7.18.15" + }, + "stdc_bit_ceil_uc": { + "defined": "7.18.16" + }, + "stdc_bit_ceil_us": { + "defined": "7.18.16" + }, + "stdc_bit_ceil_ui": { + "defined": "7.18.16" + }, + "stdc_bit_ceil_ul": { + "defined": "7.18.16" + }, + "stdc_bit_ceil_ull": { + "defined": "7.18.16" + } + } +} -- GitLab From eaa3947106e50d6d837e6681fb55cf92c2bb0f9a Mon Sep 17 00:00:00 2001 From: erichkeane Date: Fri, 12 Apr 2024 14:32:37 -0700 Subject: [PATCH 119/464] [NFC] Remove unused type alias in OpenACC Leftover from a previous commit, this ends up not being used, so remove it. --- clang/include/clang/Parse/Parser.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index db90d38c7dac..c719218731c3 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3611,9 +3611,6 @@ private: OpenACCClauseParseResult OpenACCCannotContinue(); OpenACCClauseParseResult OpenACCSuccess(OpenACCClause *Clause); - using OpenACCConditionExprParseResult = - std::pair; - /// Parses the OpenACC directive (the entire pragma) including the clause /// list, but does not produce the main AST node. OpenACCDirectiveParseInfo ParseOpenACCDirective(); -- GitLab From a472e6473e6921f22427d41c3d29e9a26eb4ab32 Mon Sep 17 00:00:00 2001 From: erichkeane Date: Fri, 12 Apr 2024 14:41:20 -0700 Subject: [PATCH 120/464] [NFC][OpenACC] Rename visitor functions to omit redundant OpenACC While working on a followup patch, it became clear that this extra bit of 'OpenACC' before each clause name was redundant with the visitors, so remove it to make this a little less verbose. --- clang/include/clang/AST/OpenACCClause.h | 11 +++++------ clang/lib/AST/OpenACCClause.cpp | 4 ++-- clang/lib/AST/StmtProfile.cpp | 6 +++--- clang/tools/libclang/CIndex.cpp | 5 ++--- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 712ad46c0f23..401b8e904a1b 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -160,10 +160,10 @@ public: switch (C->getClauseKind()) { case OpenACCClauseKind::Default: - VisitOpenACCDefaultClause(*cast(C)); + VisitDefaultClause(*cast(C)); return; case OpenACCClauseKind::If: - VisitOpenACCIfClause(*cast(C)); + VisitIfClause(*cast(C)); return; case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: @@ -212,9 +212,9 @@ public: } #define VISIT_CLAUSE(CLAUSE_NAME) \ - void VisitOpenACC##CLAUSE_NAME##Clause( \ + void Visit##CLAUSE_NAME##Clause( \ const OpenACC##CLAUSE_NAME##Clause &Clause) { \ - return getDerived().VisitOpenACC##CLAUSE_NAME##Clause(Clause); \ + return getDerived().Visit##CLAUSE_NAME##Clause(Clause); \ } #include "clang/Basic/OpenACCClauses.def" @@ -236,8 +236,7 @@ public: OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {} #define VISIT_CLAUSE(CLAUSE_NAME) \ - void VisitOpenACC##CLAUSE_NAME##Clause( \ - const OpenACC##CLAUSE_NAME##Clause &Clause); + void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause); #include "clang/Basic/OpenACCClauses.def" }; diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index 2bc8d14fa129..446e47003204 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -65,11 +65,11 @@ OpenACCClause::child_range OpenACCClause::children() { //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// -void OpenACCClausePrinter::VisitOpenACCDefaultClause( +void OpenACCClausePrinter::VisitDefaultClause( const OpenACCDefaultClause &C) { OS << "default(" << C.getDefaultClauseKind() << ")"; } -void OpenACCClausePrinter::VisitOpenACCIfClause(const OpenACCIfClause &C) { +void OpenACCClausePrinter::VisitIfClause(const OpenACCIfClause &C) { OS << "if(" << C.getConditionExpr() << ")"; } diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 44b635bfb843..68ba7475f4ca 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2459,17 +2459,17 @@ public: } #define VISIT_CLAUSE(CLAUSE_NAME) \ - void VisitOpenACC##CLAUSE_NAME##Clause( \ + void Visit##CLAUSE_NAME##Clause( \ const OpenACC##CLAUSE_NAME##Clause &Clause); #include "clang/Basic/OpenACCClauses.def" }; /// Nothing to do here, there are no sub-statements. -void OpenACCClauseProfiler::VisitOpenACCDefaultClause( +void OpenACCClauseProfiler::VisitDefaultClause( const OpenACCDefaultClause &Clause) {} -void OpenACCClauseProfiler::VisitOpenACCIfClause( +void OpenACCClauseProfiler::VisitIfClause( const OpenACCIfClause &Clause) { assert(Clause.hasConditionExpr() && "if clause requires a valid condition expr"); diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 936e8872513a..b999750c0f5e 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2787,9 +2787,8 @@ public: #include "clang/Basic/OpenACCClauses.def" }; -void OpenACCClauseEnqueue::VisitOpenACCDefaultClause( - const OpenACCDefaultClause &C) {} -void OpenACCClauseEnqueue::VisitOpenACCIfClause(const OpenACCIfClause &C) { +void OpenACCClauseEnqueue::VisitDefaultClause(const OpenACCDefaultClause &C) {} +void OpenACCClauseEnqueue::VisitIfClause(const OpenACCIfClause &C) { Visitor.AddStmt(C.getConditionExpr()); } } // namespace -- GitLab From db8e182952573fa9198424a6ed1b1bb1676eae62 Mon Sep 17 00:00:00 2001 From: erichkeane Date: Fri, 12 Apr 2024 14:44:20 -0700 Subject: [PATCH 121/464] [NFC] Clang-format previous OpenACC Patch --- clang/lib/AST/OpenACCClause.cpp | 3 +-- clang/lib/AST/StmtProfile.cpp | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index 446e47003204..dcb512cb5141 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -65,8 +65,7 @@ OpenACCClause::child_range OpenACCClause::children() { //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// -void OpenACCClausePrinter::VisitDefaultClause( - const OpenACCDefaultClause &C) { +void OpenACCClausePrinter::VisitDefaultClause(const OpenACCDefaultClause &C) { OS << "default(" << C.getDefaultClauseKind() << ")"; } diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 68ba7475f4ca..d2aac1e64038 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2459,8 +2459,7 @@ public: } #define VISIT_CLAUSE(CLAUSE_NAME) \ - void Visit##CLAUSE_NAME##Clause( \ - const OpenACC##CLAUSE_NAME##Clause &Clause); + void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause); #include "clang/Basic/OpenACCClauses.def" }; @@ -2469,8 +2468,7 @@ public: void OpenACCClauseProfiler::VisitDefaultClause( const OpenACCDefaultClause &Clause) {} -void OpenACCClauseProfiler::VisitIfClause( - const OpenACCIfClause &Clause) { +void OpenACCClauseProfiler::VisitIfClause(const OpenACCIfClause &Clause) { assert(Clause.hasConditionExpr() && "if clause requires a valid condition expr"); Profiler.VisitStmt(Clause.getConditionExpr()); -- GitLab From 779ba60417b467a6d2d25101b11711c009694315 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Fri, 12 Apr 2024 14:46:56 -0700 Subject: [PATCH 122/464] [clang][deps] Overload `Filesystem::exists` in `DependencyScanningFilesystem` to have it use cached `status` (#88152) As-is, calls to `exists()` fallback on the implementation in `ProxyFileSystem::exists` which explicitly calls out to the underlying `FS`, which for the `DependencyScanningFilesystem` (overlay) is the real underlying filesystem. Instead, directly overloading `exists` allows us to have it rely on the cached `status` behavior used elsewhere by the `DependencyScanningFilesystem`. --- .../DependencyScanningFilesystem.h | 4 +++ .../DependencyScanningFilesystem.cpp | 11 ++++++++ .../DependencyScanningFilesystemTest.cpp | 27 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 8b6f149c7cb2..f7b4510d7f7b 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -365,6 +365,10 @@ public: /// false if not (i.e. this entry is not a file or its scan fails). bool ensureDirectiveTokensArePopulated(EntryRef Entry); + /// Check whether \p Path exists. By default checks cached result of \c + /// status(), and falls back on FS if unable to do so. + bool exists(const Twine &Path) override; + private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 84185c931b55..0cab17a34244 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -300,6 +300,17 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + // While some VFS overlay filesystems may implement more-efficient + // mechanisms for `exists` queries, `DependencyScanningWorkerFilesystem` + // typically wraps `RealFileSystem` which does not specialize `exists`, + // so it is not likely to benefit from such optimizations. Instead, + // it is more-valuable to have this query go through the + // cached-`status` code-path of the `DependencyScanningWorkerFilesystem`. + llvm::ErrorOr Status = status(Path); + return Status && Status->exists(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp index 697b7d70ff03..87bb67cfd932 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp @@ -18,6 +18,7 @@ struct InstrumentingFilesystem : llvm::RTTIExtends { unsigned NumStatusCalls = 0; unsigned NumGetRealPathCalls = 0; + unsigned NumExistsCalls = 0; using llvm::RTTIExtends::RTTIExtends; @@ -32,6 +33,11 @@ struct InstrumentingFilesystem ++NumGetRealPathCalls; return ProxyFileSystem::getRealPath(Path, Output); } + + bool exists(const llvm::Twine &Path) override { + ++NumExistsCalls; + return ProxyFileSystem::exists(Path); + } }; } // namespace @@ -147,3 +153,24 @@ TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) { DepFS.status("/bar"); } } + +TEST(DependencyScanningFilesystem, CacheStatOnExists) { + auto InMemoryFS = llvm::makeIntrusiveRefCnt(); + auto InstrumentingFS = + llvm::makeIntrusiveRefCnt(InMemoryFS); + InMemoryFS->setCurrentWorkingDirectory("/"); + InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer("")); + InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer("")); + DependencyScanningFilesystemSharedCache SharedCache; + DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS); + + DepFS.status("/foo"); + DepFS.status("/foo"); + DepFS.status("/bar"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); + + DepFS.exists("/foo"); + DepFS.exists("/bar"); + EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); + EXPECT_EQ(InstrumentingFS->NumExistsCalls, 0u); +} -- GitLab From 03c393db1821ef4c362c4c228492c6fb03f8876f Mon Sep 17 00:00:00 2001 From: erichkeane Date: Fri, 12 Apr 2024 14:48:39 -0700 Subject: [PATCH 123/464] Fix build failure from a472e6473e69 Looks like I forgot to do build CIndex.cpp when validating myself! --- clang/tools/libclang/CIndex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index b999750c0f5e..f304786ff9df 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2783,7 +2783,7 @@ public: OpenACCClauseEnqueue(EnqueueVisitor &V) : Visitor(V) {} #define VISIT_CLAUSE(CLAUSE_NAME) \ - void VisitOpenACC##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &C); + void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &C); #include "clang/Basic/OpenACCClauses.def" }; -- GitLab From 0d2bb7f017f13ceae793fab7d83d3e67e8d8d8f8 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Fri, 12 Apr 2024 15:10:04 -0700 Subject: [PATCH 124/464] [CMake][Release] Disable PGO (#88465) Running the test-release.sh script with PGO enabled causes build errors like: ld.lld: error: Function Import: link error: linking module flags 'ProfileSummary': IDs have conflicting values I believe this a build system bug due to the PGO profile data being generated unconditionally. If you run `ninja check-all` and then `ninja install` like we do in test-release.sh, then the profile data is regenerated during `ninja install` and some of the clang tools which are not test dependencies get build during the ninja install step with different profile data. When these tools link against the LLVM libraries, like libSupport, we end up with these errors. --- clang/cmake/caches/Release.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/cmake/caches/Release.cmake b/clang/cmake/caches/Release.cmake index 1ca9138b9807..bd1f688d61a7 100644 --- a/clang/cmake/caches/Release.cmake +++ b/clang/cmake/caches/Release.cmake @@ -4,7 +4,7 @@ # General Options set(LLVM_RELEASE_ENABLE_LTO THIN CACHE STRING "") -set(LLVM_RELEASE_ENABLE_PGO ON CACHE BOOL "") +set(LLVM_RELEASE_ENABLE_PGO OFF CACHE BOOL "") set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "") -- GitLab From 9bd10853e505b61f5fe2e3b3592c76787a06aa31 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 13 Apr 2024 00:24:12 +0200 Subject: [PATCH 125/464] AMDGPU: Undo atomicrmw add/sub/xor 0 -> atomicrmw or canonicalization (#87533) InstCombine transforms add of 0 to or of 0. For system atomics, this is problematic because while PCIe supports add, it does not support the other operations. Undo this for system scope atomics. --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 27 +- .../AMDGPU/global_atomics_i32_system.ll | 723 ++++++++++-------- ...expand-atomicrmw-integer-ops-0-to-add-0.ll | 130 ++++ 3 files changed, 572 insertions(+), 308 deletions(-) create mode 100644 llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomicrmw-integer-ops-0-to-add-0.ll diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 14948ef9ea8d..6fde73119f81 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -16027,6 +16027,19 @@ SITargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { SSID == RMW->getContext().getOrInsertSyncScopeID("one-as"); switch (RMW->getOperation()) { + case AtomicRMWInst::Sub: + case AtomicRMWInst::Or: + case AtomicRMWInst::Xor: { + // Atomic sub/or/xor do not work over PCI express, but atomic add + // does. InstCombine transforms these with 0 to or, so undo that. + if (HasSystemScope && AMDGPU::isFlatGlobalAddrSpace(AS)) { + if (Constant *ConstVal = dyn_cast(RMW->getValOperand()); + ConstVal && ConstVal->isNullValue()) + return AtomicExpansionKind::Expand; + } + + break; + } case AtomicRMWInst::FAdd: { Type *Ty = RMW->getType(); @@ -16312,14 +16325,24 @@ bool SITargetLowering::checkForPhysRegDependency( } void SITargetLowering::emitExpandAtomicRMW(AtomicRMWInst *AI) const { + AtomicRMWInst::BinOp Op = AI->getOperation(); + + if (Op == AtomicRMWInst::Sub || Op == AtomicRMWInst::Or || + Op == AtomicRMWInst::Xor) { + // atomicrmw or %ptr, 0 -> atomicrmw add %ptr, 0 + assert(cast(AI->getValOperand())->isNullValue() && + "this cannot be replaced with add"); + AI->setOperation(AtomicRMWInst::Add); + return; + } + assert(Subtarget->hasAtomicFaddInsts() && "target should have atomic fadd instructions"); assert(AI->getType()->isFloatTy() && AI->getPointerAddressSpace() == AMDGPUAS::FLAT_ADDRESS && "generic atomicrmw expansion only supports FP32 operand in flat " "address space"); - assert(AI->getOperation() == AtomicRMWInst::FAdd && - "only fadd is supported for now"); + assert(Op == AtomicRMWInst::FAdd && "only fadd is supported for now"); // Given: atomicrmw fadd ptr %addr, float %val ordering // diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll index 99d02ffaa523..4598d23e088b 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll @@ -1403,6 +1403,43 @@ define amdgpu_gfx i32 @global_atomic_sub_i32_ret_offset_scalar(ptr addrspace(1) ret i32 %result } +define i32 @global_atomic_sub_0_i32_ret(ptr addrspace(1) %ptr) { +; SI-LABEL: global_atomic_sub_0_i32_ret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_mov_b32_e32 v2, 0 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_add v2, v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_sub_0_i32_ret: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v2, 0 +; VI-NEXT: flat_atomic_add v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_sub_0_i32_ret: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-NEXT: global_atomic_add v0, v[0:1], v2, off glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw sub ptr addrspace(1) %ptr, i32 0 seq_cst + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw and ; --------------------------------------------------------------------- @@ -1767,7 +1804,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB40_1: ; %atomicrmw.start +; SI-NEXT: .LBB41_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1782,7 +1819,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB40_1 +; SI-NEXT: s_cbranch_execnz .LBB41_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -1793,7 +1830,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB40_1: ; %atomicrmw.start +; VI-NEXT: .LBB41_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1805,7 +1842,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB40_1 +; VI-NEXT: s_cbranch_execnz .LBB41_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -1815,7 +1852,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB40_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB41_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1827,7 +1864,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB40_1 +; GFX9-NEXT: s_cbranch_execnz .LBB41_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -1845,7 +1882,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB41_1: ; %atomicrmw.start +; SI-NEXT: .LBB42_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1860,7 +1897,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB41_1 +; SI-NEXT: s_cbranch_execnz .LBB42_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -1873,7 +1910,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB41_1: ; %atomicrmw.start +; VI-NEXT: .LBB42_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1885,7 +1922,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB41_1 +; VI-NEXT: s_cbranch_execnz .LBB42_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -1895,7 +1932,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB41_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB42_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1907,7 +1944,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB41_1 +; GFX9-NEXT: s_cbranch_execnz .LBB42_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -1926,7 +1963,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB42_1: ; %atomicrmw.start +; SI-NEXT: .LBB43_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -1941,7 +1978,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB42_1 +; SI-NEXT: s_cbranch_execnz .LBB43_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -1953,7 +1990,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB42_1: ; %atomicrmw.start +; VI-NEXT: .LBB43_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -1965,7 +2002,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB42_1 +; VI-NEXT: s_cbranch_execnz .LBB43_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -1976,7 +2013,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB42_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB43_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -1988,7 +2025,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB42_1 +; GFX9-NEXT: s_cbranch_execnz .LBB43_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -2007,7 +2044,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB43_1: ; %atomicrmw.start +; SI-NEXT: .LBB44_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -2022,7 +2059,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB43_1 +; SI-NEXT: s_cbranch_execnz .LBB44_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -2036,7 +2073,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB43_1: ; %atomicrmw.start +; VI-NEXT: .LBB44_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -2048,7 +2085,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB43_1 +; VI-NEXT: s_cbranch_execnz .LBB44_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2058,7 +2095,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB43_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB44_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -2070,7 +2107,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB43_1 +; GFX9-NEXT: s_cbranch_execnz .LBB44_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -2095,7 +2132,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB44_1: ; %atomicrmw.start +; SI-NEXT: .LBB45_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v0, s34, v1 @@ -2110,7 +2147,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB44_1 +; SI-NEXT: s_cbranch_execnz .LBB45_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -2128,7 +2165,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB44_1: ; %atomicrmw.start +; VI-NEXT: .LBB45_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v2, s6, v3 @@ -2140,7 +2177,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB44_1 +; VI-NEXT: s_cbranch_execnz .LBB45_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2151,7 +2188,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB44_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB45_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v0, s6, v1 @@ -2163,7 +2200,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB44_1 +; GFX9-NEXT: s_cbranch_execnz .LBB45_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2186,7 +2223,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB45_1: ; %atomicrmw.start +; SI-NEXT: .LBB46_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v0, s34, v1 @@ -2201,7 +2238,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB45_1 +; SI-NEXT: s_cbranch_execnz .LBB46_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -2221,7 +2258,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB45_1: ; %atomicrmw.start +; VI-NEXT: .LBB46_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v2, s6, v3 @@ -2233,7 +2270,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB45_1 +; VI-NEXT: s_cbranch_execnz .LBB46_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2244,7 +2281,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB45_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB46_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v0, s6, v1 @@ -2256,7 +2293,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB45_1 +; GFX9-NEXT: s_cbranch_execnz .LBB46_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2280,7 +2317,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB46_1: ; %atomicrmw.start +; SI-NEXT: .LBB47_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -2295,7 +2332,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB46_1 +; SI-NEXT: s_cbranch_execnz .LBB47_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -2315,7 +2352,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB46_1: ; %atomicrmw.start +; VI-NEXT: .LBB47_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -2327,7 +2364,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB46_1 +; VI-NEXT: s_cbranch_execnz .LBB47_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2338,7 +2375,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB46_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB47_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -2350,7 +2387,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB46_1 +; GFX9-NEXT: s_cbranch_execnz .LBB47_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2373,7 +2410,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB47_1: ; %atomicrmw.start +; SI-NEXT: .LBB48_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -2388,7 +2425,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB47_1 +; SI-NEXT: s_cbranch_execnz .LBB48_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -2408,7 +2445,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB47_1: ; %atomicrmw.start +; VI-NEXT: .LBB48_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -2420,7 +2457,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB47_1 +; VI-NEXT: s_cbranch_execnz .LBB48_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2431,7 +2468,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB47_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB48_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -2443,7 +2480,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB47_1 +; GFX9-NEXT: s_cbranch_execnz .LBB48_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2802,6 +2839,43 @@ define amdgpu_gfx i32 @global_atomic_or_i32_ret_offset_scalar(ptr addrspace(1) i ret i32 %result } +define i32 @global_atomic_or_0_i32_ret(ptr addrspace(1) %ptr) { +; SI-LABEL: global_atomic_or_0_i32_ret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_mov_b32_e32 v2, 0 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_add v2, v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_or_0_i32_ret: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v2, 0 +; VI-NEXT: flat_atomic_add v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_or_0_i32_ret: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-NEXT: global_atomic_add v0, v[0:1], v2, off glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw or ptr addrspace(1) %ptr, i32 0 seq_cst + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw xor ; --------------------------------------------------------------------- @@ -3152,6 +3226,43 @@ define amdgpu_gfx i32 @global_atomic_xor_i32_ret_offset_scalar(ptr addrspace(1) ret i32 %result } +define i32 @global_atomic_xor_0_i32_ret(ptr addrspace(1) %ptr) { +; SI-LABEL: global_atomic_xor_0_i32_ret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: v_mov_b32_e32 v2, 0 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_add v2, v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xor_0_i32_ret: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v2, 0 +; VI-NEXT: flat_atomic_add v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xor_0_i32_ret: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-NEXT: global_atomic_add v0, v[0:1], v2, off glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw xor ptr addrspace(1) %ptr, i32 0 seq_cst + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw max ; --------------------------------------------------------------------- @@ -3166,7 +3277,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB64_1: ; %atomicrmw.start +; SI-NEXT: .LBB67_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3180,7 +3291,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB64_1 +; SI-NEXT: s_cbranch_execnz .LBB67_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -3191,7 +3302,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB64_1: ; %atomicrmw.start +; VI-NEXT: .LBB67_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3202,7 +3313,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB64_1 +; VI-NEXT: s_cbranch_execnz .LBB67_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3212,7 +3323,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB64_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB67_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3223,7 +3334,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB64_1 +; GFX9-NEXT: s_cbranch_execnz .LBB67_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3241,7 +3352,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB65_1: ; %atomicrmw.start +; SI-NEXT: .LBB68_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3255,7 +3366,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB65_1 +; SI-NEXT: s_cbranch_execnz .LBB68_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -3268,7 +3379,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB65_1: ; %atomicrmw.start +; VI-NEXT: .LBB68_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3279,7 +3390,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB65_1 +; VI-NEXT: s_cbranch_execnz .LBB68_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3289,7 +3400,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB65_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB68_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3300,7 +3411,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB65_1 +; GFX9-NEXT: s_cbranch_execnz .LBB68_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3319,7 +3430,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB66_1: ; %atomicrmw.start +; SI-NEXT: .LBB69_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -3333,7 +3444,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB66_1 +; SI-NEXT: s_cbranch_execnz .LBB69_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -3345,7 +3456,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB66_1: ; %atomicrmw.start +; VI-NEXT: .LBB69_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -3356,7 +3467,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB66_1 +; VI-NEXT: s_cbranch_execnz .LBB69_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -3367,7 +3478,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB66_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB69_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -3378,7 +3489,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB66_1 +; GFX9-NEXT: s_cbranch_execnz .LBB69_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -3397,7 +3508,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB67_1: ; %atomicrmw.start +; SI-NEXT: .LBB70_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -3411,7 +3522,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB67_1 +; SI-NEXT: s_cbranch_execnz .LBB70_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -3425,7 +3536,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB67_1: ; %atomicrmw.start +; VI-NEXT: .LBB70_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -3436,7 +3547,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB67_1 +; VI-NEXT: s_cbranch_execnz .LBB70_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3446,7 +3557,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB67_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB70_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -3457,7 +3568,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB67_1 +; GFX9-NEXT: s_cbranch_execnz .LBB70_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -3482,7 +3593,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB68_1: ; %atomicrmw.start +; SI-NEXT: .LBB71_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_i32_e32 v0, s34, v1 @@ -3496,7 +3607,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB68_1 +; SI-NEXT: s_cbranch_execnz .LBB71_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -3514,7 +3625,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB68_1: ; %atomicrmw.start +; VI-NEXT: .LBB71_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_i32_e32 v2, s6, v3 @@ -3525,7 +3636,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB68_1 +; VI-NEXT: s_cbranch_execnz .LBB71_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3536,7 +3647,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB68_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB71_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_i32_e32 v0, s6, v1 @@ -3547,7 +3658,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB68_1 +; GFX9-NEXT: s_cbranch_execnz .LBB71_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3570,7 +3681,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB69_1: ; %atomicrmw.start +; SI-NEXT: .LBB72_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_i32_e32 v0, s34, v1 @@ -3584,7 +3695,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB69_1 +; SI-NEXT: s_cbranch_execnz .LBB72_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -3604,7 +3715,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB69_1: ; %atomicrmw.start +; VI-NEXT: .LBB72_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_i32_e32 v2, s6, v3 @@ -3615,7 +3726,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB69_1 +; VI-NEXT: s_cbranch_execnz .LBB72_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3626,7 +3737,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB69_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB72_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_i32_e32 v0, s6, v1 @@ -3637,7 +3748,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB69_1 +; GFX9-NEXT: s_cbranch_execnz .LBB72_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3661,7 +3772,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB70_1: ; %atomicrmw.start +; SI-NEXT: .LBB73_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -3675,7 +3786,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB70_1 +; SI-NEXT: s_cbranch_execnz .LBB73_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -3695,7 +3806,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB70_1: ; %atomicrmw.start +; VI-NEXT: .LBB73_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -3706,7 +3817,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB70_1 +; VI-NEXT: s_cbranch_execnz .LBB73_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3717,7 +3828,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB70_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB73_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -3728,7 +3839,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB70_1 +; GFX9-NEXT: s_cbranch_execnz .LBB73_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3751,7 +3862,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB71_1: ; %atomicrmw.start +; SI-NEXT: .LBB74_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -3765,7 +3876,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB71_1 +; SI-NEXT: s_cbranch_execnz .LBB74_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -3785,7 +3896,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB71_1: ; %atomicrmw.start +; VI-NEXT: .LBB74_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -3796,7 +3907,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB71_1 +; VI-NEXT: s_cbranch_execnz .LBB74_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3807,7 +3918,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB71_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB74_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -3818,7 +3929,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB71_1 +; GFX9-NEXT: s_cbranch_execnz .LBB74_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3843,7 +3954,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB72_1: ; %atomicrmw.start +; SI-NEXT: .LBB75_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_i32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -3856,7 +3967,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB72_1 +; SI-NEXT: s_cbranch_execnz .LBB75_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -3877,7 +3988,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 ; VI-NEXT: v_mov_b32_e32 v1, s5 -; VI-NEXT: .LBB72_1: ; %atomicrmw.start +; VI-NEXT: .LBB75_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_max_i32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -3887,7 +3998,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB72_1 +; VI-NEXT: s_cbranch_execnz .LBB75_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -3905,7 +4016,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: .LBB72_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB75_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_max_i32_e32 v0, s2, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] offset:16 glc @@ -3915,7 +4026,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB72_1 +; GFX9-NEXT: s_cbranch_execnz .LBB75_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -3942,7 +4053,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB73_1: ; %atomicrmw.start +; SI-NEXT: .LBB76_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_i32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -3955,7 +4066,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB73_1 +; SI-NEXT: s_cbranch_execnz .LBB76_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -3983,7 +4094,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 ; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: .LBB73_1: ; %atomicrmw.start +; VI-NEXT: .LBB76_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_max_i32_e32 v2, s4, v3 @@ -3993,7 +4104,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB73_1 +; VI-NEXT: s_cbranch_execnz .LBB76_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -4016,7 +4127,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB73_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB76_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_max_i32_e32 v2, s2, v3 @@ -4026,7 +4137,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB73_1 +; GFX9-NEXT: s_cbranch_execnz .LBB76_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -4056,7 +4167,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB74_1: ; %atomicrmw.start +; SI-NEXT: .LBB77_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_i32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -4069,7 +4180,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB74_1 +; SI-NEXT: s_cbranch_execnz .LBB77_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -4088,7 +4199,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 -; VI-NEXT: .LBB74_1: ; %atomicrmw.start +; VI-NEXT: .LBB77_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_max_i32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -4098,7 +4209,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB74_1 +; VI-NEXT: s_cbranch_execnz .LBB77_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -4116,7 +4227,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: .LBB74_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB77_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_max_i32_e32 v0, s2, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc @@ -4126,7 +4237,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB74_1 +; GFX9-NEXT: s_cbranch_execnz .LBB77_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -4152,7 +4263,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB75_1: ; %atomicrmw.start +; SI-NEXT: .LBB78_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_i32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -4165,7 +4276,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB75_1 +; SI-NEXT: s_cbranch_execnz .LBB78_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -4191,7 +4302,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_mov_b32_e32 v1, s7 ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB75_1: ; %atomicrmw.start +; VI-NEXT: .LBB78_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_max_i32_e32 v2, s4, v3 @@ -4201,7 +4312,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB75_1 +; VI-NEXT: s_cbranch_execnz .LBB78_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -4224,7 +4335,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB75_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB78_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_max_i32_e32 v2, s2, v3 @@ -4234,7 +4345,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB75_1 +; GFX9-NEXT: s_cbranch_execnz .LBB78_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -4261,7 +4372,7 @@ define void @global_atomic_umax_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB76_1: ; %atomicrmw.start +; SI-NEXT: .LBB79_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_u32_e32 v3, v4, v2 @@ -4275,7 +4386,7 @@ define void @global_atomic_umax_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB76_1 +; SI-NEXT: s_cbranch_execnz .LBB79_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -4286,7 +4397,7 @@ define void @global_atomic_umax_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB76_1: ; %atomicrmw.start +; VI-NEXT: .LBB79_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_u32_e32 v3, v4, v2 @@ -4297,7 +4408,7 @@ define void @global_atomic_umax_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB76_1 +; VI-NEXT: s_cbranch_execnz .LBB79_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4307,7 +4418,7 @@ define void @global_atomic_umax_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB76_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB79_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_u32_e32 v3, v4, v2 @@ -4318,7 +4429,7 @@ define void @global_atomic_umax_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB76_1 +; GFX9-NEXT: s_cbranch_execnz .LBB79_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4336,7 +4447,7 @@ define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB77_1: ; %atomicrmw.start +; SI-NEXT: .LBB80_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_u32_e32 v3, v4, v2 @@ -4350,7 +4461,7 @@ define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB77_1 +; SI-NEXT: s_cbranch_execnz .LBB80_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -4363,7 +4474,7 @@ define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB77_1: ; %atomicrmw.start +; VI-NEXT: .LBB80_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_u32_e32 v3, v4, v2 @@ -4374,7 +4485,7 @@ define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB77_1 +; VI-NEXT: s_cbranch_execnz .LBB80_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4384,7 +4495,7 @@ define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB77_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB80_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_u32_e32 v3, v4, v2 @@ -4395,7 +4506,7 @@ define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB77_1 +; GFX9-NEXT: s_cbranch_execnz .LBB80_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4414,7 +4525,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB78_1: ; %atomicrmw.start +; SI-NEXT: .LBB81_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -4428,7 +4539,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB78_1 +; SI-NEXT: s_cbranch_execnz .LBB81_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -4440,7 +4551,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB78_1: ; %atomicrmw.start +; VI-NEXT: .LBB81_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -4451,7 +4562,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB78_1 +; VI-NEXT: s_cbranch_execnz .LBB81_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -4462,7 +4573,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB78_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB81_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -4473,7 +4584,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB78_1 +; GFX9-NEXT: s_cbranch_execnz .LBB81_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -4492,7 +4603,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB79_1: ; %atomicrmw.start +; SI-NEXT: .LBB82_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -4506,7 +4617,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB79_1 +; SI-NEXT: s_cbranch_execnz .LBB82_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -4520,7 +4631,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB79_1: ; %atomicrmw.start +; VI-NEXT: .LBB82_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -4531,7 +4642,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB79_1 +; VI-NEXT: s_cbranch_execnz .LBB82_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4541,7 +4652,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB79_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB82_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -4552,7 +4663,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB79_1 +; GFX9-NEXT: s_cbranch_execnz .LBB82_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -4577,7 +4688,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB80_1: ; %atomicrmw.start +; SI-NEXT: .LBB83_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_u32_e32 v0, s34, v1 @@ -4591,7 +4702,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB80_1 +; SI-NEXT: s_cbranch_execnz .LBB83_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -4609,7 +4720,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB80_1: ; %atomicrmw.start +; VI-NEXT: .LBB83_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_u32_e32 v2, s6, v3 @@ -4620,7 +4731,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB80_1 +; VI-NEXT: s_cbranch_execnz .LBB83_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4631,7 +4742,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB80_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB83_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_u32_e32 v0, s6, v1 @@ -4642,7 +4753,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB80_1 +; GFX9-NEXT: s_cbranch_execnz .LBB83_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4665,7 +4776,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB81_1: ; %atomicrmw.start +; SI-NEXT: .LBB84_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_u32_e32 v0, s34, v1 @@ -4679,7 +4790,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB81_1 +; SI-NEXT: s_cbranch_execnz .LBB84_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -4699,7 +4810,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB81_1: ; %atomicrmw.start +; VI-NEXT: .LBB84_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_u32_e32 v2, s6, v3 @@ -4710,7 +4821,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB81_1 +; VI-NEXT: s_cbranch_execnz .LBB84_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4721,7 +4832,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB81_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB84_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_u32_e32 v0, s6, v1 @@ -4732,7 +4843,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB81_1 +; GFX9-NEXT: s_cbranch_execnz .LBB84_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4756,7 +4867,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB82_1: ; %atomicrmw.start +; SI-NEXT: .LBB85_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -4770,7 +4881,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB82_1 +; SI-NEXT: s_cbranch_execnz .LBB85_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -4790,7 +4901,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB82_1: ; %atomicrmw.start +; VI-NEXT: .LBB85_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -4801,7 +4912,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB82_1 +; VI-NEXT: s_cbranch_execnz .LBB85_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4812,7 +4923,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB82_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB85_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -4823,7 +4934,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB82_1 +; GFX9-NEXT: s_cbranch_execnz .LBB85_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4846,7 +4957,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB83_1: ; %atomicrmw.start +; SI-NEXT: .LBB86_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -4860,7 +4971,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB83_1 +; SI-NEXT: s_cbranch_execnz .LBB86_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -4880,7 +4991,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB83_1: ; %atomicrmw.start +; VI-NEXT: .LBB86_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -4891,7 +5002,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB83_1 +; VI-NEXT: s_cbranch_execnz .LBB86_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4902,7 +5013,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB83_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB86_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -4913,7 +5024,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB83_1 +; GFX9-NEXT: s_cbranch_execnz .LBB86_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4938,7 +5049,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB84_1: ; %atomicrmw.start +; SI-NEXT: .LBB87_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_u32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -4951,7 +5062,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB84_1 +; SI-NEXT: s_cbranch_execnz .LBB87_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -4972,7 +5083,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 ; VI-NEXT: v_mov_b32_e32 v1, s5 -; VI-NEXT: .LBB84_1: ; %atomicrmw.start +; VI-NEXT: .LBB87_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_max_u32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -4982,7 +5093,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB84_1 +; VI-NEXT: s_cbranch_execnz .LBB87_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -5000,7 +5111,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: .LBB84_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB87_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_max_u32_e32 v0, s2, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] offset:16 glc @@ -5010,7 +5121,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB84_1 +; GFX9-NEXT: s_cbranch_execnz .LBB87_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -5037,7 +5148,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB85_1: ; %atomicrmw.start +; SI-NEXT: .LBB88_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_u32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -5050,7 +5161,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB85_1 +; SI-NEXT: s_cbranch_execnz .LBB88_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -5078,7 +5189,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 ; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: .LBB85_1: ; %atomicrmw.start +; VI-NEXT: .LBB88_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_max_u32_e32 v2, s4, v3 @@ -5088,7 +5199,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB85_1 +; VI-NEXT: s_cbranch_execnz .LBB88_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -5111,7 +5222,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB85_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB88_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_max_u32_e32 v2, s2, v3 @@ -5121,7 +5232,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB85_1 +; GFX9-NEXT: s_cbranch_execnz .LBB88_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -5152,7 +5263,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB86_1: ; %atomicrmw.start +; SI-NEXT: .LBB89_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_u32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -5165,7 +5276,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB86_1 +; SI-NEXT: s_cbranch_execnz .LBB89_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -5191,7 +5302,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_mov_b32_e32 v1, s7 ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB86_1: ; %atomicrmw.start +; VI-NEXT: .LBB89_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_max_u32_e32 v2, s4, v3 @@ -5201,7 +5312,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB86_1 +; VI-NEXT: s_cbranch_execnz .LBB89_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -5224,7 +5335,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB86_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB89_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_max_u32_e32 v2, s2, v3 @@ -5234,7 +5345,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB86_1 +; GFX9-NEXT: s_cbranch_execnz .LBB89_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -5261,7 +5372,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB87_1: ; %atomicrmw.start +; SI-NEXT: .LBB90_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5275,7 +5386,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB87_1 +; SI-NEXT: s_cbranch_execnz .LBB90_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -5286,7 +5397,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB87_1: ; %atomicrmw.start +; VI-NEXT: .LBB90_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5297,7 +5408,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB87_1 +; VI-NEXT: s_cbranch_execnz .LBB90_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5307,7 +5418,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB87_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB90_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5318,7 +5429,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB87_1 +; GFX9-NEXT: s_cbranch_execnz .LBB90_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5336,7 +5447,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB88_1: ; %atomicrmw.start +; SI-NEXT: .LBB91_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5350,7 +5461,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB88_1 +; SI-NEXT: s_cbranch_execnz .LBB91_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -5363,7 +5474,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB88_1: ; %atomicrmw.start +; VI-NEXT: .LBB91_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5374,7 +5485,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB88_1 +; VI-NEXT: s_cbranch_execnz .LBB91_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5384,7 +5495,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB88_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB91_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5395,7 +5506,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB88_1 +; GFX9-NEXT: s_cbranch_execnz .LBB91_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5414,7 +5525,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB89_1: ; %atomicrmw.start +; SI-NEXT: .LBB92_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -5428,7 +5539,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB89_1 +; SI-NEXT: s_cbranch_execnz .LBB92_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -5440,7 +5551,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB89_1: ; %atomicrmw.start +; VI-NEXT: .LBB92_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -5451,7 +5562,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB89_1 +; VI-NEXT: s_cbranch_execnz .LBB92_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -5462,7 +5573,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB89_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB92_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -5473,7 +5584,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB89_1 +; GFX9-NEXT: s_cbranch_execnz .LBB92_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -5492,7 +5603,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB90_1: ; %atomicrmw.start +; SI-NEXT: .LBB93_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -5506,7 +5617,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB90_1 +; SI-NEXT: s_cbranch_execnz .LBB93_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -5520,7 +5631,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB90_1: ; %atomicrmw.start +; VI-NEXT: .LBB93_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -5531,7 +5642,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB90_1 +; VI-NEXT: s_cbranch_execnz .LBB93_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5541,7 +5652,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB90_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB93_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -5552,7 +5663,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB90_1 +; GFX9-NEXT: s_cbranch_execnz .LBB93_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -5577,7 +5688,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB91_1: ; %atomicrmw.start +; SI-NEXT: .LBB94_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_u32_e32 v0, s34, v1 @@ -5591,7 +5702,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB91_1 +; SI-NEXT: s_cbranch_execnz .LBB94_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -5609,7 +5720,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB91_1: ; %atomicrmw.start +; VI-NEXT: .LBB94_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_u32_e32 v2, s6, v3 @@ -5620,7 +5731,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB91_1 +; VI-NEXT: s_cbranch_execnz .LBB94_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5631,7 +5742,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB91_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB94_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_u32_e32 v0, s6, v1 @@ -5642,7 +5753,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB91_1 +; GFX9-NEXT: s_cbranch_execnz .LBB94_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5665,7 +5776,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB92_1: ; %atomicrmw.start +; SI-NEXT: .LBB95_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_u32_e32 v0, s34, v1 @@ -5679,7 +5790,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB92_1 +; SI-NEXT: s_cbranch_execnz .LBB95_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -5699,7 +5810,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB92_1: ; %atomicrmw.start +; VI-NEXT: .LBB95_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_u32_e32 v2, s6, v3 @@ -5710,7 +5821,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB92_1 +; VI-NEXT: s_cbranch_execnz .LBB95_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5721,7 +5832,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB92_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB95_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_u32_e32 v0, s6, v1 @@ -5732,7 +5843,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB92_1 +; GFX9-NEXT: s_cbranch_execnz .LBB95_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5756,7 +5867,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB93_1: ; %atomicrmw.start +; SI-NEXT: .LBB96_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -5770,7 +5881,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB93_1 +; SI-NEXT: s_cbranch_execnz .LBB96_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -5790,7 +5901,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB93_1: ; %atomicrmw.start +; VI-NEXT: .LBB96_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -5801,7 +5912,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB93_1 +; VI-NEXT: s_cbranch_execnz .LBB96_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5812,7 +5923,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB93_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB96_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -5823,7 +5934,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB93_1 +; GFX9-NEXT: s_cbranch_execnz .LBB96_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5846,7 +5957,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB94_1: ; %atomicrmw.start +; SI-NEXT: .LBB97_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -5860,7 +5971,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB94_1 +; SI-NEXT: s_cbranch_execnz .LBB97_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -5880,7 +5991,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB94_1: ; %atomicrmw.start +; VI-NEXT: .LBB97_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -5891,7 +6002,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB94_1 +; VI-NEXT: s_cbranch_execnz .LBB97_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5902,7 +6013,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB94_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB97_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -5913,7 +6024,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB94_1 +; GFX9-NEXT: s_cbranch_execnz .LBB97_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5936,7 +6047,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB95_1: ; %atomicrmw.start +; SI-NEXT: .LBB98_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_i32_e32 v3, v4, v2 @@ -5950,7 +6061,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB95_1 +; SI-NEXT: s_cbranch_execnz .LBB98_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -5961,7 +6072,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB95_1: ; %atomicrmw.start +; VI-NEXT: .LBB98_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_i32_e32 v3, v4, v2 @@ -5972,7 +6083,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB95_1 +; VI-NEXT: s_cbranch_execnz .LBB98_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5982,7 +6093,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB95_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB98_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_i32_e32 v3, v4, v2 @@ -5993,7 +6104,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB95_1 +; GFX9-NEXT: s_cbranch_execnz .LBB98_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6011,7 +6122,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB96_1: ; %atomicrmw.start +; SI-NEXT: .LBB99_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_i32_e32 v3, v4, v2 @@ -6025,7 +6136,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB96_1 +; SI-NEXT: s_cbranch_execnz .LBB99_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -6038,7 +6149,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB96_1: ; %atomicrmw.start +; VI-NEXT: .LBB99_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_i32_e32 v3, v4, v2 @@ -6049,7 +6160,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB96_1 +; VI-NEXT: s_cbranch_execnz .LBB99_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6059,7 +6170,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB96_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB99_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_i32_e32 v3, v4, v2 @@ -6070,7 +6181,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB96_1 +; GFX9-NEXT: s_cbranch_execnz .LBB99_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6089,7 +6200,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB97_1: ; %atomicrmw.start +; SI-NEXT: .LBB100_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -6103,7 +6214,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB97_1 +; SI-NEXT: s_cbranch_execnz .LBB100_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -6115,7 +6226,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB97_1: ; %atomicrmw.start +; VI-NEXT: .LBB100_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -6126,7 +6237,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB97_1 +; VI-NEXT: s_cbranch_execnz .LBB100_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -6137,7 +6248,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB97_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB100_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -6148,7 +6259,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB97_1 +; GFX9-NEXT: s_cbranch_execnz .LBB100_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -6167,7 +6278,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB98_1: ; %atomicrmw.start +; SI-NEXT: .LBB101_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -6181,7 +6292,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB98_1 +; SI-NEXT: s_cbranch_execnz .LBB101_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -6195,7 +6306,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB98_1: ; %atomicrmw.start +; VI-NEXT: .LBB101_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -6206,7 +6317,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB98_1 +; VI-NEXT: s_cbranch_execnz .LBB101_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6216,7 +6327,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB98_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB101_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -6227,7 +6338,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB98_1 +; GFX9-NEXT: s_cbranch_execnz .LBB101_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -6252,7 +6363,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB99_1: ; %atomicrmw.start +; SI-NEXT: .LBB102_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_i32_e32 v0, s34, v1 @@ -6266,7 +6377,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB99_1 +; SI-NEXT: s_cbranch_execnz .LBB102_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -6284,7 +6395,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB99_1: ; %atomicrmw.start +; VI-NEXT: .LBB102_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_i32_e32 v2, s6, v3 @@ -6295,7 +6406,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB99_1 +; VI-NEXT: s_cbranch_execnz .LBB102_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6306,7 +6417,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB99_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB102_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_i32_e32 v0, s6, v1 @@ -6317,7 +6428,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB99_1 +; GFX9-NEXT: s_cbranch_execnz .LBB102_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6340,7 +6451,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB100_1: ; %atomicrmw.start +; SI-NEXT: .LBB103_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_i32_e32 v0, s34, v1 @@ -6354,7 +6465,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB100_1 +; SI-NEXT: s_cbranch_execnz .LBB103_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -6374,7 +6485,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB100_1: ; %atomicrmw.start +; VI-NEXT: .LBB103_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_i32_e32 v2, s6, v3 @@ -6385,7 +6496,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB100_1 +; VI-NEXT: s_cbranch_execnz .LBB103_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6396,7 +6507,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB100_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB103_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_i32_e32 v0, s6, v1 @@ -6407,7 +6518,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB100_1 +; GFX9-NEXT: s_cbranch_execnz .LBB103_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6431,7 +6542,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB101_1: ; %atomicrmw.start +; SI-NEXT: .LBB104_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -6445,7 +6556,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB101_1 +; SI-NEXT: s_cbranch_execnz .LBB104_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -6465,7 +6576,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB101_1: ; %atomicrmw.start +; VI-NEXT: .LBB104_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -6476,7 +6587,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB101_1 +; VI-NEXT: s_cbranch_execnz .LBB104_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6487,7 +6598,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB101_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB104_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -6498,7 +6609,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB101_1 +; GFX9-NEXT: s_cbranch_execnz .LBB104_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6521,7 +6632,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB102_1: ; %atomicrmw.start +; SI-NEXT: .LBB105_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -6535,7 +6646,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB102_1 +; SI-NEXT: s_cbranch_execnz .LBB105_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -6555,7 +6666,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB102_1: ; %atomicrmw.start +; VI-NEXT: .LBB105_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -6566,7 +6677,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB102_1 +; VI-NEXT: s_cbranch_execnz .LBB105_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6577,7 +6688,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB102_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB105_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -6588,7 +6699,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB102_1 +; GFX9-NEXT: s_cbranch_execnz .LBB105_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6613,7 +6724,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB103_1: ; %atomicrmw.start +; SI-NEXT: .LBB106_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_min_i32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -6626,7 +6737,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB103_1 +; SI-NEXT: s_cbranch_execnz .LBB106_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -6647,7 +6758,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 ; VI-NEXT: v_mov_b32_e32 v1, s5 -; VI-NEXT: .LBB103_1: ; %atomicrmw.start +; VI-NEXT: .LBB106_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_min_i32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -6657,7 +6768,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB103_1 +; VI-NEXT: s_cbranch_execnz .LBB106_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -6675,7 +6786,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: .LBB103_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB106_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_min_i32_e32 v0, s2, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] offset:16 glc @@ -6685,7 +6796,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB103_1 +; GFX9-NEXT: s_cbranch_execnz .LBB106_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -6712,7 +6823,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB104_1: ; %atomicrmw.start +; SI-NEXT: .LBB107_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_min_i32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -6725,7 +6836,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB104_1 +; SI-NEXT: s_cbranch_execnz .LBB107_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -6753,7 +6864,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 ; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: .LBB104_1: ; %atomicrmw.start +; VI-NEXT: .LBB107_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_min_i32_e32 v2, s4, v3 @@ -6763,7 +6874,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB104_1 +; VI-NEXT: s_cbranch_execnz .LBB107_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -6786,7 +6897,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB104_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB107_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_min_i32_e32 v2, s2, v3 @@ -6796,7 +6907,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB104_1 +; GFX9-NEXT: s_cbranch_execnz .LBB107_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -6822,7 +6933,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB105_1: ; %atomicrmw.start +; SI-NEXT: .LBB108_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_min_i32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -6835,7 +6946,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB105_1 +; SI-NEXT: s_cbranch_execnz .LBB108_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -6850,7 +6961,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 -; VI-NEXT: .LBB105_1: ; %atomicrmw.start +; VI-NEXT: .LBB108_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_min_i32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -6860,7 +6971,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB105_1 +; VI-NEXT: s_cbranch_execnz .LBB108_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -6874,7 +6985,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_load_dword s5, s[2:3], 0x0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s5 -; GFX9-NEXT: .LBB105_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB108_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_min_i32_e32 v0, s4, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[2:3] glc @@ -6884,7 +6995,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX9-NEXT: s_cbranch_execnz .LBB105_1 +; GFX9-NEXT: s_cbranch_execnz .LBB108_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -6909,7 +7020,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB106_1: ; %atomicrmw.start +; SI-NEXT: .LBB109_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_min_i32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -6922,7 +7033,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB106_1 +; SI-NEXT: s_cbranch_execnz .LBB109_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -6948,7 +7059,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_mov_b32_e32 v1, s7 ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB106_1: ; %atomicrmw.start +; VI-NEXT: .LBB109_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_min_i32_e32 v2, s4, v3 @@ -6958,7 +7069,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB106_1 +; VI-NEXT: s_cbranch_execnz .LBB109_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -6981,7 +7092,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB106_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB109_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_min_i32_e32 v2, s2, v3 @@ -6991,7 +7102,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB106_1 +; GFX9-NEXT: s_cbranch_execnz .LBB109_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomicrmw-integer-ops-0-to-add-0.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomicrmw-integer-ops-0-to-add-0.ll new file mode 100644 index 000000000000..e32c218e9fe5 --- /dev/null +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomicrmw-integer-ops-0-to-add-0.ll @@ -0,0 +1,130 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=atomic-expand %s | FileCheck %s + +; Test that system scoped atomicrmw or 0 is transformed to add 0. + +; Transform to add +define i32 @test_atomicrmw_or_0_global_system(ptr addrspace(1) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_or_0_global_system( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 0 seq_cst, align 4, !foo.md [[META0:![0-9]+]] +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 0 seq_cst, !foo.md !0 + ret i32 %res +} + +; Transform to add +define i32 @test_atomicrmw_or_0_global_one_as(ptr addrspace(1) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_or_0_global_one_as( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 0 syncscope("one-as") seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 0 syncscope("one-as") seq_cst + ret i32 %res +} + +; Transform to add +define i32 @test_atomicrmw_or_0_flat_system(ptr %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_or_0_flat_system( +; CHECK-SAME: ptr [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr [[PTR]], i32 0 seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw or ptr %ptr, i32 0 seq_cst + ret i32 %res +} + +; Transform to add +define i32 @test_atomicrmw_or_0_as999_system(ptr addrspace(999) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_or_0_as999_system( +; CHECK-SAME: ptr addrspace(999) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(999) [[PTR]], i32 0 seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw or ptr addrspace(999) %ptr, i32 0 seq_cst + ret i32 %res +} + +; Leave as-is, only system scope should be changed. +define i32 @test_atomicrmw_or_0_global_agent(ptr addrspace(1) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_or_0_global_agent( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i32 0 syncscope("agent") seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 0 syncscope("agent") seq_cst + ret i32 %res +} + +; Leave as-is, LDS atomics aren't relevant. +define i32 @test_atomicrmw_or_0_local(ptr addrspace(3) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_or_0_local( +; CHECK-SAME: ptr addrspace(3) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr addrspace(3) [[PTR]], i32 0 seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw or ptr addrspace(3) %ptr, i32 0 seq_cst + ret i32 %res +} + +; Leave non-0 values alone. +define i32 @test_atomicrmw_or_1_global_system(ptr addrspace(1) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_or_1_global_system( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i32 1 seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 1 seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_or_var_global_system(ptr addrspace(1) %ptr, i32 %val) { +; CHECK-LABEL: define i32 @test_atomicrmw_or_var_global_system( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VAL:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i32 [[VAL]] seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 %val seq_cst + ret i32 %res +} + +; Leave as-is +define i32 @test_atomicrmw_add_0_global_system(ptr addrspace(1) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_add_0_global_system( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 0 seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw add ptr addrspace(1) %ptr, i32 0 seq_cst + ret i32 %res +} + +; Transform to add +define i32 @test_atomicrmw_sub_0_global_system(ptr addrspace(1) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_sub_0_global_system( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 0 seq_cst, align 4, !foo.md [[META0]] +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw sub ptr addrspace(1) %ptr, i32 0 seq_cst, !foo.md !0 + ret i32 %res +} + +; Transform to add +define i32 @test_atomicrmw_xor_0_global_system(ptr addrspace(1) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_xor_0_global_system( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 0 seq_cst, align 4, !foo.md [[META0]] +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i32 0 seq_cst, !foo.md !0 + ret i32 %res +} + + +!0 = !{} +;. +; CHECK: [[META0]] = !{} +;. -- GitLab From b9bed1f1106e3116e8bea38806c511b57b956929 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 12 Apr 2024 16:44:46 -0700 Subject: [PATCH 126/464] [test] Improve tests for alias/ifunc attributes --- clang/test/Sema/alias-unused-win.cpp | 31 +++++++++++++++++ clang/test/Sema/alias-unused.c | 7 ---- clang/test/Sema/alias-unused.cpp | 50 ++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 clang/test/Sema/alias-unused-win.cpp delete mode 100644 clang/test/Sema/alias-unused.c create mode 100644 clang/test/Sema/alias-unused.cpp diff --git a/clang/test/Sema/alias-unused-win.cpp b/clang/test/Sema/alias-unused-win.cpp new file mode 100644 index 000000000000..47c96d411751 --- /dev/null +++ b/clang/test/Sema/alias-unused-win.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -triple %ms_abi_triple -Wunused -x c -verify %s +// RUN: %clang_cc1 -triple %ms_abi_triple -Wunused -verify=expected,cxx %s + +#ifdef __cplusplus +extern "C" { +#endif +static int f(void) { return 42; } // cxx-warning{{unused function 'f'}} +int g(void) __attribute__((alias("f"))); + +static int foo [] = { 42, 0xDEAD }; // cxx-warning{{variable 'foo' is not needed and will not be emitted}} +extern typeof(foo) bar __attribute__((unused, alias("foo"))); + +static int __attribute__((overloadable)) f0(int x) { return x; } // expected-warning{{unused function 'f0'}} +static float __attribute__((overloadable)) f0(float x) { return x; } // expected-warning{{unused function 'f0'}} +int g0(void) __attribute__((alias("?f0@@YAHH@Z"))); + +#ifdef __cplusplus +/// https://github.com/llvm/llvm-project/issues/88593 +/// We report a warning in C++ mode because the internal linkage `resolver` gets +/// mangled as it does not have a language linkage. GCC does not mangle +/// `resolver` or report a warning. +static int f1() { return 42; } // cxx-warning{{unused function 'f1'}} +int g1(void) __attribute__((alias("?f1@@YAHXZ"))); +} + +namespace ns { +static int f3(int) { return 42; } // cxx-warning{{unused function 'f3'}} +static int f3() { return 42; } // cxx-warning{{unused function 'f3'}} +int g3() __attribute__((alias("?f3@ns@@YAHXZ"))); +} +#endif diff --git a/clang/test/Sema/alias-unused.c b/clang/test/Sema/alias-unused.c deleted file mode 100644 index de9fc8cc7376..000000000000 --- a/clang/test/Sema/alias-unused.c +++ /dev/null @@ -1,7 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-linux-gnu -Wunneeded-internal-declaration -x c -verify %s -// expected-no-diagnostics -static int f(void) { return 42; } -int g(void) __attribute__((alias("f"))); - -static int foo [] = { 42, 0xDEAD }; -extern typeof(foo) bar __attribute__((unused, alias("foo"))); diff --git a/clang/test/Sema/alias-unused.cpp b/clang/test/Sema/alias-unused.cpp new file mode 100644 index 000000000000..509d3e26225d --- /dev/null +++ b/clang/test/Sema/alias-unused.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -Wunused -x c -verify %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -Wunused -verify=expected,cxx %s + +#ifdef __cplusplus +extern "C" { +#endif +static int f(void) { return 42; } +int g(void) __attribute__((alias("f"))); + +static int foo [] = { 42, 0xDEAD }; // cxx-warning{{variable 'foo' is not needed and will not be emitted}} +extern typeof(foo) bar __attribute__((unused, alias("foo"))); + +/// https://github.com/llvm/llvm-project/issues/88593 +/// We report a warning in C++ mode because the internal linkage `resolver` gets +/// mangled as it does not have a language linkage. GCC does not mangle +/// `resolver` or report a warning. +static int (*resolver(void))(void) { return f; } // expected-warning{{unused function 'resolver'}} +int ifunc(void) __attribute__((ifunc("resolver"))); + +static int __attribute__((overloadable)) f0(int x) { return x; } // expected-warning{{unused function 'f0'}} +static float __attribute__((overloadable)) f0(float x) { return x; } // expected-warning{{unused function 'f0'}} +int g0(void) __attribute__((alias("_ZL2f0i"))); + +#ifdef __cplusplus +static int f1() { return 42; } // expected-warning{{unused function 'f1'}} +int g1(void) __attribute__((alias("_ZL2f1v"))); +} + +static int f2(int) { return 42; } // expected-warning{{unused function 'f2'}} +static int f2() { return 42; } // expected-warning{{unused function 'f2'}} +int g2() __attribute__((alias("_ZL2f2v"))); + +static int (*resolver1())() { return f; } // expected-warning{{unused function 'resolver1'}} +static int (*resolver1(int))() { return f; } // expected-warning{{unused function 'resolver1'}} +int ifunc1() __attribute__((ifunc("_ZL9resolver1i"))); + +/// TODO: We should report "unused function" for f3(int). +namespace ns { +static int f3(int) { return 42; } // cxx-warning{{unused function 'f3'}} +static int f3() { return 42; } // cxx-warning{{unused function 'f3'}} +int g3() __attribute__((alias("_ZN2nsL2f3Ev"))); +} + +template +static void *f4(T) { return nullptr; } +static void *f4() { return nullptr; } // cxx-warning{{unused function 'f4'}} +extern void g4_int() __attribute__((ifunc("_ZL2f4IiEPvT_"))); +extern void g4_char() __attribute__((ifunc("_ZL2f4IcEPcT_"))); // rejected by CodeGen +void *use4 = f4(0); +#endif -- GitLab From 9e95c4947d31670ddd3abad1051eda06729c96b3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 13 Apr 2024 09:01:17 +0900 Subject: [PATCH 127/464] [DSE] Fix non-determinism due to address reuse (#84943) The malloc->calloc fold creates a new MemoryAccess, which may end of at the same address as a previously deleted access inside SkipStores. To the most part, this is not a problem, because SkipStores is normally only used together with MemDefs. Neither the old malloc access nor the new calloc access will be part of MemDefs, so there is no problem here. However, SkipStores is also used in one more place: In the main DSE loop, ToCheck entries are checked against it. Fix this by not using SkipStores here, and instead using a separate set to track deletions inside this loop. This way it is not affected by the calloc optimization that happens outside it. This is all pretty ugly, but I haven't found another good way to fix it. Suggestions welcome. No test case as I don't have a reliable DSE-only test-case for this. Fixes https://github.com/llvm/llvm-project/issues/84458. --- .../Scalar/DeadStoreElimination.cpp | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index bfc8bd5970bf..ed4212d29cef 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -1699,7 +1699,9 @@ struct DSEState { /// Delete dead memory defs and recursively add their operands to ToRemove if /// they became dead. - void deleteDeadInstruction(Instruction *SI) { + void + deleteDeadInstruction(Instruction *SI, + SmallPtrSetImpl *Deleted = nullptr) { MemorySSAUpdater Updater(&MSSA); SmallVector NowDeadInsts; NowDeadInsts.push_back(SI); @@ -1720,6 +1722,8 @@ struct DSEState { if (IsMemDef) { auto *MD = cast(MA); SkipStores.insert(MD); + if (Deleted) + Deleted->insert(MD); if (auto *SI = dyn_cast(MD->getMemoryInst())) { if (SI->getValueOperand()->getType()->isPointerTy()) { const Value *UO = getUnderlyingObject(SI->getValueOperand()); @@ -2168,6 +2172,11 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, unsigned PartialLimit = MemorySSAPartialStoreLimit; // Worklist of MemoryAccesses that may be killed by KillingDef. SmallSetVector ToCheck; + // Track MemoryAccesses that have been deleted in the loop below, so we can + // skip them. Don't use SkipStores for this, which may contain reused + // MemoryAccess addresses. + SmallPtrSet Deleted; + [[maybe_unused]] unsigned OrigNumSkipStores = State.SkipStores.size(); ToCheck.insert(KillingDef->getDefiningAccess()); bool Shortend = false; @@ -2175,7 +2184,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, // Check if MemoryAccesses in the worklist are killed by KillingDef. for (unsigned I = 0; I < ToCheck.size(); I++) { MemoryAccess *Current = ToCheck[I]; - if (State.SkipStores.count(Current)) + if (Deleted.contains(Current)) continue; std::optional MaybeDeadAccess = State.getDomMemoryDef( @@ -2222,7 +2231,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, continue; LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: " << *DeadI << "\n KILLER: " << *KillingI << '\n'); - State.deleteDeadInstruction(DeadI); + State.deleteDeadInstruction(DeadI, &Deleted); ++NumFastStores; MadeChange = true; } else { @@ -2259,7 +2268,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, Shortend = true; // Remove killing store and remove any outstanding overlap // intervals for the updated store. - State.deleteDeadInstruction(KillingSI); + State.deleteDeadInstruction(KillingSI, &Deleted); auto I = State.IOLs.find(DeadSI->getParent()); if (I != State.IOLs.end()) I->second.erase(DeadSI); @@ -2271,13 +2280,16 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, if (OR == OW_Complete) { LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: " << *DeadI << "\n KILLER: " << *KillingI << '\n'); - State.deleteDeadInstruction(DeadI); + State.deleteDeadInstruction(DeadI, &Deleted); ++NumFastStores; MadeChange = true; } } } + assert(State.SkipStores.size() - OrigNumSkipStores == Deleted.size() && + "SkipStores and Deleted out of sync?"); + // Check if the store is a no-op. if (!Shortend && State.storeIsNoop(KillingDef, KillingUndObj)) { LLVM_DEBUG(dbgs() << "DSE: Remove No-Op Store:\n DEAD: " << *KillingI -- GitLab From f172bfcdc229ed6f3e8a0298dab3713fb763ff28 Mon Sep 17 00:00:00 2001 From: Volodymyr Sapsai Date: Fri, 12 Apr 2024 18:27:40 -0700 Subject: [PATCH 128/464] [unused-includes][ADT] Don't include DJB.h as it's not used. NFC. (#88211) StringMap uses xxHash instead of DJB. --- llvm/include/llvm/ADT/StringMap.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h index 32e611467ac5..453d91349e35 100644 --- a/llvm/include/llvm/ADT/StringMap.h +++ b/llvm/include/llvm/ADT/StringMap.h @@ -17,7 +17,6 @@ #include "llvm/ADT/StringMapEntry.h" #include "llvm/ADT/iterator.h" #include "llvm/Support/AllocatorBase.h" -#include "llvm/Support/DJB.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include #include -- GitLab From f22c30063ddcb7f8e8c4fb0496f515be7f9408b8 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 12 Apr 2024 20:30:15 -0700 Subject: [PATCH 129/464] [test] alias-unused.cpp: set triple to Linux Otherwise the test would fail on Darwin and other platforms that use Itanium ABI but do not support alias/ifunc. --- clang/test/Sema/alias-unused.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Sema/alias-unused.cpp b/clang/test/Sema/alias-unused.cpp index 509d3e26225d..dc8e46f072d7 100644 --- a/clang/test/Sema/alias-unused.cpp +++ b/clang/test/Sema/alias-unused.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -Wunused -x c -verify %s -// RUN: %clang_cc1 -triple %itanium_abi_triple -Wunused -verify=expected,cxx %s +// RUN: %clang_cc1 -triple x86_64-linux -Wunused -x c -verify %s +// RUN: %clang_cc1 -triple x86_64-linux -Wunused -verify=expected,cxx %s #ifdef __cplusplus extern "C" { -- GitLab From aef28100294d04c2253a1cb8bbf552fa296dea4e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 12 Apr 2024 20:53:44 -0700 Subject: [PATCH 130/464] [ELF] Relocations: Avoid MIPS check for ELFCLASS64 with if constexpr. NFC After inlining, `scanSection` is significantly longer (more than 100+ instructions on x86-64 built with Clang) when `i` does not always increment by one (MIPS). --- lld/ELF/Relocations.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 55274344f881..04db413a6609 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1419,11 +1419,16 @@ template void RelocationScanner::scanOne(RelTy *&i) { uint32_t symIndex = rel.getSymbol(config->isMips64EL); Symbol &sym = sec->getFile()->getSymbol(symIndex); RelType type; - if (config->mipsN32Abi) { - type = getMipsN32RelType(i); - } else { + if constexpr (ELFT::Is64Bits) { type = rel.getType(config->isMips64EL); ++i; + } else { + if (config->mipsN32Abi) { + type = getMipsN32RelType(i); + } else { + type = rel.getType(config->isMips64EL); + ++i; + } } // Get an offset in an output section this relocation is applied to. uint64_t offset = getter.get(rel.r_offset); -- GitLab From 94b3c192d3468752e6bc2f20957d433bccdb8ff3 Mon Sep 17 00:00:00 2001 From: Jim Lin Date: Fri, 12 Apr 2024 23:39:30 -0500 Subject: [PATCH 131/464] [M68k][clang] Enable frame pointer optimization by default (#87264) Enable frame pointer optimization by default to match it with gcc. Fixes: https://github.com/llvm/llvm-project/issues/75013 --- clang/lib/Driver/ToolChains/CommonArgs.cpp | 1 + clang/test/Driver/frame-pointer-elim.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 62a53b85ce09..f10aa4dfaa9d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -114,6 +114,7 @@ static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args, case llvm::Triple::csky: case llvm::Triple::loongarch32: case llvm::Triple::loongarch64: + case llvm::Triple::m68k: return !clang::driver::tools::areOptimizationsEnabled(Args); default: break; diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c index 847c5b7b0b01..e1b0a468ab82 100644 --- a/clang/test/Driver/frame-pointer-elim.c +++ b/clang/test/Driver/frame-pointer-elim.c @@ -125,6 +125,12 @@ // RUN: %clang -### -target sparc64 -S -O1 %s 2>&1 | \ // RUN: FileCheck --check-prefix=KEEP-NONE %s +// M68k targets omit the frame pointer when optimizations are enabled. +// RUN: %clang -### -target m68k -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: %clang -### -target m68k -S -O1 %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-NONE %s + // For AAarch32 (A32, T32) linux targets, default omit frame pointer when // optimizations are enabled. // RUN: %clang -### -target arm-linux-gnueabihf- -marm -S %s 2>&1 | \ -- GitLab From 0a6f6df5b0c3d0f2a42f013bf5cafb9b5020dcac Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Sat, 13 Apr 2024 08:54:25 +0400 Subject: [PATCH 132/464] [clang] Introduce `SemaCUDA` (#88559) This patch moves CUDA-related `Sema` function into new `SemaCUDA` class, following the recent example of SYCL, OpenACC, and HLSL. This is a part of the effort to split Sema. Additional context can be found in https://github.com/llvm/llvm-project/pull/82217, https://github.com/llvm/llvm-project/pull/84184, https://github.com/llvm/llvm-project/pull/87634. --- clang/include/clang/Basic/Cuda.h | 8 + clang/include/clang/Sema/Sema.h | 304 +----------------- clang/include/clang/Sema/SemaBase.h | 2 +- clang/include/clang/Sema/SemaCUDA.h | 304 ++++++++++++++++++ clang/include/clang/Serialization/ASTReader.h | 2 +- clang/lib/Parse/ParseDecl.cpp | 4 +- clang/lib/Parse/ParseExpr.cpp | 7 +- clang/lib/Parse/ParsePragma.cpp | 5 +- clang/lib/Sema/Sema.cpp | 18 +- clang/lib/Sema/SemaBase.cpp | 5 +- clang/lib/Sema/SemaCUDA.cpp | 277 ++++++++-------- clang/lib/Sema/SemaDecl.cpp | 19 +- clang/lib/Sema/SemaDeclAttr.cpp | 12 +- clang/lib/Sema/SemaDeclCXX.cpp | 21 +- clang/lib/Sema/SemaExpr.cpp | 17 +- clang/lib/Sema/SemaExprCXX.cpp | 27 +- clang/lib/Sema/SemaLambda.cpp | 9 +- clang/lib/Sema/SemaOverload.cpp | 60 ++-- clang/lib/Sema/SemaStmt.cpp | 5 +- clang/lib/Sema/SemaTemplate.cpp | 15 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 +- clang/lib/Sema/SemaType.cpp | 9 +- clang/lib/Serialization/ASTReader.cpp | 5 +- clang/lib/Serialization/ASTWriter.cpp | 5 +- 24 files changed, 604 insertions(+), 539 deletions(-) create mode 100644 clang/include/clang/Sema/SemaCUDA.h diff --git a/clang/include/clang/Basic/Cuda.h b/clang/include/clang/Basic/Cuda.h index 3e77a74c7c00..acc6bb6581d8 100644 --- a/clang/include/clang/Basic/Cuda.h +++ b/clang/include/clang/Basic/Cuda.h @@ -126,6 +126,14 @@ enum class CudaArch { HIPDefault = CudaArch::GFX906, }; +enum class CUDAFunctionTarget { + Device, + Global, + Host, + HostDevice, + InvalidTarget +}; + static inline bool IsNVIDIAGpuArch(CudaArch A) { return A >= CudaArch::SM_20 && A < CudaArch::GFX600; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 00888b7f7a73..6b9789334811 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -38,6 +38,7 @@ #include "clang/AST/TypeOrdering.h" #include "clang/Basic/BitmaskEnum.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/Cuda.h" #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/ExpressionTraits.h" #include "clang/Basic/Module.h" @@ -183,6 +184,7 @@ class Preprocessor; class PseudoDestructorTypeStorage; class PseudoObjectExpr; class QualType; +class SemaCUDA; class SemaHLSL; class SemaOpenACC; class SemaSYCL; @@ -435,14 +437,6 @@ enum class CXXSpecialMemberKind { Invalid }; -enum class CUDAFunctionTarget { - Device, - Global, - Host, - HostDevice, - InvalidTarget -}; - /// Sema - This implements semantic analysis and AST building for C. /// \nosubgrouping class Sema final : public SemaBase { @@ -486,8 +480,7 @@ class Sema final : public SemaBase { // 35. Code Completion (SemaCodeComplete.cpp) // 36. FixIt Helpers (SemaFixItUtils.cpp) // 37. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) - // 38. CUDA (SemaCUDA.cpp) - // 39. OpenMP Directives and Clauses (SemaOpenMP.cpp) + // 38. OpenMP Directives and Clauses (SemaOpenMP.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -981,9 +974,19 @@ public: return DelayedDiagnostics.push(pool); } + /// Diagnostics that are emitted only if we discover that the given function + /// must be codegen'ed. Because handling these correctly adds overhead to + /// compilation, this is currently only enabled for CUDA compilations. + SemaDiagnosticBuilder::DeferredDiagnosticsType DeviceDeferredDiags; + /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; + SemaCUDA &CUDA() { + assert(CUDAPtr); + return *CUDAPtr; + } + SemaHLSL &HLSL() { assert(HLSLPtr); return *HLSLPtr; @@ -1029,6 +1032,7 @@ private: mutable IdentifierInfo *Ident_super; + std::unique_ptr CUDAPtr; std::unique_ptr HLSLPtr; std::unique_ptr OpenACCPtr; std::unique_ptr SYCLPtr; @@ -12908,258 +12912,6 @@ private: // // - /// \name CUDA - /// Implementations are in SemaCUDA.cpp - ///@{ - -public: - /// Increments our count of the number of times we've seen a pragma forcing - /// functions to be __host__ __device__. So long as this count is greater - /// than zero, all functions encountered will be __host__ __device__. - void PushForceCUDAHostDevice(); - - /// Decrements our count of the number of times we've seen a pragma forcing - /// functions to be __host__ __device__. Returns false if the count is 0 - /// before incrementing, so you can emit an error. - bool PopForceCUDAHostDevice(); - - ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, - MultiExprArg ExecConfig, - SourceLocation GGGLoc); - - /// Diagnostics that are emitted only if we discover that the given function - /// must be codegen'ed. Because handling these correctly adds overhead to - /// compilation, this is currently only enabled for CUDA compilations. - SemaDiagnosticBuilder::DeferredDiagnosticsType DeviceDeferredDiags; - - /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the - /// key in a hashtable, both the FD and location are hashed. - struct FunctionDeclAndLoc { - CanonicalDeclPtr FD; - SourceLocation Loc; - }; - - /// FunctionDecls and SourceLocations for which CheckCUDACall has emitted a - /// (maybe deferred) "bad call" diagnostic. We use this to avoid emitting the - /// same deferred diag twice. - llvm::DenseSet LocsWithCUDACallDiags; - - /// An inverse call graph, mapping known-emitted functions to one of their - /// known-emitted callers (plus the location of the call). - /// - /// Functions that we can tell a priori must be emitted aren't added to this - /// map. - llvm::DenseMap, - /* Caller = */ FunctionDeclAndLoc> - DeviceKnownEmittedFns; - - /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current - /// context is "used as device code". - /// - /// - If CurContext is a __host__ function, does not emit any diagnostics - /// unless \p EmitOnBothSides is true. - /// - If CurContext is a __device__ or __global__ function, emits the - /// diagnostics immediately. - /// - If CurContext is a __host__ __device__ function and we are compiling for - /// the device, creates a diagnostic which is emitted if and when we realize - /// that the function will be codegen'ed. - /// - /// Example usage: - /// - /// // Variable-length arrays are not allowed in CUDA device code. - /// if (CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) - /// << llvm::to_underlying(CurrentCUDATarget())) - /// return ExprError(); - /// // Otherwise, continue parsing as normal. - SemaDiagnosticBuilder CUDADiagIfDeviceCode(SourceLocation Loc, - unsigned DiagID); - - /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current - /// context is "used as host code". - /// - /// Same as CUDADiagIfDeviceCode, with "host" and "device" switched. - SemaDiagnosticBuilder CUDADiagIfHostCode(SourceLocation Loc, unsigned DiagID); - - /// Determines whether the given function is a CUDA device/host/kernel/etc. - /// function. - /// - /// Use this rather than examining the function's attributes yourself -- you - /// will get it wrong. Returns CUDAFunctionTarget::Host if D is null. - CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D, - bool IgnoreImplicitHDAttr = false); - CUDAFunctionTarget IdentifyCUDATarget(const ParsedAttributesView &Attrs); - - enum CUDAVariableTarget { - CVT_Device, /// Emitted on device side with a shadow variable on host side - CVT_Host, /// Emitted on host side only - CVT_Both, /// Emitted on both sides with different addresses - CVT_Unified, /// Emitted as a unified address, e.g. managed variables - }; - /// Determines whether the given variable is emitted on host or device side. - CUDAVariableTarget IdentifyCUDATarget(const VarDecl *D); - - /// Defines kinds of CUDA global host/device context where a function may be - /// called. - enum CUDATargetContextKind { - CTCK_Unknown, /// Unknown context - CTCK_InitGlobalVar, /// Function called during global variable - /// initialization - }; - - /// Define the current global CUDA host/device context where a function may be - /// called. Only used when a function is called outside of any functions. - struct CUDATargetContext { - CUDAFunctionTarget Target = CUDAFunctionTarget::HostDevice; - CUDATargetContextKind Kind = CTCK_Unknown; - Decl *D = nullptr; - } CurCUDATargetCtx; - - struct CUDATargetContextRAII { - Sema &S; - CUDATargetContext SavedCtx; - CUDATargetContextRAII(Sema &S_, CUDATargetContextKind K, Decl *D); - ~CUDATargetContextRAII() { S.CurCUDATargetCtx = SavedCtx; } - }; - - /// Gets the CUDA target for the current context. - CUDAFunctionTarget CurrentCUDATarget() { - return IdentifyCUDATarget(dyn_cast(CurContext)); - } - - static bool isCUDAImplicitHostDeviceFunction(const FunctionDecl *D); - - // CUDA function call preference. Must be ordered numerically from - // worst to best. - enum CUDAFunctionPreference { - CFP_Never, // Invalid caller/callee combination. - CFP_WrongSide, // Calls from host-device to host or device - // function that do not match current compilation - // mode. - CFP_HostDevice, // Any calls to host/device functions. - CFP_SameSide, // Calls from host-device to host or device - // function matching current compilation mode. - CFP_Native, // host-to-host or device-to-device calls. - }; - - /// Identifies relative preference of a given Caller/Callee - /// combination, based on their host/device attributes. - /// \param Caller function which needs address of \p Callee. - /// nullptr in case of global context. - /// \param Callee target function - /// - /// \returns preference value for particular Caller/Callee combination. - CUDAFunctionPreference IdentifyCUDAPreference(const FunctionDecl *Caller, - const FunctionDecl *Callee); - - /// Determines whether Caller may invoke Callee, based on their CUDA - /// host/device attributes. Returns false if the call is not allowed. - /// - /// Note: Will return true for CFP_WrongSide calls. These may appear in - /// semantically correct CUDA programs, but only if they're never codegen'ed. - bool IsAllowedCUDACall(const FunctionDecl *Caller, - const FunctionDecl *Callee) { - return IdentifyCUDAPreference(Caller, Callee) != CFP_Never; - } - - /// May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, - /// depending on FD and the current compilation settings. - void maybeAddCUDAHostDeviceAttrs(FunctionDecl *FD, - const LookupResult &Previous); - - /// May add implicit CUDAConstantAttr attribute to VD, depending on VD - /// and current compilation settings. - void MaybeAddCUDAConstantAttr(VarDecl *VD); - - /// Check whether we're allowed to call Callee from the current context. - /// - /// - If the call is never allowed in a semantically-correct program - /// (CFP_Never), emits an error and returns false. - /// - /// - If the call is allowed in semantically-correct programs, but only if - /// it's never codegen'ed (CFP_WrongSide), creates a deferred diagnostic to - /// be emitted if and when the caller is codegen'ed, and returns true. - /// - /// Will only create deferred diagnostics for a given SourceLocation once, - /// so you can safely call this multiple times without generating duplicate - /// deferred errors. - /// - /// - Otherwise, returns true without emitting any diagnostics. - bool CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee); - - void CUDACheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture); - - /// Set __device__ or __host__ __device__ attributes on the given lambda - /// operator() method. - /// - /// CUDA lambdas by default is host device function unless it has explicit - /// host or device attribute. - void CUDASetLambdaAttrs(CXXMethodDecl *Method); - - /// Record \p FD if it is a CUDA/HIP implicit host device function used on - /// device side in device compilation. - void CUDARecordImplicitHostDeviceFuncUsedByDevice(const FunctionDecl *FD); - - /// Finds a function in \p Matches with highest calling priority - /// from \p Caller context and erases all functions with lower - /// calling priority. - void EraseUnwantedCUDAMatches( - const FunctionDecl *Caller, - SmallVectorImpl> &Matches); - - /// Given a implicit special member, infer its CUDA target from the - /// calls it needs to make to underlying base/field special members. - /// \param ClassDecl the class for which the member is being created. - /// \param CSM the kind of special member. - /// \param MemberDecl the special member itself. - /// \param ConstRHS true if this is a copy operation with a const object on - /// its RHS. - /// \param Diagnose true if this call should emit diagnostics. - /// \return true if there was an error inferring. - /// The result of this call is implicit CUDA target attribute(s) attached to - /// the member declaration. - bool inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, - CXXSpecialMemberKind CSM, - CXXMethodDecl *MemberDecl, - bool ConstRHS, bool Diagnose); - - /// \return true if \p CD can be considered empty according to CUDA - /// (E.2.3.1 in CUDA 7.5 Programming guide). - bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD); - bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD); - - // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In - // case of error emits appropriate diagnostic and invalidates \p Var. - // - // \details CUDA allows only empty constructors as initializers for global - // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all - // __shared__ variables whether they are local or not (they all are implicitly - // static in CUDA). One exception is that CUDA allows constant initializers - // for __constant__ and __device__ variables. - void checkAllowedCUDAInitializer(VarDecl *VD); - - /// Check whether NewFD is a valid overload for CUDA. Emits - /// diagnostics and invalidates NewFD if not. - void checkCUDATargetOverload(FunctionDecl *NewFD, - const LookupResult &Previous); - /// Copies target attributes from the template TD to the function FD. - void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD); - - /// Returns the name of the launch configuration function. This is the name - /// of the function that will be called to configure kernel call, with the - /// parameters specified via <<<>>>. - std::string getCudaConfigureFuncName() const; - -private: - unsigned ForceCUDAHostDeviceDepth = 0; - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - /// \name OpenMP Directives and Clauses /// Implementations are in SemaOpenMP.cpp ///@{ @@ -14546,32 +14298,4 @@ std::unique_ptr CreateRISCVIntrinsicManager(Sema &S); } // end namespace clang -namespace llvm { -// Hash a FunctionDeclAndLoc by looking at both its FunctionDecl and its -// SourceLocation. -template <> struct DenseMapInfo { - using FunctionDeclAndLoc = clang::Sema::FunctionDeclAndLoc; - using FDBaseInfo = - DenseMapInfo>; - - static FunctionDeclAndLoc getEmptyKey() { - return {FDBaseInfo::getEmptyKey(), clang::SourceLocation()}; - } - - static FunctionDeclAndLoc getTombstoneKey() { - return {FDBaseInfo::getTombstoneKey(), clang::SourceLocation()}; - } - - static unsigned getHashValue(const FunctionDeclAndLoc &FDL) { - return hash_combine(FDBaseInfo::getHashValue(FDL.FD), - FDL.Loc.getHashValue()); - } - - static bool isEqual(const FunctionDeclAndLoc &LHS, - const FunctionDeclAndLoc &RHS) { - return LHS.FD == RHS.FD && LHS.Loc == RHS.Loc; - } -}; -} // namespace llvm - #endif diff --git a/clang/include/clang/Sema/SemaBase.h b/clang/include/clang/Sema/SemaBase.h index ff718022fca0..3220f71dd797 100644 --- a/clang/include/clang/Sema/SemaBase.h +++ b/clang/include/clang/Sema/SemaBase.h @@ -146,7 +146,7 @@ public: /// if (SemaDiagnosticBuilder(...) << foo << bar) /// return ExprError(); /// - /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably + /// But see DiagIfDeviceCode() and DiagIfHostCode() -- you probably /// want to use these instead of creating a SemaDiagnosticBuilder yourself. operator bool() const { return isImmediate(); } diff --git a/clang/include/clang/Sema/SemaCUDA.h b/clang/include/clang/Sema/SemaCUDA.h new file mode 100644 index 000000000000..63dc3f4da240 --- /dev/null +++ b/clang/include/clang/Sema/SemaCUDA.h @@ -0,0 +1,304 @@ +//===----- SemaCUDA.h ----- Semantic Analysis for CUDA constructs ---------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares semantic analysis for CUDA constructs. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMACUDA_H +#define LLVM_CLANG_SEMA_SEMACUDA_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Redeclarable.h" +#include "clang/Basic/Cuda.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/ParsedAttr.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaBase.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace clang { + +enum class CUDAFunctionTarget; + +class SemaCUDA : public SemaBase { +public: + SemaCUDA(Sema &S); + + /// Increments our count of the number of times we've seen a pragma forcing + /// functions to be __host__ __device__. So long as this count is greater + /// than zero, all functions encountered will be __host__ __device__. + void PushForceHostDevice(); + + /// Decrements our count of the number of times we've seen a pragma forcing + /// functions to be __host__ __device__. Returns false if the count is 0 + /// before incrementing, so you can emit an error. + bool PopForceHostDevice(); + + ExprResult ActOnExecConfigExpr(Scope *S, SourceLocation LLLLoc, + MultiExprArg ExecConfig, + SourceLocation GGGLoc); + + /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the + /// key in a hashtable, both the FD and location are hashed. + struct FunctionDeclAndLoc { + CanonicalDeclPtr FD; + SourceLocation Loc; + }; + + /// FunctionDecls and SourceLocations for which CheckCall has emitted a + /// (maybe deferred) "bad call" diagnostic. We use this to avoid emitting the + /// same deferred diag twice. + llvm::DenseSet LocsWithCUDACallDiags; + + /// An inverse call graph, mapping known-emitted functions to one of their + /// known-emitted callers (plus the location of the call). + /// + /// Functions that we can tell a priori must be emitted aren't added to this + /// map. + llvm::DenseMap, + /* Caller = */ FunctionDeclAndLoc> + DeviceKnownEmittedFns; + + /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current + /// context is "used as device code". + /// + /// - If CurContext is a __host__ function, does not emit any diagnostics + /// unless \p EmitOnBothSides is true. + /// - If CurContext is a __device__ or __global__ function, emits the + /// diagnostics immediately. + /// - If CurContext is a __host__ __device__ function and we are compiling for + /// the device, creates a diagnostic which is emitted if and when we realize + /// that the function will be codegen'ed. + /// + /// Example usage: + /// + /// // Variable-length arrays are not allowed in CUDA device code. + /// if (DiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentTarget()) + /// return ExprError(); + /// // Otherwise, continue parsing as normal. + SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID); + + /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current + /// context is "used as host code". + /// + /// Same as DiagIfDeviceCode, with "host" and "device" switched. + SemaDiagnosticBuilder DiagIfHostCode(SourceLocation Loc, unsigned DiagID); + + /// Determines whether the given function is a CUDA device/host/kernel/etc. + /// function. + /// + /// Use this rather than examining the function's attributes yourself -- you + /// will get it wrong. Returns CUDAFunctionTarget::Host if D is null. + CUDAFunctionTarget IdentifyTarget(const FunctionDecl *D, + bool IgnoreImplicitHDAttr = false); + CUDAFunctionTarget IdentifyTarget(const ParsedAttributesView &Attrs); + + enum CUDAVariableTarget { + CVT_Device, /// Emitted on device side with a shadow variable on host side + CVT_Host, /// Emitted on host side only + CVT_Both, /// Emitted on both sides with different addresses + CVT_Unified, /// Emitted as a unified address, e.g. managed variables + }; + /// Determines whether the given variable is emitted on host or device side. + CUDAVariableTarget IdentifyTarget(const VarDecl *D); + + /// Defines kinds of CUDA global host/device context where a function may be + /// called. + enum CUDATargetContextKind { + CTCK_Unknown, /// Unknown context + CTCK_InitGlobalVar, /// Function called during global variable + /// initialization + }; + + /// Define the current global CUDA host/device context where a function may be + /// called. Only used when a function is called outside of any functions. + struct CUDATargetContext { + CUDAFunctionTarget Target = CUDAFunctionTarget::HostDevice; + CUDATargetContextKind Kind = CTCK_Unknown; + Decl *D = nullptr; + } CurCUDATargetCtx; + + struct CUDATargetContextRAII { + SemaCUDA &S; + SemaCUDA::CUDATargetContext SavedCtx; + CUDATargetContextRAII(SemaCUDA &S_, SemaCUDA::CUDATargetContextKind K, + Decl *D); + ~CUDATargetContextRAII() { S.CurCUDATargetCtx = SavedCtx; } + }; + + /// Gets the CUDA target for the current context. + CUDAFunctionTarget CurrentTarget() { + return IdentifyTarget(dyn_cast(SemaRef.CurContext)); + } + + static bool isImplicitHostDeviceFunction(const FunctionDecl *D); + + // CUDA function call preference. Must be ordered numerically from + // worst to best. + enum CUDAFunctionPreference { + CFP_Never, // Invalid caller/callee combination. + CFP_WrongSide, // Calls from host-device to host or device + // function that do not match current compilation + // mode. + CFP_HostDevice, // Any calls to host/device functions. + CFP_SameSide, // Calls from host-device to host or device + // function matching current compilation mode. + CFP_Native, // host-to-host or device-to-device calls. + }; + + /// Identifies relative preference of a given Caller/Callee + /// combination, based on their host/device attributes. + /// \param Caller function which needs address of \p Callee. + /// nullptr in case of global context. + /// \param Callee target function + /// + /// \returns preference value for particular Caller/Callee combination. + CUDAFunctionPreference IdentifyPreference(const FunctionDecl *Caller, + const FunctionDecl *Callee); + + /// Determines whether Caller may invoke Callee, based on their CUDA + /// host/device attributes. Returns false if the call is not allowed. + /// + /// Note: Will return true for CFP_WrongSide calls. These may appear in + /// semantically correct CUDA programs, but only if they're never codegen'ed. + bool IsAllowedCall(const FunctionDecl *Caller, const FunctionDecl *Callee) { + return IdentifyPreference(Caller, Callee) != CFP_Never; + } + + /// May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, + /// depending on FD and the current compilation settings. + void maybeAddHostDeviceAttrs(FunctionDecl *FD, const LookupResult &Previous); + + /// May add implicit CUDAConstantAttr attribute to VD, depending on VD + /// and current compilation settings. + void MaybeAddConstantAttr(VarDecl *VD); + + /// Check whether we're allowed to call Callee from the current context. + /// + /// - If the call is never allowed in a semantically-correct program + /// (CFP_Never), emits an error and returns false. + /// + /// - If the call is allowed in semantically-correct programs, but only if + /// it's never codegen'ed (CFP_WrongSide), creates a deferred diagnostic to + /// be emitted if and when the caller is codegen'ed, and returns true. + /// + /// Will only create deferred diagnostics for a given SourceLocation once, + /// so you can safely call this multiple times without generating duplicate + /// deferred errors. + /// + /// - Otherwise, returns true without emitting any diagnostics. + bool CheckCall(SourceLocation Loc, FunctionDecl *Callee); + + void CheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture); + + /// Set __device__ or __host__ __device__ attributes on the given lambda + /// operator() method. + /// + /// CUDA lambdas by default is host device function unless it has explicit + /// host or device attribute. + void SetLambdaAttrs(CXXMethodDecl *Method); + + /// Record \p FD if it is a CUDA/HIP implicit host device function used on + /// device side in device compilation. + void RecordImplicitHostDeviceFuncUsedByDevice(const FunctionDecl *FD); + + /// Finds a function in \p Matches with highest calling priority + /// from \p Caller context and erases all functions with lower + /// calling priority. + void EraseUnwantedMatches( + const FunctionDecl *Caller, + llvm::SmallVectorImpl> + &Matches); + + /// Given a implicit special member, infer its CUDA target from the + /// calls it needs to make to underlying base/field special members. + /// \param ClassDecl the class for which the member is being created. + /// \param CSM the kind of special member. + /// \param MemberDecl the special member itself. + /// \param ConstRHS true if this is a copy operation with a const object on + /// its RHS. + /// \param Diagnose true if this call should emit diagnostics. + /// \return true if there was an error inferring. + /// The result of this call is implicit CUDA target attribute(s) attached to + /// the member declaration. + bool inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, + CXXSpecialMemberKind CSM, + CXXMethodDecl *MemberDecl, + bool ConstRHS, bool Diagnose); + + /// \return true if \p CD can be considered empty according to CUDA + /// (E.2.3.1 in CUDA 7.5 Programming guide). + bool isEmptyConstructor(SourceLocation Loc, CXXConstructorDecl *CD); + bool isEmptyDestructor(SourceLocation Loc, CXXDestructorDecl *CD); + + // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In + // case of error emits appropriate diagnostic and invalidates \p Var. + // + // \details CUDA allows only empty constructors as initializers for global + // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all + // __shared__ variables whether they are local or not (they all are implicitly + // static in CUDA). One exception is that CUDA allows constant initializers + // for __constant__ and __device__ variables. + void checkAllowedInitializer(VarDecl *VD); + + /// Check whether NewFD is a valid overload for CUDA. Emits + /// diagnostics and invalidates NewFD if not. + void checkTargetOverload(FunctionDecl *NewFD, const LookupResult &Previous); + /// Copies target attributes from the template TD to the function FD. + void inheritTargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD); + + /// Returns the name of the launch configuration function. This is the name + /// of the function that will be called to configure kernel call, with the + /// parameters specified via <<<>>>. + std::string getConfigureFuncName() const; + +private: + unsigned ForceHostDeviceDepth = 0; + + friend class ASTReader; + friend class ASTWriter; +}; + +} // namespace clang + +namespace llvm { +// Hash a FunctionDeclAndLoc by looking at both its FunctionDecl and its +// SourceLocation. +template <> struct DenseMapInfo { + using FunctionDeclAndLoc = clang::SemaCUDA::FunctionDeclAndLoc; + using FDBaseInfo = + DenseMapInfo>; + + static FunctionDeclAndLoc getEmptyKey() { + return {FDBaseInfo::getEmptyKey(), clang::SourceLocation()}; + } + + static FunctionDeclAndLoc getTombstoneKey() { + return {FDBaseInfo::getTombstoneKey(), clang::SourceLocation()}; + } + + static unsigned getHashValue(const FunctionDeclAndLoc &FDL) { + return hash_combine(FDBaseInfo::getHashValue(FDL.FD), + FDL.Loc.getHashValue()); + } + + static bool isEqual(const FunctionDeclAndLoc &LHS, + const FunctionDeclAndLoc &RHS) { + return LHS.FD == RHS.FD && LHS.Loc == RHS.Loc; + } +}; +} // namespace llvm + +#endif // LLVM_CLANG_SEMA_SEMACUDA_H diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 6656c1c58dec..e3fde887f99c 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -873,7 +873,7 @@ private: /// Our current depth in #pragma cuda force_host_device begin/end /// macros. - unsigned ForceCUDAHostDeviceDepth = 0; + unsigned ForceHostDeviceDepth = 0; /// The IDs of the declarations Sema stores directly. /// diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 583232f2d610..951e2210031a 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -26,6 +26,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" @@ -2664,7 +2665,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( } } - Sema::CUDATargetContextRAII X(Actions, Sema::CTCK_InitGlobalVar, ThisDecl); + SemaCUDA::CUDATargetContextRAII X(Actions.CUDA(), + SemaCUDA::CTCK_InitGlobalVar, ThisDecl); switch (TheInitKind) { // Parse declarator '=' initializer. case InitKind::Equal: { diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index d08e675604d1..473ec9afd601 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -30,6 +30,7 @@ #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaSYCL.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/SmallVector.h" @@ -2129,10 +2130,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } if (!LHS.isInvalid()) { - ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(), - OpenLoc, - ExecConfigExprs, - CloseLoc); + ExprResult ECResult = Actions.CUDA().ActOnExecConfigExpr( + getCurScope(), OpenLoc, ExecConfigExprs, CloseLoc); if (ECResult.isInvalid()) LHS = ExprError(); else diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 0f692e2146a4..3979f75b6020 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -21,6 +21,7 @@ #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCUDA.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSwitch.h" #include @@ -3900,8 +3901,8 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma( } if (Info->isStr("begin")) - Actions.PushForceCUDAHostDevice(); - else if (!Actions.PopForceCUDAHostDevice()) + Actions.CUDA().PushForceHostDevice(); + else if (!Actions.CUDA().PopForceHostDevice()) PP.Diag(FirstTok.getLocation(), diag::err_pragma_cannot_end_force_cuda_host_device); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index a2ea66f339c8..8de202f4f7a0 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -41,6 +41,7 @@ #include "clang/Sema/RISCVIntrinsicManager.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" @@ -199,6 +200,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr), CurScope(nullptr), Ident_super(nullptr), + CUDAPtr(std::make_unique(*this)), HLSLPtr(std::make_unique(*this)), OpenACCPtr(std::make_unique(*this)), SYCLPtr(std::make_unique(*this)), @@ -1635,15 +1637,15 @@ bool Sema::hasUncompilableErrorOccurred() const { // Print notes showing how we can reach FD starting from an a priori // known-callable function. static void emitCallStackNotes(Sema &S, const FunctionDecl *FD) { - auto FnIt = S.DeviceKnownEmittedFns.find(FD); - while (FnIt != S.DeviceKnownEmittedFns.end()) { + auto FnIt = S.CUDA().DeviceKnownEmittedFns.find(FD); + while (FnIt != S.CUDA().DeviceKnownEmittedFns.end()) { // Respect error limit. if (S.Diags.hasFatalErrorOccurred()) return; DiagnosticBuilder Builder( S.Diags.Report(FnIt->second.Loc, diag::note_called_by)); Builder << FnIt->second.FD; - FnIt = S.DeviceKnownEmittedFns.find(FnIt->second.FD); + FnIt = S.CUDA().DeviceKnownEmittedFns.find(FnIt->second.FD); } } @@ -1747,7 +1749,7 @@ public: (ShouldEmitRootNode || InOMPDeviceContext)) S.finalizeOpenMPDelayedAnalysis(Caller, FD, Loc); if (Caller) - S.DeviceKnownEmittedFns[FD] = {Caller, Loc}; + S.CUDA().DeviceKnownEmittedFns[FD] = {Caller, Loc}; // Always emit deferred diagnostics for the direct users. This does not // lead to explosion of diagnostics since each user is visited at most // twice. @@ -1836,8 +1838,8 @@ void Sema::emitDeferredDiags() { // which other not-known-emitted functions. // // When we see something which is illegal if the current function is emitted -// (usually by way of CUDADiagIfDeviceCode, CUDADiagIfHostCode, or -// CheckCUDACall), we first check if the current function is known-emitted. If +// (usually by way of DiagIfDeviceCode, DiagIfHostCode, or +// CheckCall), we first check if the current function is known-emitted. If // so, we immediately output the diagnostic. // // Otherwise, we "defer" the diagnostic. It sits in Sema::DeviceDeferredDiags @@ -1900,8 +1902,8 @@ Sema::targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD) { ? diagIfOpenMPDeviceCode(Loc, DiagID, FD) : diagIfOpenMPHostCode(Loc, DiagID, FD); if (getLangOpts().CUDA) - return getLangOpts().CUDAIsDevice ? CUDADiagIfDeviceCode(Loc, DiagID) - : CUDADiagIfHostCode(Loc, DiagID); + return getLangOpts().CUDAIsDevice ? CUDA().DiagIfDeviceCode(Loc, DiagID) + : CUDA().DiagIfHostCode(Loc, DiagID); if (getLangOpts().SYCLIsDevice) return SYCL().DiagIfDeviceCode(Loc, DiagID); diff --git a/clang/lib/Sema/SemaBase.cpp b/clang/lib/Sema/SemaBase.cpp index 95c0cfbe283b..0442fb2929e3 100644 --- a/clang/lib/Sema/SemaBase.cpp +++ b/clang/lib/Sema/SemaBase.cpp @@ -1,5 +1,6 @@ #include "clang/Sema/SemaBase.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCUDA.h" namespace clang { @@ -70,8 +71,8 @@ Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc, unsigned DiagID, } SemaDiagnosticBuilder DB = getLangOpts().CUDAIsDevice - ? SemaRef.CUDADiagIfDeviceCode(Loc, DiagID) - : SemaRef.CUDADiagIfHostCode(Loc, DiagID); + ? SemaRef.CUDA().DiagIfDeviceCode(Loc, DiagID) + : SemaRef.CUDA().DiagIfHostCode(Loc, DiagID); SetIsLastErrorImmediate(DB.isImmediate()); return DB; } diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index 9d6d709e262a..80ea43dc5316 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -10,6 +10,7 @@ /// //===----------------------------------------------------------------------===// +#include "clang/Sema/SemaCUDA.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/ExprCXX.h" @@ -27,6 +28,8 @@ #include using namespace clang; +SemaCUDA::SemaCUDA(Sema &S) : SemaBase(S) {} + template static bool hasExplicitAttr(const VarDecl *D) { if (!D) return false; @@ -35,37 +38,37 @@ template static bool hasExplicitAttr(const VarDecl *D) { return false; } -void Sema::PushForceCUDAHostDevice() { +void SemaCUDA::PushForceHostDevice() { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - ForceCUDAHostDeviceDepth++; + ForceHostDeviceDepth++; } -bool Sema::PopForceCUDAHostDevice() { +bool SemaCUDA::PopForceHostDevice() { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - if (ForceCUDAHostDeviceDepth == 0) + if (ForceHostDeviceDepth == 0) return false; - ForceCUDAHostDeviceDepth--; + ForceHostDeviceDepth--; return true; } -ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, +ExprResult SemaCUDA::ActOnExecConfigExpr(Scope *S, SourceLocation LLLLoc, MultiExprArg ExecConfig, SourceLocation GGGLoc) { - FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl(); + FunctionDecl *ConfigDecl = getASTContext().getcudaConfigureCallDecl(); if (!ConfigDecl) return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use) - << getCudaConfigureFuncName()); + << getConfigureFuncName()); QualType ConfigQTy = ConfigDecl->getType(); - DeclRefExpr *ConfigDR = new (Context) - DeclRefExpr(Context, ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc); - MarkFunctionReferenced(LLLLoc, ConfigDecl); + DeclRefExpr *ConfigDR = new (getASTContext()) DeclRefExpr( + getASTContext(), ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc); + SemaRef.MarkFunctionReferenced(LLLLoc, ConfigDecl); - return BuildCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr, - /*IsExecConfig=*/true); + return SemaRef.BuildCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr, + /*IsExecConfig=*/true); } -CUDAFunctionTarget Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { +CUDAFunctionTarget SemaCUDA::IdentifyTarget(const ParsedAttributesView &Attrs) { bool HasHostAttr = false; bool HasDeviceAttr = false; bool HasGlobalAttr = false; @@ -112,12 +115,11 @@ static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr) { }); } -Sema::CUDATargetContextRAII::CUDATargetContextRAII(Sema &S_, - CUDATargetContextKind K, - Decl *D) +SemaCUDA::CUDATargetContextRAII::CUDATargetContextRAII( + SemaCUDA &S_, SemaCUDA::CUDATargetContextKind K, Decl *D) : S(S_) { SavedCtx = S.CurCUDATargetCtx; - assert(K == CTCK_InitGlobalVar); + assert(K == SemaCUDA::CTCK_InitGlobalVar); auto *VD = dyn_cast_or_null(D); if (VD && VD->hasGlobalStorage() && !VD->isStaticLocal()) { auto Target = CUDAFunctionTarget::Host; @@ -130,8 +132,8 @@ Sema::CUDATargetContextRAII::CUDATargetContextRAII(Sema &S_, } } -/// IdentifyCUDATarget - Determine the CUDA compilation target for this function -CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D, +/// IdentifyTarget - Determine the CUDA compilation target for this function +CUDAFunctionTarget SemaCUDA::IdentifyTarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr) { // Code that lives outside a function gets the target from CurCUDATargetCtx. if (D == nullptr) @@ -160,7 +162,7 @@ CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D, } /// IdentifyTarget - Determine the CUDA compilation target for this variable. -Sema::CUDAVariableTarget Sema::IdentifyCUDATarget(const VarDecl *Var) { +SemaCUDA::CUDAVariableTarget SemaCUDA::IdentifyTarget(const VarDecl *Var) { if (Var->hasAttr()) return CVT_Unified; // Only constexpr and const variabless with implicit constant attribute @@ -180,7 +182,7 @@ Sema::CUDAVariableTarget Sema::IdentifyCUDATarget(const VarDecl *Var) { // - on both sides in host device functions // - on device side in device or global functions if (auto *FD = dyn_cast(Var->getDeclContext())) { - switch (IdentifyCUDATarget(FD)) { + switch (IdentifyTarget(FD)) { case CUDAFunctionTarget::HostDevice: return CVT_Both; case CUDAFunctionTarget::Device: @@ -221,21 +223,21 @@ Sema::CUDAVariableTarget Sema::IdentifyCUDATarget(const VarDecl *Var) { // | hd | h | SS | WS | (d) | // | hd | hd | HD | HD | (b) | -Sema::CUDAFunctionPreference -Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, +SemaCUDA::CUDAFunctionPreference +SemaCUDA::IdentifyPreference(const FunctionDecl *Caller, const FunctionDecl *Callee) { assert(Callee && "Callee must be valid."); // Treat ctor/dtor as host device function in device var initializer to allow // trivial ctor/dtor without device attr to be used. Non-trivial ctor/dtor - // will be diagnosed by checkAllowedCUDAInitializer. + // will be diagnosed by checkAllowedInitializer. if (Caller == nullptr && CurCUDATargetCtx.Kind == CTCK_InitGlobalVar && CurCUDATargetCtx.Target == CUDAFunctionTarget::Device && (isa(Callee) || isa(Callee))) return CFP_HostDevice; - CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller); - CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee); + CUDAFunctionTarget CallerTarget = IdentifyTarget(Caller); + CUDAFunctionTarget CalleeTarget = IdentifyTarget(Callee); // If one of the targets is invalid, the check always fails, no matter what // the other target is. @@ -309,13 +311,13 @@ template static bool hasImplicitAttr(const FunctionDecl *D) { return D->isImplicit(); } -bool Sema::isCUDAImplicitHostDeviceFunction(const FunctionDecl *D) { +bool SemaCUDA::isImplicitHostDeviceFunction(const FunctionDecl *D) { bool IsImplicitDevAttr = hasImplicitAttr(D); bool IsImplicitHostAttr = hasImplicitAttr(D); return IsImplicitDevAttr && IsImplicitHostAttr; } -void Sema::EraseUnwantedCUDAMatches( +void SemaCUDA::EraseUnwantedMatches( const FunctionDecl *Caller, SmallVectorImpl> &Matches) { if (Matches.size() <= 1) @@ -325,7 +327,7 @@ void Sema::EraseUnwantedCUDAMatches( // Gets the CUDA function preference for a call from Caller to Match. auto GetCFP = [&](const Pair &Match) { - return IdentifyCUDAPreference(Caller, Match.second); + return IdentifyPreference(Caller, Match.second); }; // Find the best call preference among the functions in Matches. @@ -367,7 +369,7 @@ resolveCalleeCUDATargetConflict(CUDAFunctionTarget Target1, return false; } -bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, +bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, CXXSpecialMemberKind CSM, CXXMethodDecl *MemberDecl, bool ConstRHS, @@ -388,7 +390,7 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, // We're going to invoke special member lookup; mark that these special // members are called from this one, and not from its caller. - ContextRAII MethodContext(*this, MemberDecl); + Sema::ContextRAII MethodContext(SemaRef, MemberDecl); // Look for special members in base classes that should be invoked from here. // Infer the target of this member base on the ones it should call. @@ -412,17 +414,17 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); Sema::SpecialMemberOverloadResult SMOR = - LookupSpecialMember(BaseClassDecl, CSM, - /* ConstArg */ ConstRHS, - /* VolatileArg */ false, - /* RValueThis */ false, - /* ConstThis */ false, - /* VolatileThis */ false); + SemaRef.LookupSpecialMember(BaseClassDecl, CSM, + /* ConstArg */ ConstRHS, + /* VolatileArg */ false, + /* RValueThis */ false, + /* ConstThis */ false, + /* VolatileThis */ false); if (!SMOR.getMethod()) continue; - CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR.getMethod()); + CUDAFunctionTarget BaseMethodTarget = IdentifyTarget(SMOR.getMethod()); if (!InferredTarget) { InferredTarget = BaseMethodTarget; } else { @@ -435,7 +437,8 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, << (unsigned)CSM << llvm::to_underlying(*InferredTarget) << llvm::to_underlying(BaseMethodTarget); } - MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context)); + MemberDecl->addAttr( + CUDAInvalidTargetAttr::CreateImplicit(getASTContext())); return true; } } @@ -448,25 +451,24 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, } const RecordType *FieldType = - Context.getBaseElementType(F->getType())->getAs(); + getASTContext().getBaseElementType(F->getType())->getAs(); if (!FieldType) { continue; } CXXRecordDecl *FieldRecDecl = cast(FieldType->getDecl()); Sema::SpecialMemberOverloadResult SMOR = - LookupSpecialMember(FieldRecDecl, CSM, - /* ConstArg */ ConstRHS && !F->isMutable(), - /* VolatileArg */ false, - /* RValueThis */ false, - /* ConstThis */ false, - /* VolatileThis */ false); + SemaRef.LookupSpecialMember(FieldRecDecl, CSM, + /* ConstArg */ ConstRHS && !F->isMutable(), + /* VolatileArg */ false, + /* RValueThis */ false, + /* ConstThis */ false, + /* VolatileThis */ false); if (!SMOR.getMethod()) continue; - CUDAFunctionTarget FieldMethodTarget = - IdentifyCUDATarget(SMOR.getMethod()); + CUDAFunctionTarget FieldMethodTarget = IdentifyTarget(SMOR.getMethod()); if (!InferredTarget) { InferredTarget = FieldMethodTarget; } else { @@ -479,7 +481,8 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, << (unsigned)CSM << llvm::to_underlying(*InferredTarget) << llvm::to_underlying(FieldMethodTarget); } - MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context)); + MemberDecl->addAttr( + CUDAInvalidTargetAttr::CreateImplicit(getASTContext())); return true; } } @@ -499,16 +502,16 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, // We either setting attributes first time, or the inferred ones must match // previously set ones. if (NeedsD && !HasD) - MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context)); + MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); if (NeedsH && !HasH) - MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context)); + MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); return false; } -bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) { +bool SemaCUDA::isEmptyConstructor(SourceLocation Loc, CXXConstructorDecl *CD) { if (!CD->isDefined() && CD->isTemplateInstantiation()) - InstantiateFunctionDefinition(Loc, CD->getFirstDecl()); + SemaRef.InstantiateFunctionDefinition(Loc, CD->getFirstDecl()); // (E.2.3.1, CUDA 7.5) A constructor for a class type is considered // empty at a point in the translation unit, if it is either a @@ -536,7 +539,7 @@ bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) { if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) { if (const CXXConstructExpr *CE = dyn_cast(CI->getInit())) - return isEmptyCudaConstructor(Loc, CE->getConstructor()); + return isEmptyConstructor(Loc, CE->getConstructor()); return false; })) return false; @@ -544,13 +547,13 @@ bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) { return true; } -bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { +bool SemaCUDA::isEmptyDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { // No destructor -> no problem. if (!DD) return true; if (!DD->isDefined() && DD->isTemplateInstantiation()) - InstantiateFunctionDefinition(Loc, DD->getFirstDecl()); + SemaRef.InstantiateFunctionDefinition(Loc, DD->getFirstDecl()); // (E.2.3.1, CUDA 7.5) A destructor for a class type is considered // empty at a point in the translation unit, if it is either a @@ -579,7 +582,7 @@ bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { // destructors for all base classes... if (!llvm::all_of(ClassDecl->bases(), [&](const CXXBaseSpecifier &BS) { if (CXXRecordDecl *RD = BS.getType()->getAsCXXRecordDecl()) - return isEmptyCudaDestructor(Loc, RD->getDestructor()); + return isEmptyDestructor(Loc, RD->getDestructor()); return true; })) return false; @@ -589,7 +592,7 @@ bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { if (CXXRecordDecl *RD = Field->getType() ->getBaseElementTypeUnsafe() ->getAsCXXRecordDecl()) - return isEmptyCudaDestructor(Loc, RD->getDestructor()); + return isEmptyDestructor(Loc, RD->getDestructor()); return true; })) return false; @@ -620,7 +623,7 @@ bool IsDependentVar(VarDecl *VD) { // __shared__ variables whether they are local or not (they all are implicitly // static in CUDA). One exception is that CUDA allows constant initializers // for __constant__ and __device__ variables. -bool HasAllowedCUDADeviceStaticInitializer(Sema &S, VarDecl *VD, +bool HasAllowedCUDADeviceStaticInitializer(SemaCUDA &S, VarDecl *VD, CUDAInitializerCheckKind CheckKind) { assert(!VD->isInvalidDecl() && VD->hasGlobalStorage()); assert(!IsDependentVar(VD) && "do not check dependent var"); @@ -629,30 +632,30 @@ bool HasAllowedCUDADeviceStaticInitializer(Sema &S, VarDecl *VD, if (!Init) return true; if (const auto *CE = dyn_cast(Init)) { - return S.isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor()); + return S.isEmptyConstructor(VD->getLocation(), CE->getConstructor()); } return false; }; auto IsConstantInit = [&](const Expr *Init) { assert(Init); - ASTContext::CUDAConstantEvalContextRAII EvalCtx(S.Context, + ASTContext::CUDAConstantEvalContextRAII EvalCtx(S.getASTContext(), /*NoWronSidedVars=*/true); - return Init->isConstantInitializer(S.Context, + return Init->isConstantInitializer(S.getASTContext(), VD->getType()->isReferenceType()); }; auto HasEmptyDtor = [&](VarDecl *VD) { if (const auto *RD = VD->getType()->getAsCXXRecordDecl()) - return S.isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor()); + return S.isEmptyDestructor(VD->getLocation(), RD->getDestructor()); return true; }; if (CheckKind == CICK_Shared) return IsEmptyInit(Init) && HasEmptyDtor(VD); - return S.LangOpts.GPUAllowDeviceInit || + return S.getLangOpts().GPUAllowDeviceInit || ((IsEmptyInit(Init) || IsConstantInit(Init)) && HasEmptyDtor(VD)); } } // namespace -void Sema::checkAllowedCUDAInitializer(VarDecl *VD) { +void SemaCUDA::checkAllowedInitializer(VarDecl *VD) { // Return early if VD is inside a non-instantiated template function since // the implicit constructor is not defined yet. if (const FunctionDecl *FD = @@ -688,7 +691,7 @@ void Sema::checkAllowedCUDAInitializer(VarDecl *VD) { InitFn = CE->getDirectCallee(); } if (InitFn) { - CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn); + CUDAFunctionTarget InitFnTarget = IdentifyTarget(InitFn); if (InitFnTarget != CUDAFunctionTarget::Host && InitFnTarget != CUDAFunctionTarget::HostDevice) { Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer) @@ -700,22 +703,22 @@ void Sema::checkAllowedCUDAInitializer(VarDecl *VD) { } } -void Sema::CUDARecordImplicitHostDeviceFuncUsedByDevice( +void SemaCUDA::RecordImplicitHostDeviceFuncUsedByDevice( const FunctionDecl *Callee) { - FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *Caller = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); if (!Caller) return; - if (!isCUDAImplicitHostDeviceFunction(Callee)) + if (!isImplicitHostDeviceFunction(Callee)) return; - CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller); + CUDAFunctionTarget CallerTarget = IdentifyTarget(Caller); // Record whether an implicit host device function is used on device side. if (CallerTarget != CUDAFunctionTarget::Device && CallerTarget != CUDAFunctionTarget::Global && (CallerTarget != CUDAFunctionTarget::HostDevice || - (isCUDAImplicitHostDeviceFunction(Caller) && + (isImplicitHostDeviceFunction(Caller) && !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(Caller)))) return; @@ -731,18 +734,18 @@ void Sema::CUDARecordImplicitHostDeviceFuncUsedByDevice( // system header, in which case we leave the constexpr function unattributed. // // In addition, all function decls are treated as __host__ __device__ when -// ForceCUDAHostDeviceDepth > 0 (corresponding to code within a +// ForceHostDeviceDepth > 0 (corresponding to code within a // #pragma clang force_cuda_host_device_begin/end // pair). -void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, +void SemaCUDA::maybeAddHostDeviceAttrs(FunctionDecl *NewD, const LookupResult &Previous) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - if (ForceCUDAHostDeviceDepth > 0) { + if (ForceHostDeviceDepth > 0) { if (!NewD->hasAttr()) - NewD->addAttr(CUDAHostAttr::CreateImplicit(Context)); + NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); if (!NewD->hasAttr()) - NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context)); + NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); return; } @@ -753,8 +756,8 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, !NewD->hasAttr() && (NewD->getDescribedFunctionTemplate() || NewD->isFunctionTemplateSpecialization())) { - NewD->addAttr(CUDAHostAttr::CreateImplicit(Context)); - NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context)); + NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); + NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); return; } @@ -771,8 +774,9 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, FunctionDecl *OldD = D->getAsFunction(); return OldD && OldD->hasAttr() && !OldD->hasAttr() && - !IsOverload(NewD, OldD, /* UseMemberUsingDeclRules = */ false, - /* ConsiderCudaAttrs = */ false); + !SemaRef.IsOverload(NewD, OldD, + /* UseMemberUsingDeclRules = */ false, + /* ConsiderCudaAttrs = */ false); }; auto It = llvm::find_if(Previous, IsMatchingDeviceFn); if (It != Previous.end()) { @@ -781,7 +785,7 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, // in a system header, in which case we simply return without making NewD // host+device. NamedDecl *Match = *It; - if (!getSourceManager().isInSystemHeader(Match->getLocation())) { + if (!SemaRef.getSourceManager().isInSystemHeader(Match->getLocation())) { Diag(NewD->getLocation(), diag::err_cuda_unattributed_constexpr_cannot_overload_device) << NewD; @@ -791,14 +795,14 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, return; } - NewD->addAttr(CUDAHostAttr::CreateImplicit(Context)); - NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context)); + NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); + NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); } // TODO: `__constant__` memory may be a limited resource for certain targets. // A safeguard may be needed at the end of compilation pipeline if // `__constant__` memory usage goes beyond limit. -void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) { +void SemaCUDA::MaybeAddConstantAttr(VarDecl *VD) { // Do not promote dependent variables since the cotr/dtor/initializer are // not determined. Do it after instantiation. if (getLangOpts().CUDAIsDevice && !VD->hasAttr() && @@ -812,14 +816,15 @@ void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) { } } -Sema::SemaDiagnosticBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc, - unsigned DiagID) { +SemaBase::SemaDiagnosticBuilder SemaCUDA::DiagIfDeviceCode(SourceLocation Loc, + unsigned DiagID) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - FunctionDecl *CurFunContext = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *CurFunContext = + SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); SemaDiagnosticBuilder::Kind DiagKind = [&] { if (!CurFunContext) return SemaDiagnosticBuilder::K_Nop; - switch (CurrentCUDATarget()) { + switch (CurrentTarget()) { case CUDAFunctionTarget::Global: case CUDAFunctionTarget::Device: return SemaDiagnosticBuilder::K_Immediate; @@ -829,27 +834,29 @@ Sema::SemaDiagnosticBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc, // mode until the function is known-emitted. if (!getLangOpts().CUDAIsDevice) return SemaDiagnosticBuilder::K_Nop; - if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID)) + if (SemaRef.IsLastErrorImmediate && + getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID)) return SemaDiagnosticBuilder::K_Immediate; - return (getEmissionStatus(CurFunContext) == - FunctionEmissionStatus::Emitted) + return (SemaRef.getEmissionStatus(CurFunContext) == + Sema::FunctionEmissionStatus::Emitted) ? SemaDiagnosticBuilder::K_ImmediateWithCallStack : SemaDiagnosticBuilder::K_Deferred; default: return SemaDiagnosticBuilder::K_Nop; } }(); - return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, *this); + return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, SemaRef); } -Sema::SemaDiagnosticBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc, +Sema::SemaDiagnosticBuilder SemaCUDA::DiagIfHostCode(SourceLocation Loc, unsigned DiagID) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - FunctionDecl *CurFunContext = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *CurFunContext = + SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); SemaDiagnosticBuilder::Kind DiagKind = [&] { if (!CurFunContext) return SemaDiagnosticBuilder::K_Nop; - switch (CurrentCUDATarget()) { + switch (CurrentTarget()) { case CUDAFunctionTarget::Host: return SemaDiagnosticBuilder::K_Immediate; case CUDAFunctionTarget::HostDevice: @@ -858,40 +865,41 @@ Sema::SemaDiagnosticBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc, // mode until the function is known-emitted. if (getLangOpts().CUDAIsDevice) return SemaDiagnosticBuilder::K_Nop; - if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID)) + if (SemaRef.IsLastErrorImmediate && + getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID)) return SemaDiagnosticBuilder::K_Immediate; - return (getEmissionStatus(CurFunContext) == - FunctionEmissionStatus::Emitted) + return (SemaRef.getEmissionStatus(CurFunContext) == + Sema::FunctionEmissionStatus::Emitted) ? SemaDiagnosticBuilder::K_ImmediateWithCallStack : SemaDiagnosticBuilder::K_Deferred; default: return SemaDiagnosticBuilder::K_Nop; } }(); - return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, *this); + return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, SemaRef); } -bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { +bool SemaCUDA::CheckCall(SourceLocation Loc, FunctionDecl *Callee) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); assert(Callee && "Callee may not be null."); - const auto &ExprEvalCtx = currentEvaluationContext(); + const auto &ExprEvalCtx = SemaRef.currentEvaluationContext(); if (ExprEvalCtx.isUnevaluated() || ExprEvalCtx.isConstantEvaluated()) return true; // FIXME: Is bailing out early correct here? Should we instead assume that // the caller is a global initializer? - FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *Caller = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); if (!Caller) return true; // If the caller is known-emitted, mark the callee as known-emitted. // Otherwise, mark the call in our call graph so we can traverse it later. - bool CallerKnownEmitted = - getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted; + bool CallerKnownEmitted = SemaRef.getEmissionStatus(Caller) == + Sema::FunctionEmissionStatus::Emitted; SemaDiagnosticBuilder::Kind DiagKind = [this, Caller, Callee, CallerKnownEmitted] { - switch (IdentifyCUDAPreference(Caller, Callee)) { + switch (IdentifyPreference(Caller, Callee)) { case CFP_Never: case CFP_WrongSide: assert(Caller && "Never/wrongSide calls require a non-null caller"); @@ -908,7 +916,7 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { if (DiagKind == SemaDiagnosticBuilder::K_Nop) { // For -fgpu-rdc, keep track of external kernels used by host functions. - if (LangOpts.CUDAIsDevice && LangOpts.GPURelocatableDeviceCode && + if (getLangOpts().CUDAIsDevice && getLangOpts().GPURelocatableDeviceCode && Callee->hasAttr() && !Callee->isDefined() && (!Caller || (!Caller->getDescribedFunctionTemplate() && getASTContext().GetGVALinkageForFunction(Caller) == @@ -924,12 +932,13 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { if (!LocsWithCUDACallDiags.insert({Caller, Loc}).second) return true; - SemaDiagnosticBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, *this) - << llvm::to_underlying(IdentifyCUDATarget(Callee)) << /*function*/ 0 - << Callee << llvm::to_underlying(IdentifyCUDATarget(Caller)); + SemaDiagnosticBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, + SemaRef) + << llvm::to_underlying(IdentifyTarget(Callee)) << /*function*/ 0 << Callee + << llvm::to_underlying(IdentifyTarget(Caller)); if (!Callee->getBuiltinID()) SemaDiagnosticBuilder(DiagKind, Callee->getLocation(), - diag::note_previous_decl, Caller, *this) + diag::note_previous_decl, Caller, SemaRef) << Callee; return DiagKind != SemaDiagnosticBuilder::K_Immediate && DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack; @@ -940,7 +949,7 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { // defined and uses the capture by reference when the lambda is called. When // the capture and use happen on different sides, the capture is invalid and // should be diagnosed. -void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, +void SemaCUDA::CheckLambdaCapture(CXXMethodDecl *Callee, const sema::Capture &Capture) { // In host compilation we only need to check lambda functions emitted on host // side. In such lambda functions, a reference capture is invalid only @@ -950,12 +959,12 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, // kernel cannot pass a lambda back to a host function since we cannot // define a kernel argument type which can hold the lambda before the lambda // itself is defined. - if (!LangOpts.CUDAIsDevice) + if (!getLangOpts().CUDAIsDevice) return; // File-scope lambda can only do init captures for global variables, which // results in passing by value for these global variables. - FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *Caller = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); if (!Caller) return; @@ -972,7 +981,7 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, auto DiagKind = SemaDiagnosticBuilder::K_Deferred; if (Capture.isVariableCapture() && !getLangOpts().HIPStdPar) { SemaDiagnosticBuilder(DiagKind, Capture.getLocation(), - diag::err_capture_bad_target, Callee, *this) + diag::err_capture_bad_target, Callee, SemaRef) << Capture.getVariable(); } else if (Capture.isThisCapture()) { // Capture of this pointer is allowed since this pointer may be pointing to @@ -981,28 +990,28 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, // accessible on device side. SemaDiagnosticBuilder(DiagKind, Capture.getLocation(), diag::warn_maybe_capture_bad_target_this_ptr, Callee, - *this); + SemaRef); } } -void Sema::CUDASetLambdaAttrs(CXXMethodDecl *Method) { +void SemaCUDA::SetLambdaAttrs(CXXMethodDecl *Method) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); if (Method->hasAttr() || Method->hasAttr()) return; - Method->addAttr(CUDADeviceAttr::CreateImplicit(Context)); - Method->addAttr(CUDAHostAttr::CreateImplicit(Context)); + Method->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); + Method->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); } -void Sema::checkCUDATargetOverload(FunctionDecl *NewFD, +void SemaCUDA::checkTargetOverload(FunctionDecl *NewFD, const LookupResult &Previous) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - CUDAFunctionTarget NewTarget = IdentifyCUDATarget(NewFD); + CUDAFunctionTarget NewTarget = IdentifyTarget(NewFD); for (NamedDecl *OldND : Previous) { FunctionDecl *OldFD = OldND->getAsFunction(); if (!OldFD) continue; - CUDAFunctionTarget OldTarget = IdentifyCUDATarget(OldFD); + CUDAFunctionTarget OldTarget = IdentifyTarget(OldFD); // Don't allow HD and global functions to overload other functions with the // same signature. We allow overloading based on CUDA attributes so that // functions can have different implementations on the host and device, but @@ -1010,17 +1019,17 @@ void Sema::checkCUDATargetOverload(FunctionDecl *NewFD, // should have the same implementation on both sides. if (NewTarget != OldTarget && ((NewTarget == CUDAFunctionTarget::HostDevice && - !(LangOpts.OffloadImplicitHostDeviceTemplates && - isCUDAImplicitHostDeviceFunction(NewFD) && + !(getLangOpts().OffloadImplicitHostDeviceTemplates && + isImplicitHostDeviceFunction(NewFD) && OldTarget == CUDAFunctionTarget::Device)) || (OldTarget == CUDAFunctionTarget::HostDevice && - !(LangOpts.OffloadImplicitHostDeviceTemplates && - isCUDAImplicitHostDeviceFunction(OldFD) && + !(getLangOpts().OffloadImplicitHostDeviceTemplates && + isImplicitHostDeviceFunction(OldFD) && NewTarget == CUDAFunctionTarget::Device)) || (NewTarget == CUDAFunctionTarget::Global) || (OldTarget == CUDAFunctionTarget::Global)) && - !IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false, - /* ConsiderCudaAttrs = */ false)) { + !SemaRef.IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false, + /* ConsiderCudaAttrs = */ false)) { Diag(NewFD->getLocation(), diag::err_cuda_ovl_target) << llvm::to_underlying(NewTarget) << NewFD->getDeclName() << llvm::to_underlying(OldTarget) << OldFD; @@ -1041,21 +1050,21 @@ static void copyAttrIfPresent(Sema &S, FunctionDecl *FD, } } -void Sema::inheritCUDATargetAttrs(FunctionDecl *FD, +void SemaCUDA::inheritTargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD) { const FunctionDecl &TemplateFD = *TD.getTemplatedDecl(); - copyAttrIfPresent(*this, FD, TemplateFD); - copyAttrIfPresent(*this, FD, TemplateFD); - copyAttrIfPresent(*this, FD, TemplateFD); + copyAttrIfPresent(SemaRef, FD, TemplateFD); + copyAttrIfPresent(SemaRef, FD, TemplateFD); + copyAttrIfPresent(SemaRef, FD, TemplateFD); } -std::string Sema::getCudaConfigureFuncName() const { +std::string SemaCUDA::getConfigureFuncName() const { if (getLangOpts().HIP) return getLangOpts().HIPUseNewLaunchAPI ? "__hipPushCallConfiguration" : "hipConfigureCall"; // New CUDA kernel launch sequence. - if (CudaFeatureEnabled(Context.getTargetInfo().getSDKVersion(), + if (CudaFeatureEnabled(getASTContext().getTargetInfo().getSDKVersion(), CudaFeature::CUDA_USES_NEW_LAUNCH)) return "__cudaPushCallConfiguration"; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 720e56692359..17032d137052 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -45,6 +45,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" @@ -10595,12 +10596,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // We do not add HD attributes to specializations here because // they may have different constexpr-ness compared to their - // templates and, after maybeAddCUDAHostDeviceAttrs() is applied, + // templates and, after maybeAddHostDeviceAttrs() is applied, // may end up with different effective targets. Instead, a // specialization inherits its target attributes from its template // in the CheckFunctionTemplateSpecialization() call below. if (getLangOpts().CUDA && !isFunctionTemplateSpecialization) - maybeAddCUDAHostDeviceAttrs(NewFD, Previous); + CUDA().maybeAddHostDeviceAttrs(NewFD, Previous); // Handle explict specializations of function templates // and friend function declarations with an explicit @@ -10898,12 +10899,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (getLangOpts().CUDA) { IdentifierInfo *II = NewFD->getIdentifier(); - if (II && II->isStr(getCudaConfigureFuncName()) && + if (II && II->isStr(CUDA().getConfigureFuncName()) && !NewFD->isInvalidDecl() && NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { if (!R->castAs()->getReturnType()->isScalarType()) Diag(NewFD->getLocation(), diag::err_config_scalar_return) - << getCudaConfigureFuncName(); + << CUDA().getConfigureFuncName(); Context.setcudaConfigureCallDecl(NewFD); } @@ -12398,7 +12399,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } if (!Redeclaration && LangOpts.CUDA) - checkCUDATargetOverload(NewFD, Previous); + CUDA().checkTargetOverload(NewFD, Previous); } // Check if the function definition uses any AArch64 SME features without @@ -14415,7 +14416,7 @@ StmtResult Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (var->isInvalidDecl()) return; - MaybeAddCUDAConstantAttr(var); + CUDA().MaybeAddConstantAttr(var); if (getLangOpts().OpenCL) { // OpenCL v2.0 s6.12.5 - Every block variable declaration must have an @@ -14829,7 +14830,7 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { // variables whether they are local or not. CUDA also allows // constant initializers for __constant__ and __device__ variables. if (getLangOpts().CUDA) - checkAllowedCUDAInitializer(VD); + CUDA().checkAllowedInitializer(VD); // Grab the dllimport or dllexport attribute off of the VarDecl. const InheritableAttr *DLLAttr = getDLLAttr(VD); @@ -20666,7 +20667,7 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(const FunctionDecl *FD, // when compiling for host, device and global functions are never emitted. // (Technically, we do emit a host-side stub for global functions, but this // doesn't count for our purposes here.) - CUDAFunctionTarget T = IdentifyCUDATarget(FD); + CUDAFunctionTarget T = CUDA().IdentifyTarget(FD); if (LangOpts.CUDAIsDevice && T == CUDAFunctionTarget::Host) return FunctionEmissionStatus::CUDADiscarded; if (!LangOpts.CUDAIsDevice && @@ -20691,5 +20692,5 @@ bool Sema::shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee) { // for host, only HD functions actually called from the host get marked as // known-emitted. return LangOpts.CUDA && !LangOpts.CUDAIsDevice && - IdentifyCUDATarget(Callee) == CUDAFunctionTarget::Global; + CUDA().IdentifyTarget(Callee) == CUDAFunctionTarget::Global; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 56c9d90c9b52..b7b1fbc625a1 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -39,6 +39,7 @@ #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/STLExtras.h" @@ -5099,8 +5100,8 @@ static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } if (S.getLangOpts().CUDA && VD->hasLocalStorage() && - S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared) - << llvm::to_underlying(S.CurrentCUDATarget())) + S.CUDA().DiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared) + << llvm::to_underlying(S.CUDA().CurrentTarget())) return; D->addAttr(::new (S.Context) CUDASharedAttr(S.Context, AL)); } @@ -5189,8 +5190,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Diagnostic is emitted elsewhere: here we store the (valid) AL // in the Decl node for syntactic reasoning, e.g., pretty-printing. CallingConv CC; - if (S.CheckCallingConvAttr(AL, CC, /*FD*/ nullptr, - S.IdentifyCUDATarget(dyn_cast(D)))) + if (S.CheckCallingConvAttr( + AL, CC, /*FD*/ nullptr, + S.CUDA().IdentifyTarget(dyn_cast(D)))) return; if (!isa(D)) { @@ -5495,7 +5497,7 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, if (LangOpts.CUDA) { auto *Aux = Context.getAuxTargetInfo(); assert(FD || CFT != CUDAFunctionTarget::InvalidTarget); - auto CudaTarget = FD ? IdentifyCUDATarget(FD) : CFT; + auto CudaTarget = FD ? CUDA().IdentifyTarget(FD) : CFT; bool CheckHost = false, CheckDevice = false; switch (CudaTarget) { case CUDAFunctionTarget::HostDevice: diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 51c14443d2d8..1fe10375222c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -42,6 +42,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/ArrayRef.h" @@ -9876,15 +9877,15 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, // failed. // For inherited constructors (non-null ICI), CSM may be passed so that MD // is treated as certain special member, which may not reflect what special - // member MD really is. However inferCUDATargetForImplicitSpecialMember + // member MD really is. However inferTargetForImplicitSpecialMember // expects CSM to match MD, therefore recalculate CSM. assert(ICI || CSM == getSpecialMember(MD)); auto RealCSM = CSM; if (ICI) RealCSM = getSpecialMember(MD); - return inferCUDATargetForImplicitSpecialMember(RD, RealCSM, MD, - SMI.ConstArg, Diagnose); + return CUDA().inferTargetForImplicitSpecialMember(RD, RealCSM, MD, + SMI.ConstArg, Diagnose); } return false; @@ -14055,7 +14056,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( setupImplicitSpecialMemberType(DefaultCon, Context.VoidTy, std::nullopt); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember( + CUDA().inferTargetForImplicitSpecialMember( ClassDecl, CXXSpecialMemberKind::DefaultConstructor, DefaultCon, /* ConstRHS */ false, /* Diagnose */ false); @@ -14341,7 +14342,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { setupImplicitSpecialMemberType(Destructor, Context.VoidTy, std::nullopt); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember( + CUDA().inferTargetForImplicitSpecialMember( ClassDecl, CXXSpecialMemberKind::Destructor, Destructor, /* ConstRHS */ false, /* Diagnose */ false); @@ -14983,7 +14984,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { setupImplicitSpecialMemberType(CopyAssignment, RetType, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember( + CUDA().inferTargetForImplicitSpecialMember( ClassDecl, CXXSpecialMemberKind::CopyAssignment, CopyAssignment, /* ConstRHS */ Const, /* Diagnose */ false); @@ -15335,7 +15336,7 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember( + CUDA().inferTargetForImplicitSpecialMember( ClassDecl, CXXSpecialMemberKind::MoveAssignment, MoveAssignment, /* ConstRHS */ false, /* Diagnose */ false); @@ -15733,7 +15734,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( setupImplicitSpecialMemberType(CopyConstructor, Context.VoidTy, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember( + CUDA().inferTargetForImplicitSpecialMember( ClassDecl, CXXSpecialMemberKind::CopyConstructor, CopyConstructor, /* ConstRHS */ Const, /* Diagnose */ false); @@ -15878,7 +15879,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( setupImplicitSpecialMemberType(MoveConstructor, Context.VoidTy, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember( + CUDA().inferTargetForImplicitSpecialMember( ClassDecl, CXXSpecialMemberKind::MoveConstructor, MoveConstructor, /* ConstRHS */ false, /* Diagnose */ false); @@ -16184,7 +16185,7 @@ ExprResult Sema::BuildCXXConstructExpr( DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) && "given constructor for wrong type"); MarkFunctionReferenced(ConstructLoc, Constructor); - if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor)) + if (getLangOpts().CUDA && !CUDA().CheckCall(ConstructLoc, Constructor)) return ExprError(); return CheckForImmediateInvocation( diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index b294d2bd9f53..823bf36d88bc 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -49,6 +49,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" @@ -308,7 +309,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, DeduceReturnType(FD, Loc)) return true; - if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD)) + if (getLangOpts().CUDA && !CUDA().CheckCall(Loc, FD)) return true; } @@ -17307,7 +17308,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, // CUDA device code does not support varargs. if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { if (const FunctionDecl *F = dyn_cast(CurContext)) { - CUDAFunctionTarget T = IdentifyCUDATarget(F); + CUDAFunctionTarget T = CUDA().IdentifyTarget(F); if (T == CUDAFunctionTarget::Global || T == CUDAFunctionTarget::Device || T == CUDAFunctionTarget::HostDevice) return ExprError(Diag(E->getBeginLoc(), diag::err_va_arg_in_device)); @@ -18961,7 +18962,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, checkSpecializationReachability(Loc, Func); if (getLangOpts().CUDA) - CheckCUDACall(Loc, Func); + CUDA().CheckCall(Loc, Func); // If we need a definition, try to create one. if (NeedDefinition && !Func->getBody()) { @@ -19108,7 +19109,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, // side. Therefore keep trying until it is recorded. if (LangOpts.OffloadImplicitHostDeviceTemplates && LangOpts.CUDAIsDevice && !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(Func)) - CUDARecordImplicitHostDeviceFuncUsedByDevice(Func); + CUDA().RecordImplicitHostDeviceFuncUsedByDevice(Func); // If this is the first "real" use, act on that. if (OdrUse == OdrUseContext::Used && !Func->isUsed(/*CheckUsedAttr=*/false)) { @@ -19181,9 +19182,9 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef, if (SemaRef.LangOpts.CUDA && Var->hasGlobalStorage()) { auto *FD = dyn_cast_or_null(SemaRef.CurContext); - auto VarTarget = SemaRef.IdentifyCUDATarget(Var); - auto UserTarget = SemaRef.IdentifyCUDATarget(FD); - if (VarTarget == Sema::CVT_Host && + auto VarTarget = SemaRef.CUDA().IdentifyTarget(Var); + auto UserTarget = SemaRef.CUDA().IdentifyTarget(FD); + if (VarTarget == SemaCUDA::CVT_Host && (UserTarget == CUDAFunctionTarget::Device || UserTarget == CUDAFunctionTarget::HostDevice || UserTarget == CUDAFunctionTarget::Global)) { @@ -19199,7 +19200,7 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef, ? diag::note_cuda_const_var_unpromoted : diag::note_cuda_host_var); } - } else if (VarTarget == Sema::CVT_Device && + } else if (VarTarget == SemaCUDA::CVT_Device && !Var->hasAttr() && (UserTarget == CUDAFunctionTarget::Host || UserTarget == CUDAFunctionTarget::HostDevice)) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index ce9d5c26e218..8911257a6f61 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -38,6 +38,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaLambda.h" #include "clang/Sema/Template.h" @@ -884,8 +885,8 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) - CUDADiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions) - << "throw" << llvm::to_underlying(CurrentCUDATarget()); + CUDA().DiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions) + << "throw" << llvm::to_underlying(CUDA().CurrentTarget()); if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw"; @@ -1708,17 +1709,17 @@ bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) { // [CUDA] Ignore this function, if we can't call it. const FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); if (getLangOpts().CUDA) { - auto CallPreference = IdentifyCUDAPreference(Caller, Method); + auto CallPreference = CUDA().IdentifyPreference(Caller, Method); // If it's not callable at all, it's not the right function. - if (CallPreference < CFP_WrongSide) + if (CallPreference < SemaCUDA::CFP_WrongSide) return false; - if (CallPreference == CFP_WrongSide) { + if (CallPreference == SemaCUDA::CFP_WrongSide) { // Maybe. We have to check if there are better alternatives. DeclContext::lookup_result R = Method->getDeclContext()->lookup(Method->getDeclName()); for (const auto *D : R) { if (const auto *FD = dyn_cast(D)) { - if (IdentifyCUDAPreference(Caller, FD) > CFP_WrongSide) + if (CUDA().IdentifyPreference(Caller, FD) > SemaCUDA::CFP_WrongSide) return false; } } @@ -1737,7 +1738,7 @@ bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) { return llvm::none_of(PreventedBy, [&](const FunctionDecl *FD) { assert(FD->getNumParams() == 1 && "Only single-operand functions should be in PreventedBy"); - return IdentifyCUDAPreference(Caller, FD) >= CFP_HostDevice; + return CUDA().IdentifyPreference(Caller, FD) >= SemaCUDA::CFP_HostDevice; }); } @@ -1774,7 +1775,7 @@ namespace { UsualDeallocFnInfo(Sema &S, DeclAccessPair Found) : Found(Found), FD(dyn_cast(Found->getUnderlyingDecl())), Destroying(false), HasSizeT(false), HasAlignValT(false), - CUDAPref(Sema::CFP_Native) { + CUDAPref(SemaCUDA::CFP_Native) { // A function template declaration is never a usual deallocation function. if (!FD) return; @@ -1800,7 +1801,7 @@ namespace { // In CUDA, determine how much we'd like / dislike to call this. if (S.getLangOpts().CUDA) - CUDAPref = S.IdentifyCUDAPreference( + CUDAPref = S.CUDA().IdentifyPreference( S.getCurFunctionDecl(/*AllowLambda=*/true), FD); } @@ -1831,7 +1832,7 @@ namespace { DeclAccessPair Found; FunctionDecl *FD; bool Destroying, HasSizeT, HasAlignValT; - Sema::CUDAFunctionPreference CUDAPref; + SemaCUDA::CUDAFunctionPreference CUDAPref; }; } @@ -1855,7 +1856,7 @@ static UsualDeallocFnInfo resolveDeallocationOverload( for (auto I = R.begin(), E = R.end(); I != E; ++I) { UsualDeallocFnInfo Info(S, I.getPair()); if (!Info || !isNonPlacementDeallocationFunction(S, Info.FD) || - Info.CUDAPref == Sema::CFP_Never) + Info.CUDAPref == SemaCUDA::CFP_Never) continue; if (!Best) { @@ -2956,8 +2957,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, } if (getLangOpts().CUDA) - EraseUnwantedCUDAMatches(getCurFunctionDecl(/*AllowLambda=*/true), - Matches); + CUDA().EraseUnwantedMatches(getCurFunctionDecl(/*AllowLambda=*/true), + Matches); } else { // C++1y [expr.new]p22: // For a non-placement allocation function, the normal deallocation diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 5b95bae567b7..35a51c6c2328 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -9,17 +9,18 @@ // This file implements semantic analysis for C++ lambda expressions. // //===----------------------------------------------------------------------===// -#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/SemaLambda.h" #include "TypeLocBuilder.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/SemaLambda.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" #include @@ -1393,7 +1394,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // CUDA lambdas get implicit host and device attributes. if (getLangOpts().CUDA) - CUDASetLambdaAttrs(Method); + CUDA().SetLambdaAttrs(Method); // OpenMP lambdas might get assumumption attributes. if (LangOpts.OpenMP) @@ -2136,7 +2137,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, CaptureInits.push_back(Init.get()); if (LangOpts.CUDA) - CUDACheckLambdaCapture(CallOperator, From); + CUDA().CheckLambdaCapture(CallOperator, From); } Class->setCaptures(Context, Captures); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index e1155dc2d5d2..397e7681828f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -31,6 +31,7 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" @@ -1549,8 +1550,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, // Don't allow overloading of destructors. (In theory we could, but it // would be a giant change to clang.) if (!isa(New)) { - CUDAFunctionTarget NewTarget = SemaRef.IdentifyCUDATarget(New), - OldTarget = SemaRef.IdentifyCUDATarget(Old); + CUDAFunctionTarget NewTarget = SemaRef.CUDA().IdentifyTarget(New), + OldTarget = SemaRef.CUDA().IdentifyTarget(Old); if (NewTarget != CUDAFunctionTarget::InvalidTarget) { assert((OldTarget != CUDAFunctionTarget::InvalidTarget) && "Unexpected invalid target."); @@ -7100,7 +7101,7 @@ void Sema::AddOverloadCandidate( // inferred for the member automatically, based on the bases and fields of // the class. if (!(Caller && Caller->isImplicit()) && - !IsAllowedCUDACall(Caller, Function)) { + !CUDA().IsAllowedCall(Caller, Function)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_target; return; @@ -7618,7 +7619,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // (CUDA B.1): Check for invalid calls between targets. if (getLangOpts().CUDA) - if (!IsAllowedCUDACall(getCurFunctionDecl(/*AllowLambda=*/true), Method)) { + if (!CUDA().IsAllowedCall(getCurFunctionDecl(/*AllowLambda=*/true), + Method)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_target; return; @@ -10440,7 +10442,7 @@ bool clang::isBetterOverloadCandidate( // If other rules cannot determine which is better, CUDA preference will be // used again to determine which is better. // - // TODO: Currently IdentifyCUDAPreference does not return correct values + // TODO: Currently IdentifyPreference does not return correct values // for functions called in global variable initializers due to missing // correct context about device/host. Therefore we can only enforce this // rule when there is a caller. We should enforce this rule for functions @@ -10452,14 +10454,14 @@ bool clang::isBetterOverloadCandidate( if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function && S.getLangOpts().GPUExcludeWrongSideOverloads) { if (FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true)) { - bool IsCallerImplicitHD = Sema::isCUDAImplicitHostDeviceFunction(Caller); + bool IsCallerImplicitHD = SemaCUDA::isImplicitHostDeviceFunction(Caller); bool IsCand1ImplicitHD = - Sema::isCUDAImplicitHostDeviceFunction(Cand1.Function); + SemaCUDA::isImplicitHostDeviceFunction(Cand1.Function); bool IsCand2ImplicitHD = - Sema::isCUDAImplicitHostDeviceFunction(Cand2.Function); - auto P1 = S.IdentifyCUDAPreference(Caller, Cand1.Function); - auto P2 = S.IdentifyCUDAPreference(Caller, Cand2.Function); - assert(P1 != Sema::CFP_Never && P2 != Sema::CFP_Never); + SemaCUDA::isImplicitHostDeviceFunction(Cand2.Function); + auto P1 = S.CUDA().IdentifyPreference(Caller, Cand1.Function); + auto P2 = S.CUDA().IdentifyPreference(Caller, Cand2.Function); + assert(P1 != SemaCUDA::CFP_Never && P2 != SemaCUDA::CFP_Never); // The implicit HD function may be a function in a system header which // is forced by pragma. In device compilation, if we prefer HD candidates // over wrong-sided candidates, overloading resolution may change, which @@ -10473,8 +10475,8 @@ bool clang::isBetterOverloadCandidate( auto EmitThreshold = (S.getLangOpts().CUDAIsDevice && IsCallerImplicitHD && (IsCand1ImplicitHD || IsCand2ImplicitHD)) - ? Sema::CFP_Never - : Sema::CFP_WrongSide; + ? SemaCUDA::CFP_Never + : SemaCUDA::CFP_WrongSide; auto Cand1Emittable = P1 > EmitThreshold; auto Cand2Emittable = P2 > EmitThreshold; if (Cand1Emittable && !Cand2Emittable) @@ -10758,8 +10760,8 @@ bool clang::isBetterOverloadCandidate( // to determine which is better. if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) { FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true); - return S.IdentifyCUDAPreference(Caller, Cand1.Function) > - S.IdentifyCUDAPreference(Caller, Cand2.Function); + return S.CUDA().IdentifyPreference(Caller, Cand1.Function) > + S.CUDA().IdentifyPreference(Caller, Cand2.Function); } // General member function overloading is handled above, so this only handles @@ -10891,15 +10893,15 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, llvm::any_of(Candidates, [&](OverloadCandidate *Cand) { // Check viable function only. return Cand->Viable && Cand->Function && - S.IdentifyCUDAPreference(Caller, Cand->Function) == - Sema::CFP_SameSide; + S.CUDA().IdentifyPreference(Caller, Cand->Function) == + SemaCUDA::CFP_SameSide; }); if (ContainsSameSideCandidate) { auto IsWrongSideCandidate = [&](OverloadCandidate *Cand) { // Check viable function only to avoid unnecessary data copying/moving. return Cand->Viable && Cand->Function && - S.IdentifyCUDAPreference(Caller, Cand->Function) == - Sema::CFP_WrongSide; + S.CUDA().IdentifyPreference(Caller, Cand->Function) == + SemaCUDA::CFP_WrongSide; }; llvm::erase_if(Candidates, IsWrongSideCandidate); } @@ -11938,8 +11940,8 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true); FunctionDecl *Callee = Cand->Function; - CUDAFunctionTarget CallerTarget = S.IdentifyCUDATarget(Caller), - CalleeTarget = S.IdentifyCUDATarget(Callee); + CUDAFunctionTarget CallerTarget = S.CUDA().IdentifyTarget(Caller), + CalleeTarget = S.CUDA().IdentifyTarget(Callee); std::string FnDesc; std::pair FnKindPair = @@ -11986,9 +11988,9 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { } } - S.inferCUDATargetForImplicitSpecialMember(ParentClass, CSM, Meth, - /* ConstRHS */ ConstRHS, - /* Diagnose */ true); + S.CUDA().inferTargetForImplicitSpecialMember(ParentClass, CSM, Meth, + /* ConstRHS */ ConstRHS, + /* Diagnose */ true); } } @@ -13060,7 +13062,7 @@ private: if (S.getLangOpts().CUDA) { FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true); if (!(Caller && Caller->isImplicit()) && - !S.IsAllowedCUDACall(Caller, FunDecl)) + !S.CUDA().IsAllowedCall(Caller, FunDecl)) return false; } if (FunDecl->isMultiVersion()) { @@ -13180,8 +13182,8 @@ private: } void EliminateSuboptimalCudaMatches() { - S.EraseUnwantedCUDAMatches(S.getCurFunctionDecl(/*AllowLambda=*/true), - Matches); + S.CUDA().EraseUnwantedMatches(S.getCurFunctionDecl(/*AllowLambda=*/true), + Matches); } public: @@ -13335,8 +13337,8 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) { // Return positive for better, negative for worse, 0 for equal preference. auto CheckCUDAPreference = [&](FunctionDecl *FD1, FunctionDecl *FD2) { FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); - return static_cast(IdentifyCUDAPreference(Caller, FD1)) - - static_cast(IdentifyCUDAPreference(Caller, FD2)); + return static_cast(CUDA().IdentifyPreference(Caller, FD1)) - + static_cast(CUDA().IdentifyPreference(Caller, FD2)); }; auto CheckMoreConstrained = [&](FunctionDecl *FD1, diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 1c2f6120f621..d28c24cfdfd3 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -33,6 +33,7 @@ #include "clang/Sema/Ownership.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -4574,8 +4575,8 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) - CUDADiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions) - << "try" << llvm::to_underlying(CurrentCUDATarget()); + CUDA().DiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions) + << "try" << llvm::to_underlying(CUDA().CurrentTarget()); if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try"; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e0f5e53dc248..95171359f0ab 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -33,6 +33,7 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" @@ -10155,9 +10156,9 @@ bool Sema::CheckFunctionTemplateSpecialization( // take target attributes into account, we reject candidates // here that have a different target. if (LangOpts.CUDA && - IdentifyCUDATarget(Specialization, - /* IgnoreImplicitHDAttr = */ true) != - IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttr = */ true)) { + CUDA().IdentifyTarget(Specialization, + /* IgnoreImplicitHDAttr = */ true) != + CUDA().IdentifyTarget(FD, /* IgnoreImplicitHDAttr = */ true)) { FailedCandidates.addCandidate().set( I.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo( @@ -10328,7 +10329,7 @@ bool Sema::CheckFunctionTemplateSpecialization( // virtue e.g. of being constexpr, and it passes these implicit // attributes on to its specializations.) if (LangOpts.CUDA) - inheritCUDATargetAttrs(FD, *Specialization->getPrimaryTemplate()); + CUDA().inheritTargetAttrs(FD, *Specialization->getPrimaryTemplate()); // The "previous declaration" for this function template specialization is // the prior function template specialization. @@ -11364,9 +11365,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // target attributes into account, we reject candidates here that // have a different target. if (LangOpts.CUDA && - IdentifyCUDATarget(Specialization, - /* IgnoreImplicitHDAttr = */ true) != - IdentifyCUDATarget(D.getDeclSpec().getAttributes())) { + CUDA().IdentifyTarget(Specialization, + /* IgnoreImplicitHDAttr = */ true) != + CUDA().IdentifyTarget(D.getDeclSpec().getAttributes())) { FailedCandidates.addCandidate().set( P.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo( diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 7f510d34d671..c0469a47ab8b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -26,6 +26,7 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" @@ -5537,7 +5538,7 @@ void Sema::InstantiateVariableInitializer( } if (getLangOpts().CUDA) - checkAllowedCUDAInitializer(Var); + CUDA().checkAllowedInitializer(Var); } /// Instantiate the definition of the given variable from its diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index b3f6078952f6..404c4e8e31b5 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -33,6 +33,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" @@ -2735,7 +2736,7 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM, bool IsCUDADevice = (getLangOpts().CUDA && getLangOpts().CUDAIsDevice); targetDiag(Loc, IsCUDADevice ? diag::err_cuda_vla : diag::err_vla_unsupported) - << (IsCUDADevice ? llvm::to_underlying(CurrentCUDATarget()) : 0); + << (IsCUDADevice ? llvm::to_underlying(CUDA().CurrentTarget()) : 0); } else if (sema::FunctionScopeInfo *FSI = getCurFunction()) { // VLAs are supported on this target, but we may need to do delayed // checking that the VLA is not being used within a coroutine. @@ -3618,7 +3619,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // D.getDeclarationAttributes()) because those are always C++11 attributes, // and those don't get distributed. distributeTypeAttrsFromDeclarator( - state, T, SemaRef.IdentifyCUDATarget(D.getAttributes())); + state, T, SemaRef.CUDA().IdentifyTarget(D.getAttributes())); // Find the deduced type in this type. Look in the trailing return type if we // have one, otherwise in the DeclSpec type. @@ -4139,7 +4140,7 @@ static CallingConv getCCForDeclaratorChunk( // handleFunctionTypeAttr. CallingConv CC; if (!S.CheckCallingConvAttr(AL, CC, /*FunctionDecl=*/nullptr, - S.IdentifyCUDATarget(D.getAttributes())) && + S.CUDA().IdentifyTarget(D.getAttributes())) && (!FTI.isVariadic || supportsVariadicCall(CC))) { return CC; } @@ -5825,7 +5826,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // See if there are any attributes on this declarator chunk. processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs(), - S.IdentifyCUDATarget(D.getAttributes())); + S.CUDA().IdentifyTarget(D.getAttributes())); if (DeclType.Kind != DeclaratorChunk::Paren) { if (ExpectNoDerefChunk && !IsNoDerefableChunk(DeclType)) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index a47c7a393d63..8c4b460970ad 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -78,6 +78,7 @@ #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Scope.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/Weak.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTDeserializationListener.h" @@ -3995,7 +3996,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, if (Record.size() != 1) return llvm::createStringError(std::errc::illegal_byte_sequence, "invalid cuda pragma options record"); - ForceCUDAHostDeviceDepth = Record[0]; + ForceHostDeviceDepth = Record[0]; break; case ALIGN_PACK_PRAGMA_OPTIONS: { @@ -8274,7 +8275,7 @@ void ASTReader::UpdateSema() { PragmaMSPointersToMembersState, PointersToMembersPragmaLocation); } - SemaObj->ForceCUDAHostDeviceDepth = ForceCUDAHostDeviceDepth; + SemaObj->CUDA().ForceHostDeviceDepth = ForceHostDeviceDepth; if (PragmaAlignPackCurrentValue) { // The bottom of the stack might have a default value. It must be adjusted diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index d45695784354..85b7fd5535a1 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -65,6 +65,7 @@ #include "clang/Sema/IdentifierResolver.h" #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/Weak.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTReader.h" @@ -4335,8 +4336,8 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { Stream.EmitRecord(OPENCL_EXTENSIONS, Record); } void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) { - if (SemaRef.ForceCUDAHostDeviceDepth > 0) { - RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth}; + if (SemaRef.CUDA().ForceHostDeviceDepth > 0) { + RecordData::value_type Record[] = {SemaRef.CUDA().ForceHostDeviceDepth}; Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record); } } -- GitLab From 6dcb60481323c871556a5a14ed887a5867ece114 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Sat, 13 Apr 2024 08:55:09 +0400 Subject: [PATCH 133/464] [clang] Implement `__is_pointer_interconvertible_base_of()` (#88473) This patch implements intrinsic that supports `std::is_pointer_interconvertible_base_of` type trait from [P0466R5](https://wg21.link/p0466r5) "Layout-compatibility and Pointer-interconvertibility Traits". Normative wording: > Comment: If `Base` and Derived are non-union class types and are not (possibly _cv_-qualified) versions of the same type, `Derived` is a complete type. > Condition: `Derived` is unambiguously derived from `Base` without regard to _cv_-qualifiers, and each object of type `Derived` is pointer-interconvertible (6.7.2 [basic.compound]) with its `Base` subobject, or `Base` and `Derived` are not unions and name the same class type without regard to _cv_-qualifiers. The paper also express the following intent: > Note that `is_pointer_interconvertible_base_of_v` is always true under this wording, even though `T` is not derived from itself. I find the treatment of unions in the wording contradictory to this intent, and I'm not able to find anything relevant in minutes or on the reflector. That said, this patch implements what the wording says, since it's very explicit about unions. --- clang/docs/ReleaseNotes.rst | 3 +- clang/include/clang/Basic/TokenKinds.def | 1 + clang/include/clang/Sema/Sema.h | 2 + clang/lib/Sema/SemaChecking.cpp | 21 ++++++ clang/lib/Sema/SemaExprCXX.cpp | 16 +++++ clang/test/SemaCXX/type-traits.cpp | 91 +++++++++++++++++++++++- 6 files changed, 132 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 45a9a79739a4..399d5ba796d1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -98,7 +98,8 @@ C++20 Feature Support behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'. (#GH79240). -- Implemented the `__is_layout_compatible` intrinsic to support +- Implemented the `__is_layout_compatible` and `__is_pointer_interconvertible_base_of` + intrinsics to support `P0466R5: Layout-compatibility and Pointer-interconvertibility Traits `_. - Clang now implements [module.import]p7 fully. Clang now will import module diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 800af0e6d044..a27fbed358a6 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -521,6 +521,7 @@ TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX) TYPE_TRAIT_1(__has_unique_object_representations, HasUniqueObjectRepresentations, KEYCXX) TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX) +TYPE_TRAIT_2(__is_pointer_interconvertible_base_of, IsPointerInterconvertibleBaseOf, KEYCXX) #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX) #include "clang/Basic/TransformTypeTraits.def" diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6b9789334811..3b252f94dcbe 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1999,6 +1999,8 @@ public: }; bool IsLayoutCompatible(QualType T1, QualType T2) const; + bool IsPointerInterconvertibleBaseOf(const TypeSourceInfo *Base, + const TypeSourceInfo *Derived); bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, const FunctionProtoType *Proto); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index abfd9a303157..8e21811b67d9 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -19710,6 +19710,27 @@ bool Sema::IsLayoutCompatible(QualType T1, QualType T2) const { return isLayoutCompatible(getASTContext(), T1, T2); } +//===-------------- Pointer interconvertibility ----------------------------// + +bool Sema::IsPointerInterconvertibleBaseOf(const TypeSourceInfo *Base, + const TypeSourceInfo *Derived) { + QualType BaseT = Base->getType()->getCanonicalTypeUnqualified(); + QualType DerivedT = Derived->getType()->getCanonicalTypeUnqualified(); + + if (BaseT->isStructureOrClassType() && DerivedT->isStructureOrClassType() && + getASTContext().hasSameType(BaseT, DerivedT)) + return true; + + if (!IsDerivedFrom(Derived->getTypeLoc().getBeginLoc(), DerivedT, BaseT)) + return false; + + // Per [basic.compound]/4.3, containing object has to be standard-layout. + if (DerivedT->getAsCXXRecordDecl()->isStandardLayout()) + return true; + + return false; +} + //===--- CHECK: pointer_with_type_tag attribute: datatypes should match ----// /// Given a type tag expression find the type tag itself. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 8911257a6f61..1cfd3e56a583 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6100,6 +6100,22 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI Self.Diag(Rhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) << 1 << tok::kw___is_layout_compatible; return Self.IsLayoutCompatible(LhsT, RhsT); + } + case BTT_IsPointerInterconvertibleBaseOf: { + if (LhsT->isStructureOrClassType() && RhsT->isStructureOrClassType() && + !Self.getASTContext().hasSameUnqualifiedType(LhsT, RhsT)) { + Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT, + diag::err_incomplete_type); + } + + if (LhsT->isVariableArrayType()) + Self.Diag(Lhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) + << 1 << tok::kw___is_pointer_interconvertible_base_of; + if (RhsT->isVariableArrayType()) + Self.Diag(Rhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) + << 1 << tok::kw___is_pointer_interconvertible_base_of; + + return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } default: llvm_unreachable("not a BTT"); } diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index 421d3007d27f..d43701c3d976 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -1740,7 +1740,7 @@ void is_layout_compatible(int n) static_assert(!__is_layout_compatible(void, int)); static_assert(__is_layout_compatible(void, const void)); static_assert(__is_layout_compatible(void, volatile void)); - static_assert(__is_layout_compatible(const int, volatile int)); + static_assert(__is_layout_compatible(const void, volatile void)); static_assert(__is_layout_compatible(int, int)); static_assert(__is_layout_compatible(int, const int)); static_assert(__is_layout_compatible(int, volatile int)); @@ -1839,6 +1839,95 @@ void is_layout_compatible(int n) static_assert(!__is_layout_compatible(EnumClassForward, int)); } +namespace IPIBO { +struct Base {}; +struct Base2 {}; +struct Base3 : Base {}; +struct Base3Virtual : virtual Base {}; +struct Derived : Base {}; +struct DerivedIndirect : Base3 {}; +struct DerivedMultiple : Base, Base2 {}; +struct DerivedAmbiguous : Base, Base3 {}; +/* expected-warning@-1 {{direct base 'Base' is inaccessible due to ambiguity: + struct IPIBO::DerivedAmbiguous -> Base + struct IPIBO::DerivedAmbiguous -> Base3 -> Base}} */ +struct DerivedPrivate : private Base {}; +struct DerivedVirtual : virtual Base {}; + +union Union {}; +union UnionIncomplete; +struct StructIncomplete; // #StructIncomplete + +void is_pointer_interconvertible_base_of(int n) +{ + static_assert(__is_pointer_interconvertible_base_of(Base, Derived)); + static_assert(!__is_pointer_interconvertible_base_of(Base2, Derived)); + static_assert(__is_pointer_interconvertible_base_of(Base, DerivedIndirect)); + static_assert(__is_pointer_interconvertible_base_of(Base, DerivedMultiple)); + static_assert(!__is_pointer_interconvertible_base_of(Base3, DerivedMultiple)); + static_assert(!__is_pointer_interconvertible_base_of(Base, DerivedAmbiguous)); + static_assert(__is_pointer_interconvertible_base_of(Base, DerivedPrivate)); + static_assert(!__is_pointer_interconvertible_base_of(Base, DerivedVirtual)); + static_assert(!__is_pointer_interconvertible_base_of(Union, Union)); + static_assert(!__is_pointer_interconvertible_base_of(UnionIncomplete, UnionIncomplete)); + static_assert(__is_pointer_interconvertible_base_of(StructIncomplete, StructIncomplete)); + static_assert(__is_pointer_interconvertible_base_of(StructIncomplete, const StructIncomplete)); + static_assert(__is_pointer_interconvertible_base_of(StructIncomplete, volatile StructIncomplete)); + static_assert(__is_pointer_interconvertible_base_of(const StructIncomplete, volatile StructIncomplete)); + static_assert(!__is_pointer_interconvertible_base_of(StructIncomplete, Derived)); + static_assert(!__is_pointer_interconvertible_base_of(Base, StructIncomplete)); + // expected-error@-1 {{incomplete type 'StructIncomplete' where a complete type is required}} + // expected-note@#StructIncomplete {{forward declaration of 'IPIBO::StructIncomplete'}} + static_assert(!__is_pointer_interconvertible_base_of(CStruct2, CppStructNonStandardByBase2)); + static_assert(!__is_pointer_interconvertible_base_of(void, void)); + static_assert(!__is_pointer_interconvertible_base_of(void, int)); + static_assert(!__is_pointer_interconvertible_base_of(void, const void)); + static_assert(!__is_pointer_interconvertible_base_of(void, volatile void)); + static_assert(!__is_pointer_interconvertible_base_of(const void, volatile void)); + static_assert(!__is_pointer_interconvertible_base_of(int, int)); + static_assert(!__is_pointer_interconvertible_base_of(int, const int)); + static_assert(!__is_pointer_interconvertible_base_of(int, volatile int)); + static_assert(!__is_pointer_interconvertible_base_of(const int, volatile int)); + static_assert(!__is_pointer_interconvertible_base_of(int *, int * __restrict)); + static_assert(!__is_pointer_interconvertible_base_of(int, _Atomic int)); + static_assert(!__is_pointer_interconvertible_base_of(_Atomic(int), _Atomic int)); + static_assert(!__is_pointer_interconvertible_base_of(int, unsigned int)); + static_assert(!__is_pointer_interconvertible_base_of(char, unsigned char)); + static_assert(!__is_pointer_interconvertible_base_of(char, signed char)); + static_assert(!__is_pointer_interconvertible_base_of(unsigned char, signed char)); + using function_type = void(); + using function_type2 = void(char); + static_assert(!__is_pointer_interconvertible_base_of(const function_type, const function_type)); + // expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}} + // expected-warning@-2 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}} + static_assert(!__is_pointer_interconvertible_base_of(function_type, const function_type)); + // expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}} + static_assert(!__is_pointer_interconvertible_base_of(const function_type, const function_type2)); + // expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}} + // expected-warning@-2 {{'const' qualifier on function type 'function_type2' (aka 'void (char)') has no effect}} + static_assert(!__is_pointer_interconvertible_base_of(int CStruct2::*, int CStruct2::*)); + static_assert(!__is_pointer_interconvertible_base_of(int CStruct2::*, char CStruct2::*)); + static_assert(!__is_pointer_interconvertible_base_of(void(CStruct2::*)(int), void(CStruct2::*)(int))); + static_assert(!__is_pointer_interconvertible_base_of(void(CStruct2::*)(int), void(CStruct2::*)(char))); + static_assert(!__is_pointer_interconvertible_base_of(int[], int[])); + static_assert(!__is_pointer_interconvertible_base_of(int[], double[])); + static_assert(!__is_pointer_interconvertible_base_of(int[2], int[2])); + static_assert(!__is_pointer_interconvertible_base_of(int[n], int[2])); + // expected-error@-1 {{variable length arrays are not supported in '__is_pointer_interconvertible_base_of'}} + static_assert(!__is_pointer_interconvertible_base_of(int[n], int[n])); + // expected-error@-1 {{variable length arrays are not supported in '__is_pointer_interconvertible_base_of'}} + // expected-error@-2 {{variable length arrays are not supported in '__is_pointer_interconvertible_base_of'}} + static_assert(!__is_pointer_interconvertible_base_of(int&, int&)); + static_assert(!__is_pointer_interconvertible_base_of(int&, char&)); + static_assert(!__is_pointer_interconvertible_base_of(void(int), void(int))); + static_assert(!__is_pointer_interconvertible_base_of(void(int), void(char))); + static_assert(!__is_pointer_interconvertible_base_of(void(&)(int), void(&)(int))); + static_assert(!__is_pointer_interconvertible_base_of(void(&)(int), void(&)(char))); + static_assert(!__is_pointer_interconvertible_base_of(void(*)(int), void(*)(int))); + static_assert(!__is_pointer_interconvertible_base_of(void(*)(int), void(*)(char))); +} +} + void is_signed() { //static_assert(__is_signed(char)); -- GitLab From 79dca25f4a0fefd47e9e37d9ce47d84dc0b3bedb Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Fri, 12 Apr 2024 22:05:12 -0700 Subject: [PATCH 134/464] [InstallAPI] Replace std::string -> StringRef --- clang/tools/clang-installapi/Options.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index 120ff3da8998..3dc61476ce09 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -372,7 +372,7 @@ bool Options::addFilePaths(InputArgList &Args, PathSeq &Headers, } // Sort headers to ensure deterministic behavior. sort(*InputHeadersOrErr); - for (std::string &H : *InputHeadersOrErr) + for (StringRef H : *InputHeadersOrErr) Headers.emplace_back(std::move(H)); } else Headers.emplace_back(Path); @@ -690,7 +690,7 @@ InstallAPIContext Options::createContext() { FrameworkName = getFrameworkNameFromInstallName(LinkerOpts.InstallName); // Process inputs. - for (const std::string &ListPath : DriverOpts.FileLists) { + for (const StringRef ListPath : DriverOpts.FileLists) { auto Buffer = FM->getBufferForFile(ListPath); if (auto Err = Buffer.getError()) { Diags->Report(diag::err_cannot_open_file) << ListPath << Err.message(); -- GitLab From ed128c7df9b4e60bfd814dc9fd22de1dde4a2c1c Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Sat, 13 Apr 2024 08:28:02 +0300 Subject: [PATCH 135/464] [clang][NFC] Replace `dr` with `cwg` in DR test suite This patch is breaking `dr` to `cwg` equivalence in our terminology, making room for tests for LWG issues that concern compiler intrinsics. --- clang/test/CXX/drs/{dr118.cpp => cwg118.cpp} | 2 +- clang/test/CXX/drs/{dr124.cpp => cwg124.cpp} | 18 +- clang/test/CXX/drs/{dr158.cpp => cwg158.cpp} | 2 +- .../test/CXX/drs/{dr1748.cpp => cwg1748.cpp} | 2 +- .../test/CXX/drs/{dr177x.cpp => cwg177x.cpp} | 8 +- .../test/CXX/drs/{dr1807.cpp => cwg1807.cpp} | 10 +- clang/test/CXX/drs/{dr185.cpp => cwg185.cpp} | 12 +- clang/test/CXX/drs/{dr193.cpp => cwg193.cpp} | 18 +- clang/test/CXX/drs/{dr199.cpp => cwg199.cpp} | 12 +- clang/test/CXX/drs/{dr201.cpp => cwg201.cpp} | 16 +- clang/test/CXX/drs/{dr210.cpp => cwg210.cpp} | 8 +- .../test/CXX/drs/{dr2335.cpp => cwg2335.cpp} | 26 +- .../test/CXX/drs/{dr2390.cpp => cwg2390.cpp} | 2 +- .../test/CXX/drs/{dr2504.cpp => cwg2504.cpp} | 8 +- clang/test/CXX/drs/{dr292.cpp => cwg292.cpp} | 8 +- clang/test/CXX/drs/{dr392.cpp => cwg392.cpp} | 10 +- clang/test/CXX/drs/{dr412.cpp => cwg412.cpp} | 2 +- clang/test/CXX/drs/{dr438.cpp => cwg438.cpp} | 6 +- clang/test/CXX/drs/{dr439.cpp => cwg439.cpp} | 6 +- clang/test/CXX/drs/{dr441.cpp => cwg441.cpp} | 18 +- clang/test/CXX/drs/{dr462.cpp => cwg462.cpp} | 10 +- clang/test/CXX/drs/{dr492.cpp => cwg492.cpp} | 6 +- clang/test/CXX/drs/{dr519.cpp => cwg519.cpp} | 6 +- clang/test/CXX/drs/{dr571.cpp => cwg571.cpp} | 6 +- clang/test/CXX/drs/{dr605.cpp => cwg605.cpp} | 6 +- clang/test/CXX/drs/{dr650.cpp => cwg650.cpp} | 12 +- clang/test/CXX/drs/{dr653.cpp => cwg653.cpp} | 6 +- clang/test/CXX/drs/{dr658.cpp => cwg658.cpp} | 6 +- clang/test/CXX/drs/{dr661.cpp => cwg661.cpp} | 8 +- clang/test/CXX/drs/{dr672.cpp => cwg672.cpp} | 8 +- clang/test/CXX/drs/{dr593.cpp => cwgr593.cpp} | 6 +- clang/test/CXX/drs/dr0xx.cpp | 842 +++++++++--------- clang/test/CXX/drs/dr10xx.cpp | 36 +- clang/test/CXX/drs/dr11xx.cpp | 24 +- clang/test/CXX/drs/dr12xx.cpp | 34 +- clang/test/CXX/drs/dr13xx.cpp | 234 ++--- clang/test/CXX/drs/dr14xx.cpp | 238 ++--- clang/test/CXX/drs/dr15xx.cpp | 370 ++++---- clang/test/CXX/drs/dr16xx.cpp | 290 +++--- clang/test/CXX/drs/dr17xx.cpp | 64 +- clang/test/CXX/drs/dr18xx.cpp | 100 +-- clang/test/CXX/drs/dr19xx.cpp | 68 +- clang/test/CXX/drs/dr1xx.cpp | 614 ++++++------- clang/test/CXX/drs/dr20xx.cpp | 152 ++-- clang/test/CXX/drs/dr21xx.cpp | 104 +-- clang/test/CXX/drs/dr22xx.cpp | 46 +- clang/test/CXX/drs/dr23xx.cpp | 80 +- clang/test/CXX/drs/dr24xx.cpp | 8 +- clang/test/CXX/drs/dr25xx.cpp | 66 +- clang/test/CXX/drs/dr26xx.cpp | 76 +- clang/test/CXX/drs/dr27xx.cpp | 18 +- clang/test/CXX/drs/dr28xx.cpp | 8 +- clang/test/CXX/drs/dr2xx.cpp | 510 +++++------ clang/test/CXX/drs/dr3xx.cpp | 774 ++++++++-------- clang/test/CXX/drs/dr4xx.cpp | 558 ++++++------ clang/test/CXX/drs/dr5xx.cpp | 444 ++++----- clang/test/CXX/drs/dr6xx.cpp | 446 +++++----- clang/test/CXX/drs/dr7xx.cpp | 120 +-- clang/test/CXX/drs/dr8xx.cpp | 12 +- clang/test/CXX/drs/dr9xx.cpp | 62 +- clang/www/make_cxx_dr_status | 6 +- 61 files changed, 3339 insertions(+), 3339 deletions(-) rename clang/test/CXX/drs/{dr118.cpp => cwg118.cpp} (98%) rename clang/test/CXX/drs/{dr124.cpp => cwg124.cpp} (83%) rename clang/test/CXX/drs/{dr158.cpp => cwg158.cpp} (98%) rename clang/test/CXX/drs/{dr1748.cpp => cwg1748.cpp} (98%) rename clang/test/CXX/drs/{dr177x.cpp => cwg177x.cpp} (95%) rename clang/test/CXX/drs/{dr1807.cpp => cwg1807.cpp} (83%) rename clang/test/CXX/drs/{dr185.cpp => cwg185.cpp} (85%) rename clang/test/CXX/drs/{dr193.cpp => cwg193.cpp} (79%) rename clang/test/CXX/drs/{dr199.cpp => cwg199.cpp} (85%) rename clang/test/CXX/drs/{dr201.cpp => cwg201.cpp} (82%) rename clang/test/CXX/drs/{dr210.cpp => cwg210.cpp} (91%) rename clang/test/CXX/drs/{dr2335.cpp => cwg2335.cpp} (56%) rename clang/test/CXX/drs/{dr2390.cpp => cwg2390.cpp} (98%) rename clang/test/CXX/drs/{dr2504.cpp => cwg2504.cpp} (90%) rename clang/test/CXX/drs/{dr292.cpp => cwg292.cpp} (91%) rename clang/test/CXX/drs/{dr392.cpp => cwg392.cpp} (88%) rename clang/test/CXX/drs/{dr412.cpp => cwg412.cpp} (99%) rename clang/test/CXX/drs/{dr438.cpp => cwg438.cpp} (94%) rename clang/test/CXX/drs/{dr439.cpp => cwg439.cpp} (94%) rename clang/test/CXX/drs/{dr441.cpp => cwg441.cpp} (76%) rename clang/test/CXX/drs/{dr462.cpp => cwg462.cpp} (87%) rename clang/test/CXX/drs/{dr492.cpp => cwg492.cpp} (94%) rename clang/test/CXX/drs/{dr519.cpp => cwg519.cpp} (95%) rename clang/test/CXX/drs/{dr571.cpp => cwg571.cpp} (91%) rename clang/test/CXX/drs/{dr605.cpp => cwg605.cpp} (91%) rename clang/test/CXX/drs/{dr650.cpp => cwg650.cpp} (86%) rename clang/test/CXX/drs/{dr653.cpp => cwg653.cpp} (92%) rename clang/test/CXX/drs/{dr658.cpp => cwg658.cpp} (92%) rename clang/test/CXX/drs/{dr661.cpp => cwg661.cpp} (91%) rename clang/test/CXX/drs/{dr672.cpp => cwg672.cpp} (91%) rename clang/test/CXX/drs/{dr593.cpp => cwgr593.cpp} (93%) diff --git a/clang/test/CXX/drs/dr118.cpp b/clang/test/CXX/drs/cwg118.cpp similarity index 98% rename from clang/test/CXX/drs/dr118.cpp rename to clang/test/CXX/drs/cwg118.cpp index 58aa3912c801..04e19ce05078 100644 --- a/clang/test/CXX/drs/dr118.cpp +++ b/clang/test/CXX/drs/cwg118.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call " // RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call " -// dr118: yes +// cwg118: yes struct S { virtual void f(); diff --git a/clang/test/CXX/drs/dr124.cpp b/clang/test/CXX/drs/cwg124.cpp similarity index 83% rename from clang/test/CXX/drs/dr124.cpp rename to clang/test/CXX/drs/cwg124.cpp index c07beb11709c..fef3c6085c37 100644 --- a/clang/test/CXX/drs/dr124.cpp +++ b/clang/test/CXX/drs/cwg124.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr124 { // dr124: 2.7 +namespace cwg124 { // cwg124: 2.7 extern void full_expr_fence() NOTHROW; @@ -32,20 +32,20 @@ void f() { full_expr_fence(); } -// CHECK-LABEL: define {{.*}} void @dr124::f()() -// CHECK: call void @dr124::full_expr_fence() +// CHECK-LABEL: define {{.*}} void @cwg124::f()() +// CHECK: call void @cwg124::full_expr_fence() // CHECK: br label %arrayctor.loop // CHECK-LABEL: arrayctor.loop: -// CHECK: call void @dr124::A::A() -// CHECK: call void @dr124::B::B(dr124::A) -// CHECK: call void @dr124::A::~A() +// CHECK: call void @cwg124::A::A() +// CHECK: call void @cwg124::B::B(cwg124::A) +// CHECK: call void @cwg124::A::~A() // CHECK: br {{.*}}, label %arrayctor.cont, label %arrayctor.loop // CHECK-LABEL: arrayctor.cont: -// CHECK: call void @dr124::full_expr_fence() +// CHECK: call void @cwg124::full_expr_fence() // CHECK: br label %arraydestroy.body // CHECK-LABEL: arraydestroy.body: -// CHECK: call void @dr124::B::~B() +// CHECK: call void @cwg124::B::~B() // CHECK-LABEL: } -} // namespace dr124 +} // namespace cwg124 diff --git a/clang/test/CXX/drs/dr158.cpp b/clang/test/CXX/drs/cwg158.cpp similarity index 98% rename from clang/test/CXX/drs/dr158.cpp rename to clang/test/CXX/drs/cwg158.cpp index a0a8bd05baee..9301c790297e 100644 --- a/clang/test/CXX/drs/dr158.cpp +++ b/clang/test/CXX/drs/cwg158.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s -// dr158: yes +// cwg158: yes // CHECK-LABEL: define {{.*}} @_Z1f const int *f(const int * const *p, int **q) { diff --git a/clang/test/CXX/drs/dr1748.cpp b/clang/test/CXX/drs/cwg1748.cpp similarity index 98% rename from clang/test/CXX/drs/dr1748.cpp rename to clang/test/CXX/drs/cwg1748.cpp index 7e04f402d266..f216963d69f2 100644 --- a/clang/test/CXX/drs/dr1748.cpp +++ b/clang/test/CXX/drs/cwg1748.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | FileCheck %s // RUN: %clang_cc1 -std=c++1z %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | FileCheck %s -// dr1748: 3.7 +// cwg1748: 3.7 // FIXME: __SIZE_TYPE__ expands to 'long long' on some targets. __extension__ typedef __SIZE_TYPE__ size_t; diff --git a/clang/test/CXX/drs/dr177x.cpp b/clang/test/CXX/drs/cwg177x.cpp similarity index 95% rename from clang/test/CXX/drs/dr177x.cpp rename to clang/test/CXX/drs/cwg177x.cpp index 7b96ff0996c7..cc62bdac4cf0 100644 --- a/clang/test/CXX/drs/dr177x.cpp +++ b/clang/test/CXX/drs/cwg177x.cpp @@ -4,9 +4,9 @@ // RUN: %clang_cc1 -std=c++1z %s -fexceptions -fcxx-exceptions -pedantic-errors -ast-dump | FileCheck %s --check-prefixes=CHECK,CXX11,CXX14 // RUN: %clang_cc1 -std=c++1z %s -fexceptions -fcxx-exceptions -pedantic-errors -triple i386-windows-pc -ast-dump | FileCheck %s --check-prefixes=CHECK,CXX11,CXX14 -namespace dr1772 { // dr1772: 14 +namespace cwg1772 { // cwg1772: 14 // __func__ in a lambda should name operator(), not the containing function. - // CHECK: NamespaceDecl{{.+}}dr1772 + // CHECK: NamespaceDecl{{.+}}cwg1772 #if __cplusplus >= 201103L auto x = []() { __func__; }; // CXX11: LambdaExpr @@ -30,10 +30,10 @@ namespace dr1772 { // dr1772: 14 #endif // __cplusplus >= 201103L } -namespace dr1779 { // dr1779: 14 +namespace cwg1779 { // cwg1779: 14 // __func__ in a function template, member function template, or generic // lambda should have a dependent type. - // CHECK: NamespaceDecl{{.+}}dr1779 + // CHECK: NamespaceDecl{{.+}}cwg1779 template void FuncTemplate() { diff --git a/clang/test/CXX/drs/dr1807.cpp b/clang/test/CXX/drs/cwg1807.cpp similarity index 83% rename from clang/test/CXX/drs/dr1807.cpp rename to clang/test/CXX/drs/cwg1807.cpp index 81e1e8ca640e..59edacc49658 100644 --- a/clang/test/CXX/drs/dr1807.cpp +++ b/clang/test/CXX/drs/cwg1807.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 -namespace dr1807 { // dr1807: 3.0 +namespace cwg1807 { // cwg1807: 3.0 struct S { S() {} ~S() {} @@ -17,12 +17,12 @@ void f() { } } -// CHECK-LABEL: define dso_local void @dr1807::f() -// CHECK: invoke void @dr1807::S::S(){{.+}} +// CHECK-LABEL: define dso_local void @cwg1807::f() +// CHECK: invoke void @cwg1807::S::S(){{.+}} // CHECK-NEXT: {{.+}} unwind label %lpad // CHECK-LABEL: lpad: // CHECK: br {{.+}}, label {{.+}}, label %arraydestroy.body // CHECK-LABEL: arraydestroy.body: // CHECK: [[ARRAYDESTROY_ELEMENT:%.*]] = getelementptr {{.+}}, i64 -1 -// CXX98-NEXT: invoke void @dr1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]]) -// SINCE-CXX11-NEXT: call void @dr1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]]) +// CXX98-NEXT: invoke void @cwg1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]]) +// SINCE-CXX11-NEXT: call void @cwg1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]]) diff --git a/clang/test/CXX/drs/dr185.cpp b/clang/test/CXX/drs/cwg185.cpp similarity index 85% rename from clang/test/CXX/drs/dr185.cpp rename to clang/test/CXX/drs/cwg185.cpp index aff00f1a8764..8ab5bc5d28f8 100644 --- a/clang/test/CXX/drs/dr185.cpp +++ b/clang/test/CXX/drs/cwg185.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr185 { // dr185: 2.7 +namespace cwg185 { // cwg185: 2.7 struct A { mutable int value; explicit A(int i) : value(i) {} @@ -20,11 +20,11 @@ int foo() { return n.value; } -// CHECK-LABEL: define {{.*}} i32 @dr185::foo() -// CHECK: call void @dr185::A::A(int)(ptr {{[^,]*}} %ref.tmp, {{.*}}) +// CHECK-LABEL: define {{.*}} i32 @cwg185::foo() +// CHECK: call void @cwg185::A::A(int)(ptr {{[^,]*}} %ref.tmp, {{.*}}) // CHECK: store ptr %ref.tmp, ptr %t // CHECK-NOT: %t = -// CHECK: [[DR185_T:%.+]] = load ptr, ptr %t -// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{[^,]*}} %n, ptr {{[^,]*}} [[DR185_T]], {{.*}}) +// CHECK: [[CWG185_T:%.+]] = load ptr, ptr %t +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{[^,]*}} %n, ptr {{[^,]*}} [[CWG185_T]], {{.*}}) // CHECK-LABEL: } -} // namespace dr185 +} // namespace cwg185 diff --git a/clang/test/CXX/drs/dr193.cpp b/clang/test/CXX/drs/cwg193.cpp similarity index 79% rename from clang/test/CXX/drs/dr193.cpp rename to clang/test/CXX/drs/cwg193.cpp index c010dad50e40..0a6ac38941d2 100644 --- a/clang/test/CXX/drs/dr193.cpp +++ b/clang/test/CXX/drs/cwg193.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr193 { // dr193: 2.7 +namespace cwg193 { // cwg193: 2.7 struct A { ~A() NOTHROW {} }; @@ -35,12 +35,12 @@ void foo() { } // skipping over D1 (complete object destructor) -// CHECK-LABEL: define {{.*}} void @dr193::D::~D(){{.*}} -// CHECK-LABEL: define {{.*}} void @dr193::D::~D(){{.*}} -// CHECK-NOT: call void @dr193::A::~A() -// CHECK-NOT: call void @dr193::B::~B() -// CHECK: call void @dr193::C::~C() -// CHECK: call void @dr193::B::~B() -// CHECK: call void @dr193::A::~A() +// CHECK-LABEL: define {{.*}} void @cwg193::D::~D(){{.*}} +// CHECK-LABEL: define {{.*}} void @cwg193::D::~D(){{.*}} +// CHECK-NOT: call void @cwg193::A::~A() +// CHECK-NOT: call void @cwg193::B::~B() +// CHECK: call void @cwg193::C::~C() +// CHECK: call void @cwg193::B::~B() +// CHECK: call void @cwg193::A::~A() // CHECK-LABEL: } -} // namespace dr193 +} // namespace cwg193 diff --git a/clang/test/CXX/drs/dr199.cpp b/clang/test/CXX/drs/cwg199.cpp similarity index 85% rename from clang/test/CXX/drs/dr199.cpp rename to clang/test/CXX/drs/cwg199.cpp index 7517d79680c6..5d2e5110786f 100644 --- a/clang/test/CXX/drs/dr199.cpp +++ b/clang/test/CXX/drs/cwg199.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr199 { // dr199: 2.8 +namespace cwg199 { // cwg199: 2.8 struct A { ~A() NOTHROW {} }; @@ -25,9 +25,9 @@ void foo() { A(), B(); } -// CHECK-LABEL: define {{.*}} void @dr199::foo() -// CHECK-NOT: call void @dr199::A::~A() -// CHECK: call void @dr199::B::~B() -// CHECK: call void @dr199::A::~A() +// CHECK-LABEL: define {{.*}} void @cwg199::foo() +// CHECK-NOT: call void @cwg199::A::~A() +// CHECK: call void @cwg199::B::~B() +// CHECK: call void @cwg199::A::~A() // CHECK-LABEL: } -} // namespace dr199 +} // namespace cwg199 diff --git a/clang/test/CXX/drs/dr201.cpp b/clang/test/CXX/drs/cwg201.cpp similarity index 82% rename from clang/test/CXX/drs/dr201.cpp rename to clang/test/CXX/drs/cwg201.cpp index 7e864981e13b..b6cf92a1fc74 100644 --- a/clang/test/CXX/drs/dr201.cpp +++ b/clang/test/CXX/drs/cwg201.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr201 { // dr201: 2.8 +namespace cwg201 { // cwg201: 2.8 extern void full_expr_fence() NOTHROW; @@ -31,12 +31,12 @@ void foo() { full_expr_fence(); } -// CHECK-LABEL: define {{.*}} void @dr201::foo() -// CHECK: call void @dr201::full_expr_fence() -// CHECK: call void @dr201::B::B(dr201::A) -// CHECK: call void @dr201::A::~A() -// CHECK: call void @dr201::full_expr_fence() -// CHECK: call void @dr201::B::~B() +// CHECK-LABEL: define {{.*}} void @cwg201::foo() +// CHECK: call void @cwg201::full_expr_fence() +// CHECK: call void @cwg201::B::B(cwg201::A) +// CHECK: call void @cwg201::A::~A() +// CHECK: call void @cwg201::full_expr_fence() +// CHECK: call void @cwg201::B::~B() // CHECK-LABEL: } -} // namespace dr201 +} // namespace cwg201 diff --git a/clang/test/CXX/drs/dr210.cpp b/clang/test/CXX/drs/cwg210.cpp similarity index 91% rename from clang/test/CXX/drs/dr210.cpp rename to clang/test/CXX/drs/cwg210.cpp index 156ee81093b4..2c3cf61a6a5b 100644 --- a/clang/test/CXX/drs/dr210.cpp +++ b/clang/test/CXX/drs/cwg210.cpp @@ -13,7 +13,7 @@ #pragma clang diagnostic pop #endif -namespace dr210 { // dr210: 2.7 +namespace cwg210 { // cwg210: 2.7 struct B { long i; B(); @@ -33,9 +33,9 @@ void toss(const B* b) { throw *b; } -// CHECK-LABEL: define {{.*}} void @dr210::toss(dr210::B const*) +// CHECK-LABEL: define {{.*}} void @cwg210::toss(cwg210::B const*) // CHECK: %[[EXCEPTION:.*]] = call ptr @__cxa_allocate_exception(i64 16) -// CHECK: call void @__cxa_throw(ptr %[[EXCEPTION]], ptr @typeinfo for dr210::B, ptr @dr210::B::~B()) +// CHECK: call void @__cxa_throw(ptr %[[EXCEPTION]], ptr @typeinfo for cwg210::B, ptr @cwg210::B::~B()) // CHECK-LABEL: } -} // namespace dr210 +} // namespace cwg210 diff --git a/clang/test/CXX/drs/dr2335.cpp b/clang/test/CXX/drs/cwg2335.cpp similarity index 56% rename from clang/test/CXX/drs/dr2335.cpp rename to clang/test/CXX/drs/cwg2335.cpp index 33eebb2c4a5c..8b00a9d2d98a 100644 --- a/clang/test/CXX/drs/dr2335.cpp +++ b/clang/test/CXX/drs/cwg2335.cpp @@ -10,7 +10,7 @@ // expected-no-diagnostics #endif -namespace dr2335 { // dr2335: no drafting 2018-06 +namespace cwg2335 { // cwg2335: no drafting 2018-06 // FIXME: current consensus is that the examples are well-formed. #if __cplusplus >= 201402L namespace ex1 { @@ -25,24 +25,24 @@ namespace ex2 { template struct X {}; template struct partition_indices { static auto compute_right() { return X(); } - // since-cxx14-error@-1 {{no member 'I' in 'dr2335::ex2::partition_indices'; it has not yet been instantiated}} - // since-cxx14-note@#dr2335-ex2-right {{in instantiation of member function 'dr2335::ex2::partition_indices::compute_right' requested here}} - // since-cxx14-note@#dr2335-ex2-inst {{in instantiation of template class 'dr2335::ex2::partition_indices' requested here}} - // since-cxx14-note@#dr2335-ex2-I {{not-yet-instantiated member is declared here}} - static constexpr auto right = compute_right; // #dr2335-ex2-right - static constexpr int I = sizeof(T); // #dr2335-ex2-I + // since-cxx14-error@-1 {{no member 'I' in 'cwg2335::ex2::partition_indices'; it has not yet been instantiated}} + // since-cxx14-note@#cwg2335-ex2-right {{in instantiation of member function 'cwg2335::ex2::partition_indices::compute_right' requested here}} + // since-cxx14-note@#cwg2335-ex2-inst {{in instantiation of template class 'cwg2335::ex2::partition_indices' requested here}} + // since-cxx14-note@#cwg2335-ex2-I {{not-yet-instantiated member is declared here}} + static constexpr auto right = compute_right; // #cwg2335-ex2-right + static constexpr int I = sizeof(T); // #cwg2335-ex2-I }; -template struct partition_indices; // #dr2335-ex2-inst +template struct partition_indices; // #cwg2335-ex2-inst } // namespace ex2 namespace ex3 { struct partition_indices { - static auto compute_right() {} // #dr2335-compute_right - static constexpr auto right = compute_right; // #dr2335-ex3-right + static auto compute_right() {} // #cwg2335-compute_right + static constexpr auto right = compute_right; // #cwg2335-ex3-right // since-cxx14-error@-1 {{function 'compute_right' with deduced return type cannot be used before it is defined}} - // since-cxx14-note@#dr2335-compute_right {{'compute_right' declared here}} - // since-cxx14-error@#dr2335-ex3-right {{declaration of variable 'right' with deduced type 'const auto' requires an initializer}} + // since-cxx14-note@#cwg2335-compute_right {{'compute_right' declared here}} + // since-cxx14-error@#cwg2335-ex3-right {{declaration of variable 'right' with deduced type 'const auto' requires an initializer}} }; } // namespace ex3 #endif -} // namespace dr2335 +} // namespace cwg2335 diff --git a/clang/test/CXX/drs/dr2390.cpp b/clang/test/CXX/drs/cwg2390.cpp similarity index 98% rename from clang/test/CXX/drs/dr2390.cpp rename to clang/test/CXX/drs/cwg2390.cpp index 3931365b568c..41bbd0d1c549 100644 --- a/clang/test/CXX/drs/dr2390.cpp +++ b/clang/test/CXX/drs/cwg2390.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -E -P %s -o - | FileCheck %s -// dr2390: 14 +// cwg2390: 14 namespace PR48462 { // Test that macro expansion of the builtin argument works. diff --git a/clang/test/CXX/drs/dr2504.cpp b/clang/test/CXX/drs/cwg2504.cpp similarity index 90% rename from clang/test/CXX/drs/dr2504.cpp rename to clang/test/CXX/drs/cwg2504.cpp index 686ea73cd6a0..fa775df327cb 100644 --- a/clang/test/CXX/drs/dr2504.cpp +++ b/clang/test/CXX/drs/cwg2504.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 -namespace dr2504 { // dr2504: no +namespace cwg2504 { // cwg2504: no #if __cplusplus >= 201103L struct V { V() = default; V(int); }; struct Q { Q(); }; @@ -27,11 +27,11 @@ void foo() { C c; } // bar is not invoked, because the V subobject is not initia // we are not supposed to unconditionally call `bar()` and call a constructor // inherited from `V`. -// SINCE-CXX11-LABEL: define linkonce_odr void @dr2504::B::B() +// SINCE-CXX11-LABEL: define linkonce_odr void @cwg2504::B::B() // SINCE-CXX11-NOT: br -// SINCE-CXX11: call noundef i32 @dr2504::bar() +// SINCE-CXX11: call noundef i32 @cwg2504::bar() // SINCE-CXX11-NOT: br -// SINCE-CXX11: call void @dr2504::A::A(int) +// SINCE-CXX11: call void @cwg2504::A::A(int) // SINCE-CXX11-LABEL: } // CHECK: {{.*}} diff --git a/clang/test/CXX/drs/dr292.cpp b/clang/test/CXX/drs/cwg292.cpp similarity index 91% rename from clang/test/CXX/drs/dr292.cpp rename to clang/test/CXX/drs/cwg292.cpp index 19caeef291fa..b05d3b92d627 100644 --- a/clang/test/CXX/drs/dr292.cpp +++ b/clang/test/CXX/drs/cwg292.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr292 { // dr292: 2.9 +namespace cwg292 { // cwg292: 2.9 extern int g(); @@ -18,13 +18,13 @@ void f() { new A(g()); } -// CHECK-LABEL: define {{.*}} void @dr292::f()() +// CHECK-LABEL: define {{.*}} void @cwg292::f()() // CHECK: %[[CALL:.+]] = call {{.*}} @operator new(unsigned long)({{.*}}) -// CHECK: invoke {{.*}} i32 @dr292::g()() +// CHECK: invoke {{.*}} i32 @cwg292::g()() // CHECK-NEXT: to {{.*}} unwind label %lpad // CHECK-LABEL: lpad: // CHECK: call void @operator delete(void*)(ptr {{.*}} %[[CALL]]) // CHECK-LABEL: eh.resume: // CHECK-LABEL: } -} // namespace dr292 +} // namespace cwg292 diff --git a/clang/test/CXX/drs/dr392.cpp b/clang/test/CXX/drs/cwg392.cpp similarity index 88% rename from clang/test/CXX/drs/dr392.cpp rename to clang/test/CXX/drs/cwg392.cpp index 26e6259f7196..e118dd7bdb5c 100644 --- a/clang/test/CXX/drs/dr392.cpp +++ b/clang/test/CXX/drs/cwg392.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr392 { // dr392: 2.8 +namespace cwg392 { // cwg392: 2.8 struct A { operator bool() NOTHROW; @@ -32,9 +32,9 @@ void f() if (C().get()) {} } -} // namespace dr392 +} // namespace cwg392 -// CHECK-LABEL: define {{.*}} void @dr392::f()() -// CHECK: call {{.*}} i1 @dr392::A::operator bool() -// CHECK: call void @dr392::C::~C() +// CHECK-LABEL: define {{.*}} void @cwg392::f()() +// CHECK: call {{.*}} i1 @cwg392::A::operator bool() +// CHECK: call void @cwg392::C::~C() // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr412.cpp b/clang/test/CXX/drs/cwg412.cpp similarity index 99% rename from clang/test/CXX/drs/dr412.cpp rename to clang/test/CXX/drs/cwg412.cpp index 8ea29135d1df..7e75bececac8 100644 --- a/clang/test/CXX/drs/dr412.cpp +++ b/clang/test/CXX/drs/cwg412.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= // RUN: %clang_cc1 -std=c++2c %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= -// dr412: 3.4 +// cwg412: 3.4 // lwg404: yes // lwg2340: yes diff --git a/clang/test/CXX/drs/dr438.cpp b/clang/test/CXX/drs/cwg438.cpp similarity index 94% rename from clang/test/CXX/drs/dr438.cpp rename to clang/test/CXX/drs/cwg438.cpp index a6ed39b88c24..5f2fb7c70d87 100644 --- a/clang/test/CXX/drs/dr438.cpp +++ b/clang/test/CXX/drs/cwg438.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr438 { // dr438: 2.7 +namespace cwg438 { // cwg438: 2.7 void f() { long A[2]; @@ -14,9 +14,9 @@ void f() { A[A[0]] = 1; } -} // namespace dr438 +} // namespace cwg438 -// CHECK-LABEL: define {{.*}} void @dr438::f()() +// CHECK-LABEL: define {{.*}} void @cwg438::f()() // CHECK: [[A:%.+]] = alloca [2 x i64] // CHECK: {{.+}} = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0 // CHECK: [[ARRAYIDX1:%.+]] = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0 diff --git a/clang/test/CXX/drs/dr439.cpp b/clang/test/CXX/drs/cwg439.cpp similarity index 94% rename from clang/test/CXX/drs/dr439.cpp rename to clang/test/CXX/drs/cwg439.cpp index 46960af93bb9..e409b803797f 100644 --- a/clang/test/CXX/drs/dr439.cpp +++ b/clang/test/CXX/drs/cwg439.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr439 { // dr439: 2.7 +namespace cwg439 { // cwg439: 2.7 void f() { int* p1 = new int; @@ -14,12 +14,12 @@ void f() { bool b = p1 == p2; // b will have the value true. } -} // namespace dr439 +} // namespace cwg439 // We're checking that p2 was copied from p1, and then was carried over // to the comparison without change. -// CHECK-LABEL: define {{.*}} void @dr439::f()() +// CHECK-LABEL: define {{.*}} void @cwg439::f()() // CHECK: [[P1:%.+]] = alloca ptr, align 8 // CHECK-NEXT: [[P2:%.+]] = alloca ptr, align 8 // CHECK: [[TEMP0:%.+]] = load ptr, ptr [[P1]] diff --git a/clang/test/CXX/drs/dr441.cpp b/clang/test/CXX/drs/cwg441.cpp similarity index 76% rename from clang/test/CXX/drs/dr441.cpp rename to clang/test/CXX/drs/cwg441.cpp index 6504bba689d2..5f566f230193 100644 --- a/clang/test/CXX/drs/dr441.cpp +++ b/clang/test/CXX/drs/cwg441.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr441 { // dr441: 2.7 +namespace cwg441 { // cwg441: 2.7 struct A { A() {} @@ -17,21 +17,21 @@ int i; int& ir = i; int* ip = &i; -} // namespace dr441 +} // namespace cwg441 -// CHECK-DAG: @dr441::dynamic_init = global %"struct.dr441::A" zeroinitializer -// CHECK-DAG: @dr441::i = global i32 0 -// CHECK-DAG: @dr441::ir = constant ptr @dr441::i -// CHECK-DAG: @dr441::ip = global ptr @dr441::i -// CHECK-DAG: @llvm.global_ctors = appending global [{{.+}}] [{ {{.+}} } { {{.+}}, ptr @_GLOBAL__sub_I_dr441.cpp, {{.+}} }] +// CHECK-DAG: @cwg441::dynamic_init = global %"struct.cwg441::A" zeroinitializer +// CHECK-DAG: @cwg441::i = global i32 0 +// CHECK-DAG: @cwg441::ir = constant ptr @cwg441::i +// CHECK-DAG: @cwg441::ip = global ptr @cwg441::i +// CHECK-DAG: @llvm.global_ctors = appending global [{{.+}}] [{ {{.+}} } { {{.+}}, ptr @_GLOBAL__sub_I_cwg441.cpp, {{.+}} }] // CHECK-LABEL: define {{.*}} void @__cxx_global_var_init() // CHECK-NEXT: entry: -// CHECK-NEXT: call void @dr441::A::A()({{.*}} @dr441::dynamic_init) +// CHECK-NEXT: call void @cwg441::A::A()({{.*}} @cwg441::dynamic_init) // CHECK-NEXT: ret void // CHECK-NEXT: } -// CHECK-LABEL: define {{.*}} void @_GLOBAL__sub_I_dr441.cpp() +// CHECK-LABEL: define {{.*}} void @_GLOBAL__sub_I_cwg441.cpp() // CHECK-NEXT: entry: // CHECK-NEXT: call void @__cxx_global_var_init() // CHECK-NEXT: ret void diff --git a/clang/test/CXX/drs/dr462.cpp b/clang/test/CXX/drs/cwg462.cpp similarity index 87% rename from clang/test/CXX/drs/dr462.cpp rename to clang/test/CXX/drs/cwg462.cpp index 2b268778ea10..bdbcacd733bb 100644 --- a/clang/test/CXX/drs/dr462.cpp +++ b/clang/test/CXX/drs/cwg462.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr462 { // dr462: 2.7 +namespace cwg462 { // cwg462: 2.7 struct A { ~A() NOTHROW {} @@ -25,9 +25,9 @@ void f() { full_expr_fence(); } -} // namespace dr462 +} // namespace cwg462 -// CHECK-LABEL: define {{.*}} void @dr462::f()() -// CHECK: call void @dr462::full_expr_fence()() -// CHECK: call void @dr462::A::~A() +// CHECK-LABEL: define {{.*}} void @cwg462::f()() +// CHECK: call void @cwg462::full_expr_fence()() +// CHECK: call void @cwg462::A::~A() // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr492.cpp b/clang/test/CXX/drs/cwg492.cpp similarity index 94% rename from clang/test/CXX/drs/dr492.cpp rename to clang/test/CXX/drs/cwg492.cpp index f53f1cb54124..7fc46b04d72b 100644 --- a/clang/test/CXX/drs/dr492.cpp +++ b/clang/test/CXX/drs/cwg492.cpp @@ -18,7 +18,7 @@ struct type_info { }; } -namespace dr492 { // dr492: 2.7 +namespace cwg492 { // cwg492: 2.7 void f() { typeid(int).name(); @@ -27,9 +27,9 @@ void f() { typeid(const volatile int).name(); } -} // namespace dr492 +} // namespace cwg492 -// CHECK-LABEL: define {{.*}} void @dr492::f()() +// CHECK-LABEL: define {{.*}} void @cwg492::f()() // CHECK: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int) // CHECK-NEXT: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int) // CHECK-NEXT: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int) diff --git a/clang/test/CXX/drs/dr519.cpp b/clang/test/CXX/drs/cwg519.cpp similarity index 95% rename from clang/test/CXX/drs/dr519.cpp rename to clang/test/CXX/drs/cwg519.cpp index 67c01d95ef7c..ce8a1cc95f60 100644 --- a/clang/test/CXX/drs/dr519.cpp +++ b/clang/test/CXX/drs/cwg519.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr519 { // dr519: 2.7 +namespace cwg519 { // cwg519: 2.7 void f() { int *a = 0; void *v = a; @@ -16,12 +16,12 @@ void f() { int *b = static_cast(w); bool c2 = b == static_cast(0); } -} // namespace dr519 +} // namespace cwg519 // We're checking that `null`s that were initially stored in `a` and `w` // are simply copied over all the way to respective comparisons with `null`. -// CHECK-LABEL: define {{.*}} void @dr519::f()() +// CHECK-LABEL: define {{.*}} void @cwg519::f()() // CHECK: store ptr null, ptr [[A:%.+]], // CHECK-NEXT: [[TEMP_A:%.+]] = load ptr, ptr [[A]] // CHECK-NEXT: store ptr [[TEMP_A]], ptr [[V:%.+]], diff --git a/clang/test/CXX/drs/dr571.cpp b/clang/test/CXX/drs/cwg571.cpp similarity index 91% rename from clang/test/CXX/drs/dr571.cpp rename to clang/test/CXX/drs/cwg571.cpp index 19a85b7ddc35..9f0f455fb727 100644 --- a/clang/test/CXX/drs/dr571.cpp +++ b/clang/test/CXX/drs/cwg571.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr571 { // dr571: 2.7 +namespace cwg571 { // cwg571: 2.7 typedef int &ir; int n; const ir r = n; @@ -16,5 +16,5 @@ namespace dr571 { // dr571: 2.7 // Entities have external linkage by default. -// CHECK: @dr571::r = constant ptr @dr571::n -// CHECK: @dr571::r2 = constant ptr @dr571::n +// CHECK: @cwg571::r = constant ptr @cwg571::n +// CHECK: @cwg571::r2 = constant ptr @cwg571::n diff --git a/clang/test/CXX/drs/dr605.cpp b/clang/test/CXX/drs/cwg605.cpp similarity index 91% rename from clang/test/CXX/drs/dr605.cpp rename to clang/test/CXX/drs/cwg605.cpp index 6c212d8dabc0..2fd9e8155bf7 100644 --- a/clang/test/CXX/drs/dr605.cpp +++ b/clang/test/CXX/drs/cwg605.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr605 { // dr605: 2.7 +namespace cwg605 { // cwg605: 2.7 template static T f(T t) {} @@ -18,6 +18,6 @@ void g(int a) { f(a); } -} // namespace dr605 +} // namespace cwg605 -// CHECK: define internal {{.*}} i32 @int dr605::f(int) +// CHECK: define internal {{.*}} i32 @int cwg605::f(int) diff --git a/clang/test/CXX/drs/dr650.cpp b/clang/test/CXX/drs/cwg650.cpp similarity index 86% rename from clang/test/CXX/drs/dr650.cpp rename to clang/test/CXX/drs/cwg650.cpp index 715b4fdf04a7..dcb844095b05 100644 --- a/clang/test/CXX/drs/dr650.cpp +++ b/clang/test/CXX/drs/cwg650.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr650 { // dr650: 2.8 +namespace cwg650 { // cwg650: 2.8 struct Q { ~Q() NOTHROW; @@ -31,10 +31,10 @@ const S& f() { return (R(), S()); } -} // namespace dr650 +} // namespace cwg650 -// CHECK-LABEL: define {{.*}} @dr650::f()() -// CHECK: call void @dr650::S::~S() -// CHECK: call void @dr650::R::~R() -// CHECK: call void @dr650::Q::~Q() +// CHECK-LABEL: define {{.*}} @cwg650::f()() +// CHECK: call void @cwg650::S::~S() +// CHECK: call void @cwg650::R::~R() +// CHECK: call void @cwg650::Q::~Q() // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr653.cpp b/clang/test/CXX/drs/cwg653.cpp similarity index 92% rename from clang/test/CXX/drs/dr653.cpp rename to clang/test/CXX/drs/cwg653.cpp index fd1f0153bfb7..3aeb394347ea 100644 --- a/clang/test/CXX/drs/dr653.cpp +++ b/clang/test/CXX/drs/cwg653.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr653 { // dr653: 2.7 +namespace cwg653 { // cwg653: 2.7 union U { int a; @@ -18,8 +18,8 @@ void f(U u) { v = u; } -} // namespace dr653 +} // namespace cwg653 -// CHECK-LABEL: define {{.*}} void @dr653::f(dr653::U) +// CHECK-LABEL: define {{.*}} void @cwg653::f(cwg653::U) // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %v, ptr {{.*}} %u, {{.*}}) // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr658.cpp b/clang/test/CXX/drs/cwg658.cpp similarity index 92% rename from clang/test/CXX/drs/dr658.cpp rename to clang/test/CXX/drs/cwg658.cpp index 51034c2af3bf..2f7f1ad7deda 100644 --- a/clang/test/CXX/drs/dr658.cpp +++ b/clang/test/CXX/drs/cwg658.cpp @@ -6,17 +6,17 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr658 { // dr658: 2.7 +namespace cwg658 { // cwg658: 2.7 void f(int* p1) { char* p2 = reinterpret_cast(p1); } -} // namespace dr658 +} // namespace cwg658 // We're checking that p1 is stored into p2 without changes. -// CHECK-LABEL: define {{.*}} void @dr658::f(int*)(ptr noundef %p1) +// CHECK-LABEL: define {{.*}} void @cwg658::f(int*)(ptr noundef %p1) // CHECK: [[P1_ADDR:%.+]] = alloca ptr, align 8 // CHECK-NEXT: [[P2:%.+]] = alloca ptr, align 8 // CHECK: store ptr %p1, ptr [[P1_ADDR]] diff --git a/clang/test/CXX/drs/dr661.cpp b/clang/test/CXX/drs/cwg661.cpp similarity index 91% rename from clang/test/CXX/drs/dr661.cpp rename to clang/test/CXX/drs/cwg661.cpp index 4e97bb708847..557213171070 100644 --- a/clang/test/CXX/drs/dr661.cpp +++ b/clang/test/CXX/drs/cwg661.cpp @@ -6,9 +6,9 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr661 { +namespace cwg661 { -void f(int a, int b) { // dr661: 2.7 +void f(int a, int b) { // cwg661: 2.7 a == b; a != b; a < b; @@ -17,9 +17,9 @@ void f(int a, int b) { // dr661: 2.7 a >= b; } -} // namespace dr661 +} // namespace cwg661 -// CHECK-LABEL: define {{.*}} void @dr661::f(int, int) +// CHECK-LABEL: define {{.*}} void @cwg661::f(int, int) // CHECK: icmp eq // CHECK: icmp ne // CHECK: icmp slt diff --git a/clang/test/CXX/drs/dr672.cpp b/clang/test/CXX/drs/cwg672.cpp similarity index 91% rename from clang/test/CXX/drs/dr672.cpp rename to clang/test/CXX/drs/cwg672.cpp index d5f0530ecbc9..07a64eaaf826 100644 --- a/clang/test/CXX/drs/dr672.cpp +++ b/clang/test/CXX/drs/cwg672.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr672 { // dr672: 2.7 +namespace cwg672 { // cwg672: 2.7 struct A { A() NOTHROW; @@ -22,11 +22,11 @@ void f() { A *a = new A; } -} // namespace dr672 +} // namespace cwg672 -// CHECK-LABEL: define {{.*}} void @dr672::f()() +// CHECK-LABEL: define {{.*}} void @cwg672::f()() // CHECK: [[A:%.+]] = alloca ptr // CHECK: [[CALL:%.+]] = call {{.*}} ptr @operator new(unsigned long) -// CHECK: call void @dr672::A::A() +// CHECK: call void @cwg672::A::A() // CHECK: store ptr [[CALL]], ptr [[A]] // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr593.cpp b/clang/test/CXX/drs/cwgr593.cpp similarity index 93% rename from clang/test/CXX/drs/dr593.cpp rename to clang/test/CXX/drs/cwgr593.cpp index 4998af966ebb..d747f4e4a161 100644 --- a/clang/test/CXX/drs/dr593.cpp +++ b/clang/test/CXX/drs/cwgr593.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr593 { // dr593: 2.8 +namespace cwg593 { // cwg593: 2.8 void f(); void fence() NOTHROW; @@ -29,7 +29,7 @@ void g() { A(); } -} // namespace dr593 +} // namespace cwg593 -// CHECK: call void @dr593::fence()() +// CHECK: call void @cwg593::fence()() // CHECK-NEXT: invoke void @__cxa_rethrow() diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp index 5959f0a0c8dd..a304862885c6 100644 --- a/clang/test/CXX/drs/dr0xx.cpp +++ b/clang/test/CXX/drs/dr0xx.cpp @@ -5,44 +5,44 @@ // RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -namespace dr1 { // dr1: no - namespace X { extern "C" void dr1_f(int a = 1); } - namespace Y { extern "C" void dr1_f(int a = 1); } - using X::dr1_f; using Y::dr1_f; +namespace cwg1 { // cwg1: no + namespace X { extern "C" void cwg1_f(int a = 1); } + namespace Y { extern "C" void cwg1_f(int a = 1); } + using X::cwg1_f; using Y::cwg1_f; void g() { - dr1_f(0); + cwg1_f(0); // FIXME: This should be rejected, due to the ambiguous default argument. - dr1_f(); + cwg1_f(); } namespace X { - using Y::dr1_f; + using Y::cwg1_f; void h() { - dr1_f(0); + cwg1_f(0); // FIXME: This should be rejected, due to the ambiguous default argument. - dr1_f(); + cwg1_f(); } } namespace X { void z(int); } - void X::z(int = 1) {} // #dr1-z + void X::z(int = 1) {} // #cwg1-z namespace X { void z(int = 1); // expected-error@-1 {{redefinition of default argument}} - // expected-note@#dr1-z {{previous definition is here}} + // expected-note@#cwg1-z {{previous definition is here}} } void i(int = 1); void j() { void i(int = 1); - using dr1::i; + using cwg1::i; i(0); // FIXME: This should be rejected, due to the ambiguous default argument. i(); } void k() { - using dr1::i; + using cwg1::i; void i(int = 1); i(0); // FIXME: This should be rejected, due to the ambiguous default argument. @@ -50,27 +50,27 @@ namespace dr1 { // dr1: no } } -namespace dr3 { // dr3: yes +namespace cwg3 { // cwg3: yes template struct A {}; - template void f(T) { A a; } // #dr3-f-T + template void f(T) { A a; } // #cwg3-f-T template void f(int); template<> struct A {}; - // expected-error@-1 {{explicit specialization of 'dr3::A' after instantiation}} - // expected-note@#dr3-f-T {{implicit instantiation first required here}} + // expected-error@-1 {{explicit specialization of 'cwg3::A' after instantiation}} + // expected-note@#cwg3-f-T {{implicit instantiation first required here}} } -namespace dr4 { // dr4: 2.8 +namespace cwg4 { // cwg4: 2.8 extern "C" { - static void dr4_f(int) {} - static void dr4_f(float) {} - void dr4_g(int) {} // #dr4-g-int - void dr4_g(float) {} - // expected-error@-1 {{conflicting types for 'dr4_g'}} - // expected-note@#dr4-g-int {{previous definition is here}} + static void cwg4_f(int) {} + static void cwg4_f(float) {} + void cwg4_g(int) {} // #cwg4-g-int + void cwg4_g(float) {} + // expected-error@-1 {{conflicting types for 'cwg4_g'}} + // expected-note@#cwg4-g-int {{previous definition is here}} } } -namespace dr5 { // dr5: 3.1 +namespace cwg5 { // cwg5: 3.1 struct A {} a; struct B { B(const A&); @@ -84,24 +84,24 @@ namespace dr5 { // dr5: 3.1 const C c = e; } -namespace dr7 { // dr7: 3.4 +namespace cwg7 { // cwg7: 3.4 class A { public: ~A(); }; - class B : virtual private A {}; // #dr7-B - class C : public B {} c; // #dr7-C - // expected-error@#dr7-C {{inherited virtual base class 'A' has private destructor}} - // expected-note@#dr7-C {{in implicit default constructor for 'dr7::C' first required here}} - // expected-note@#dr7-B {{declared private here}} - // expected-error@#dr7-C {{inherited virtual base class 'A' has private destructor}} - // expected-note@#dr7-C {{in implicit destructor for 'dr7::C' first required here}} - // expected-note@#dr7-B {{declared private here}} + class B : virtual private A {}; // #cwg7-B + class C : public B {} c; // #cwg7-C + // expected-error@#cwg7-C {{inherited virtual base class 'A' has private destructor}} + // expected-note@#cwg7-C {{in implicit default constructor for 'cwg7::C' first required here}} + // expected-note@#cwg7-B {{declared private here}} + // expected-error@#cwg7-C {{inherited virtual base class 'A' has private destructor}} + // expected-note@#cwg7-C {{in implicit destructor for 'cwg7::C' first required here}} + // expected-note@#cwg7-B {{declared private here}} class VeryDerivedC : public B, virtual public A {} vdc; - class X { ~X(); }; // #dr7-X + class X { ~X(); }; // #cwg7-X class Y : X { ~Y() {} }; // expected-error@-1 {{base class 'X' has private destructor}} - // expected-note@#dr7-X {{implicitly declared private here}} + // expected-note@#cwg7-X {{implicitly declared private here}} - namespace PR16370 { // This regressed the first time DR7 was fixed. + namespace PR16370 { // This regressed the first time CWG7 was fixed. struct S1 { virtual ~S1(); }; struct S2 : S1 {}; struct S3 : S2 {}; @@ -114,7 +114,7 @@ namespace dr7 { // dr7: 3.4 } } -namespace dr8 { // dr8: dup 45 +namespace cwg8 { // cwg8: dup 45 class A { struct U; static const int k = 5; @@ -126,23 +126,23 @@ namespace dr8 { // dr8: dup 45 A::T *A::g() { return 0; } } -namespace dr9 { // dr9: 2.8 +namespace cwg9 { // cwg9: 2.8 struct B { protected: - int m; // #dr9-m + int m; // #cwg9-m friend int R1(); }; - struct N : protected B { // #dr9-N + struct N : protected B { // #cwg9-N friend int R2(); } n; int R1() { return n.m; } - // expected-error@-1 {{'m' is a protected member of 'dr9::B'}} - // expected-note@#dr9-N {{constrained by protected inheritance here}} - // expected-note@#dr9-m {{member is declared here}} + // expected-error@-1 {{'m' is a protected member of 'cwg9::B'}} + // expected-note@#cwg9-N {{constrained by protected inheritance here}} + // expected-note@#cwg9-m {{member is declared here}} int R2() { return n.m; } } -namespace dr10 { // dr10: dup 45 +namespace cwg10 { // cwg10: dup 45 class A { struct B { A::B *p; @@ -150,7 +150,7 @@ namespace dr10 { // dr10: dup 45 }; } -namespace dr11 { // dr11: yes +namespace cwg11 { // cwg11: yes template struct A : T { using typename T::U; U u; @@ -164,19 +164,19 @@ namespace dr11 { // dr11: yes A ax; } -namespace dr12 { // dr12: sup 239 +namespace cwg12 { // cwg12: sup 239 enum E { e }; E &f(E, E = e); void g() { int &f(int, E = e); - // Under DR12, these call two different functions. - // Under DR239, they call the same function. + // Under CWG12, these call two different functions. + // Under CWG239, they call the same function. int &b = f(e); int &c = f(1); } } -namespace dr13 { // dr13: no +namespace cwg13 { // cwg13: no extern "C" void f(int); void g(char); @@ -191,60 +191,60 @@ namespace dr13 { // dr13: no int a4 = h(g); } -namespace dr14 { // dr14: 3.4 - namespace X { extern "C" int dr14_f(); } - namespace Y { extern "C" int dr14_f(); } +namespace cwg14 { // cwg14: 3.4 + namespace X { extern "C" int cwg14_f(); } + namespace Y { extern "C" int cwg14_f(); } using namespace X; using namespace Y; - int k = dr14_f(); + int k = cwg14_f(); class C { int k; - friend int Y::dr14_f(); + friend int Y::cwg14_f(); } c; namespace Z { - extern "C" int dr14_f() { return c.k; } + extern "C" int cwg14_f() { return c.k; } } - namespace X { typedef int T; typedef int U; } // #dr14-X-U - namespace Y { typedef int T; typedef long U; } // #dr14-Y-U + namespace X { typedef int T; typedef int U; } // #cwg14-X-U + namespace Y { typedef int T; typedef long U; } // #cwg14-Y-U T t; // ok, same type both times U u; // expected-error@-1 {{reference to 'U' is ambiguous}} - // expected-note@#dr14-X-U {{candidate found by name lookup is 'dr14::X::U'}} - // expected-note@#dr14-Y-U {{candidate found by name lookup is 'dr14::Y::U'}} + // expected-note@#cwg14-X-U {{candidate found by name lookup is 'cwg14::X::U'}} + // expected-note@#cwg14-Y-U {{candidate found by name lookup is 'cwg14::Y::U'}} } -namespace dr15 { // dr15: yes - template void f(int); // #dr15-f-decl-first +namespace cwg15 { // cwg15: yes + template void f(int); // #cwg15-f-decl-first template void f(int = 0); // expected-error@-1 {{default arguments cannot be added to a function template that has already been declared}} - // expected-note@#dr15-f-decl-first {{previous template declaration is here}} + // expected-note@#cwg15-f-decl-first {{previous template declaration is here}} } -namespace dr16 { // dr16: 2.8 - class A { // #dr16-A - void f(); // #dr16-A-f-decl +namespace cwg16 { // cwg16: 2.8 + class A { // #cwg16-A + void f(); // #cwg16-A-f-decl friend class C; }; - class B : A {}; // #dr16-B + class B : A {}; // #cwg16-B class C : B { void g() { f(); - // expected-error@-1 {{'f' is a private member of 'dr16::A'}} - // expected-note@#dr16-B {{constrained by implicitly private inheritance here}} - // expected-note@#dr16-A-f-decl {{member is declared here}} - A::f(); // #dr16-A-f-call - // expected-error@#dr16-A-f-call {{'A' is a private member of 'dr16::A'}} - // expected-note@#dr16-B {{constrained by implicitly private inheritance here}} - // expected-note@#dr16-A {{member is declared here}} - // expected-error@#dr16-A-f-call {{cannot cast 'dr16::C' to its private base class 'dr16::A'}} - // expected-note@#dr16-B {{implicitly declared private here}} + // expected-error@-1 {{'f' is a private member of 'cwg16::A'}} + // expected-note@#cwg16-B {{constrained by implicitly private inheritance here}} + // expected-note@#cwg16-A-f-decl {{member is declared here}} + A::f(); // #cwg16-A-f-call + // expected-error@#cwg16-A-f-call {{'A' is a private member of 'cwg16::A'}} + // expected-note@#cwg16-B {{constrained by implicitly private inheritance here}} + // expected-note@#cwg16-A {{member is declared here}} + // expected-error@#cwg16-A-f-call {{cannot cast 'cwg16::C' to its private base class 'cwg16::A'}} + // expected-note@#cwg16-B {{implicitly declared private here}} } }; } -namespace dr17 { // dr17: yes +namespace cwg17 { // cwg17: yes class A { int n; int f(); @@ -257,38 +257,38 @@ namespace dr17 { // dr17: yes }; } -// dr18: sup 577 +// cwg18: sup 577 -namespace dr19 { // dr19: 3.1 +namespace cwg19 { // cwg19: 3.1 struct A { - int n; // #dr19-n + int n; // #cwg19-n }; - struct B : protected A { // #dr19-B + struct B : protected A { // #cwg19-B }; struct C : B {} c; struct D : B { int get1() { return c.n; } - // expected-error@-1 {{'n' is a protected member of 'dr19::A'}} - // expected-note@#dr19-B {{constrained by protected inheritance here}} - // expected-note@#dr19-n {{member is declared here}} + // expected-error@-1 {{'n' is a protected member of 'cwg19::A'}} + // expected-note@#cwg19-B {{constrained by protected inheritance here}} + // expected-note@#cwg19-n {{member is declared here}} int get2() { return ((A&)c).n; } // ok, A is an accessible base of B from here }; } -namespace dr20 { // dr20: 2.8 +namespace cwg20 { // cwg20: 2.8 class X { public: X(); private: - X(const X&); // #dr20-X-ctor + X(const X&); // #cwg20-X-ctor }; X &f(); X x = f(); - // expected-error@-1 {{calling a private constructor of class 'dr20::X'}} - // expected-note@#dr20-X-ctor {{declared private here}} + // expected-error@-1 {{calling a private constructor of class 'cwg20::X'}} + // expected-note@#cwg20-X-ctor {{declared private here}} } -namespace dr21 { // dr21: 3.4 +namespace cwg21 { // cwg21: 3.4 template struct A; struct X { template friend struct A; @@ -298,25 +298,25 @@ namespace dr21 { // dr21: 3.4 }; } -namespace dr22 { // dr22: sup 481 - template struct X; - // expected-error@-1 {{unknown type name 'dr22_T'}} +namespace cwg22 { // cwg22: sup 481 + template struct X; + // expected-error@-1 {{unknown type name 'cwg22_T'}} typedef int T; template struct Y; } -namespace dr23 { // dr23: yes - template void f(T, T); // #dr23-f-T-T - template void f(T, int); // #dr23-f-T-int +namespace cwg23 { // cwg23: yes + template void f(T, T); // #cwg23-f-T-T + template void f(T, int); // #cwg23-f-T-int void g() { f(0, 0); } // expected-error@-1 {{call to 'f' is ambiguous}} - // expected-note@#dr23-f-T-T {{candidate function [with T = int]}} - // expected-note@#dr23-f-T-int {{candidate function [with T = int]}} + // expected-note@#cwg23-f-T-T {{candidate function [with T = int]}} + // expected-note@#cwg23-f-T-int {{candidate function [with T = int]}} } -// dr24: na +// cwg24: na -namespace dr25 { // dr25: yes +namespace cwg25 { // cwg25: yes struct A { void f() throw(int); // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} @@ -351,7 +351,7 @@ namespace dr25 { // dr25: yes } } -namespace dr26 { // dr26: yes +namespace cwg26 { // cwg26: yes struct A { A(A, const A & = A()); }; // expected-error@-1 {{copy constructor must pass its first argument by reference}} struct B { @@ -371,77 +371,77 @@ namespace dr26 { // dr26: yes }; } -namespace dr27 { // dr27: yes +namespace cwg27 { // cwg27: yes enum E { e } n; E &m = true ? n : n; } -// dr28: na lib +// cwg28: na lib -namespace dr29 { // dr29: 3.4 - void dr29_f0(); // #dr29-f0 - void g0() { void dr29_f0(); } - extern "C++" void g0_cxx() { void dr29_f0(); } - extern "C" void g0_c() { void dr29_f0(); } - // expected-error@-1 {{declaration of 'dr29_f0' has a different language linkage}} - // expected-note@#dr29-f0 {{previous declaration is here}} +namespace cwg29 { // cwg29: 3.4 + void cwg29_f0(); // #cwg29-f0 + void g0() { void cwg29_f0(); } + extern "C++" void g0_cxx() { void cwg29_f0(); } + extern "C" void g0_c() { void cwg29_f0(); } + // expected-error@-1 {{declaration of 'cwg29_f0' has a different language linkage}} + // expected-note@#cwg29-f0 {{previous declaration is here}} - extern "C" void dr29_f1(); // #dr29-f1 - void g1() { void dr29_f1(); } - extern "C" void g1_c() { void dr29_f1(); } - extern "C++" void g1_cxx() { void dr29_f1(); } - // expected-error@-1 {{declaration of 'dr29_f1' has a different language linkage}} - // expected-note@#dr29-f1 {{previous declaration is here}} + extern "C" void cwg29_f1(); // #cwg29-f1 + void g1() { void cwg29_f1(); } + extern "C" void g1_c() { void cwg29_f1(); } + extern "C++" void g1_cxx() { void cwg29_f1(); } + // expected-error@-1 {{declaration of 'cwg29_f1' has a different language linkage}} + // expected-note@#cwg29-f1 {{previous declaration is here}} - void g2() { void dr29_f2(); } // #dr29-f2 - extern "C" void dr29_f2(); - // expected-error@-1 {{declaration of 'dr29_f2' has a different language linkage}} - // expected-note@#dr29-f2 {{previous declaration is here}} + void g2() { void cwg29_f2(); } // #cwg29-f2 + extern "C" void cwg29_f2(); + // expected-error@-1 {{declaration of 'cwg29_f2' has a different language linkage}} + // expected-note@#cwg29-f2 {{previous declaration is here}} - extern "C" void g3() { void dr29_f3(); } // #dr29-f3 - extern "C++" void dr29_f3(); - // expected-error@-1 {{declaration of 'dr29_f3' has a different language linkage}} - // expected-note@#dr29-f3 {{previous declaration is here}} + extern "C" void g3() { void cwg29_f3(); } // #cwg29-f3 + extern "C++" void cwg29_f3(); + // expected-error@-1 {{declaration of 'cwg29_f3' has a different language linkage}} + // expected-note@#cwg29-f3 {{previous declaration is here}} - extern "C++" void g4() { void dr29_f4(); } // #dr29-f4 - extern "C" void dr29_f4(); - // expected-error@-1 {{declaration of 'dr29_f4' has a different language linkage}} - // expected-note@#dr29-f4 {{previous declaration is here}} + extern "C++" void g4() { void cwg29_f4(); } // #cwg29-f4 + extern "C" void cwg29_f4(); + // expected-error@-1 {{declaration of 'cwg29_f4' has a different language linkage}} + // expected-note@#cwg29-f4 {{previous declaration is here}} extern "C" void g5(); - extern "C++" void dr29_f5(); + extern "C++" void cwg29_f5(); void g5() { - void dr29_f5(); // ok, g5 is extern "C" but we're not inside the linkage-specification here. + void cwg29_f5(); // ok, g5 is extern "C" but we're not inside the linkage-specification here. } extern "C++" void g6(); - extern "C" void dr29_f6(); + extern "C" void cwg29_f6(); void g6() { - void dr29_f6(); // ok, g6 is extern "C" but we're not inside the linkage-specification here. + void cwg29_f6(); // ok, g6 is extern "C" but we're not inside the linkage-specification here. } extern "C" void g7(); - extern "C++" void dr29_f7(); // #dr29-f7 + extern "C++" void cwg29_f7(); // #cwg29-f7 extern "C" void g7() { - void dr29_f7(); - // expected-error@-1 {{declaration of 'dr29_f7' has a different language linkage}} - // expected-note@#dr29-f7 {{previous declaration is here}} + void cwg29_f7(); + // expected-error@-1 {{declaration of 'cwg29_f7' has a different language linkage}} + // expected-note@#cwg29-f7 {{previous declaration is here}} } extern "C++" void g8(); - extern "C" void dr29_f8(); // #dr29-f8 + extern "C" void cwg29_f8(); // #cwg29-f8 extern "C++" void g8() { - void dr29_f8(); - // expected-error@-1 {{declaration of 'dr29_f8' has a different language linkage}} - // expected-note@#dr29-f8 {{previous declaration is here}} + void cwg29_f8(); + // expected-error@-1 {{declaration of 'cwg29_f8' has a different language linkage}} + // expected-note@#cwg29-f8 {{previous declaration is here}} } } -namespace dr30 { // dr30: sup 468 c++11 +namespace cwg30 { // cwg30: sup 468 c++11 struct A { template static int f(); } a, *p = &a; - // FIXME: It's not clear whether DR468 applies to C++98 too. + // FIXME: It's not clear whether CWG468 applies to C++98 too. int x = A::template f<0>(); // cxx98-error@-1 {{'template' keyword outside of a template}} int y = a.template f<0>(); @@ -450,29 +450,29 @@ namespace dr30 { // dr30: sup 468 c++11 // cxx98-error@-1 {{'template' keyword outside of a template}} } -namespace dr31 { // dr31: 2.8 +namespace cwg31 { // cwg31: 2.8 class X { private: - void operator delete(void*); // #dr31-delete + void operator delete(void*); // #cwg31-delete }; // We would call X::operator delete if X() threw (even though it can't, // and even though we allocated the X using ::operator delete). X *p = new X; - // expected-error@-1 {{'operator delete' is a private member of 'dr31::X'}} - // expected-note@#dr31-delete {{declared private here}} + // expected-error@-1 {{'operator delete' is a private member of 'cwg31::X'}} + // expected-note@#cwg31-delete {{declared private here}} } -// dr32: na +// cwg32: na -namespace dr33 { // dr33: 9 - namespace X { struct S; void f(void (*)(S)); } // #dr33-f-S - namespace Y { struct T; void f(void (*)(T)); } // #dr33-f-T +namespace cwg33 { // cwg33: 9 + namespace X { struct S; void f(void (*)(S)); } // #cwg33-f-S + namespace Y { struct T; void f(void (*)(T)); } // #cwg33-f-T void g(X::S); template Z g(Y::T); void h() { f(&g); } // expected-error@-1 {{call to 'f' is ambiguous}} - // expected-note@#dr33-f-S {{candidate function}} - // expected-note@#dr33-f-T {{candidate function}} + // expected-note@#cwg33-f-S {{candidate function}} + // expected-note@#cwg33-f-T {{candidate function}} template void t(X::S); template void u(X::S); @@ -507,10 +507,10 @@ namespace dr33 { // dr33: 9 } } -// dr34: na -// dr35: dup 178 +// cwg34: na +// cwg35: dup 178 -namespace dr36 { // dr36: 2.8 +namespace cwg36 { // cwg36: 2.8 namespace example1 { namespace A { int i; @@ -540,25 +540,25 @@ namespace example2 { struct D : virtual B, virtual C { - using B::i; // #dr36-ex2-B-i-first + using B::i; // #cwg36-ex2-B-i-first using B::i; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex2-B-i-first {{previous using declaration}} + // expected-note@#cwg36-ex2-B-i-first {{previous using declaration}} - using C::i; // #dr36-ex2-C-i-first + using C::i; // #cwg36-ex2-C-i-first using C::i; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex2-C-i-first {{previous using declaration}} + // expected-note@#cwg36-ex2-C-i-first {{previous using declaration}} - using B::j; // #dr36-ex2-B-j-first + using B::j; // #cwg36-ex2-B-j-first using B::j; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex2-B-j-first {{previous using declaration}} + // expected-note@#cwg36-ex2-B-j-first {{previous using declaration}} - using C::j; // #dr36-ex2-C-j-first + using C::j; // #cwg36-ex2-C-j-first using C::j; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex2-C-j-first {{previous using declaration}} + // expected-note@#cwg36-ex2-C-j-first {{previous using declaration}} }; } @@ -578,25 +578,25 @@ namespace example3 { template struct D : virtual B, virtual C { - using B::i; // #dr36-ex3-B-i-first + using B::i; // #cwg36-ex3-B-i-first using B::i; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex3-B-i-first {{previous using declaration}} + // expected-note@#cwg36-ex3-B-i-first {{previous using declaration}} - using C::i; // #dr36-ex3-C-i-first + using C::i; // #cwg36-ex3-C-i-first using C::i; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex3-C-i-first {{previous using declaration}} + // expected-note@#cwg36-ex3-C-i-first {{previous using declaration}} - using B::j; // #dr36-ex3-B-j-first + using B::j; // #cwg36-ex3-B-j-first using B::j; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex3-B-j-first {{previous using declaration}} + // expected-note@#cwg36-ex3-B-j-first {{previous using declaration}} - using C::j; // #dr36-ex3-C-j-first + using C::j; // #cwg36-ex3-C-j-first using C::j; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex3-C-j-first {{previous using declaration}} + // expected-note@#cwg36-ex3-C-j-first {{previous using declaration}} }; } namespace example4 { @@ -607,23 +607,23 @@ namespace example4 { template struct G : E { - using E::k; // #dr36-E-k-first + using E::k; // #cwg36-E-k-first using E::k; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-E-k-first {{previous using declaration}} + // expected-note@#cwg36-E-k-first {{previous using declaration}} }; } } -// dr37: sup 475 +// cwg37: sup 475 -namespace dr38 { // dr38: yes +namespace cwg38 { // cwg38: yes template struct X {}; template X operator+(X a, X b) { return a; } template X operator+(X, X); } -namespace dr39 { // dr39: no +namespace cwg39 { // cwg39: no namespace example1 { struct A { int &f(int); }; struct B : A { @@ -635,16 +635,16 @@ namespace dr39 { // dr39: no namespace example2 { struct A { - int &x(int); // #dr39-A-x-decl - static int &y(int); // #dr39-A-y-decl + int &x(int); // #cwg39-A-x-decl + static int &y(int); // #cwg39-A-y-decl }; struct V { int &z(int); }; struct B : A, virtual V { - using A::x; // #dr39-using-A-x + using A::x; // #cwg39-using-A-x float &x(float); - using A::y; // #dr39-using-A-y + using A::y; // #cwg39-using-A-y static float &y(float); using V::z; float &z(float); @@ -652,18 +652,18 @@ namespace dr39 { // dr39: no struct C : A, B, virtual V {} c; /* expected-warning@-1 {{direct base 'A' is inaccessible due to ambiguity: - struct dr39::example2::C -> A - struct dr39::example2::C -> B -> A}} */ + struct cwg39::example2::C -> A + struct cwg39::example2::C -> B -> A}} */ int &x = c.x(0); // expected-error@-1 {{member 'x' found in multiple base classes of different types}} - // expected-note@#dr39-A-x-decl {{member found by ambiguous name lookup}} - // expected-note@#dr39-using-A-x {{member found by ambiguous name lookup}} + // expected-note@#cwg39-A-x-decl {{member found by ambiguous name lookup}} + // expected-note@#cwg39-using-A-x {{member found by ambiguous name lookup}} // FIXME: This is valid, because we find the same static data member either way. int &y = c.y(0); // expected-error@-1 {{member 'y' found in multiple base classes of different types}} - // expected-note@#dr39-A-y-decl {{member found by ambiguous name lookup}} - // expected-note@#dr39-using-A-y {{member found by ambiguous name lookup}} + // expected-note@#cwg39-A-y-decl {{member found by ambiguous name lookup}} + // expected-note@#cwg39-using-A-y {{member found by ambiguous name lookup}} int &z = c.z(0); } @@ -676,63 +676,63 @@ namespace dr39 { // dr39: no } namespace example4 { - struct A { int n; }; // #dr39-ex4-A-n + struct A { int n; }; // #cwg39-ex4-A-n struct B : A {}; struct C : A {}; struct D : B, C { int f() { return n; } }; /* expected-error@-1 {{non-static member 'n' found in multiple base-class subobjects of type 'A': - struct dr39::example4::D -> B -> A - struct dr39::example4::D -> C -> A}} */ - // expected-note@#dr39-ex4-A-n {{member found by ambiguous name lookup}} + struct cwg39::example4::D -> B -> A + struct cwg39::example4::D -> C -> A}} */ + // expected-note@#cwg39-ex4-A-n {{member found by ambiguous name lookup}} } namespace PR5916 { // FIXME: This is valid. - struct A { int n; }; // #dr39-A-n + struct A { int n; }; // #cwg39-A-n struct B : A {}; struct C : A {}; struct D : B, C {}; - int k = sizeof(D::n); // #dr39-sizeof - /* expected-error@#dr39-sizeof + int k = sizeof(D::n); // #cwg39-sizeof + /* expected-error@#cwg39-sizeof {{non-static member 'n' found in multiple base-class subobjects of type 'A': - struct dr39::PR5916::D -> B -> A - struct dr39::PR5916::D -> C -> A}} */ - // expected-note@#dr39-A-n {{member found by ambiguous name lookup}} + struct cwg39::PR5916::D -> B -> A + struct cwg39::PR5916::D -> C -> A}} */ + // expected-note@#cwg39-A-n {{member found by ambiguous name lookup}} - // expected-error@#dr39-sizeof {{unknown type name}} + // expected-error@#cwg39-sizeof {{unknown type name}} #if __cplusplus >= 201103L decltype(D::n) n; /* expected-error@-1 {{non-static member 'n' found in multiple base-class subobjects of type 'A': - struct dr39::PR5916::D -> B -> A - struct dr39::PR5916::D -> C -> A}} */ - // expected-note@#dr39-A-n {{member found by ambiguous name lookup}} + struct cwg39::PR5916::D -> B -> A + struct cwg39::PR5916::D -> C -> A}} */ + // expected-note@#cwg39-A-n {{member found by ambiguous name lookup}} #endif } } -// dr40: na +// cwg40: na -namespace dr41 { // dr41: yes +namespace cwg41 { // cwg41: yes struct S f(S); } -namespace dr42 { // dr42: yes +namespace cwg42 { // cwg42: yes struct A { static const int k = 0; }; struct B : A { static const int k = A::k; }; } -// dr43: na +// cwg43: na -namespace dr44 { // dr44: sup 727 +namespace cwg44 { // cwg44: sup 727 struct A { template void f(); template<> void f<0>(); }; } -namespace dr45 { // dr45: yes +namespace cwg45 { // cwg45: yes class A { class B {}; class C : B {}; @@ -740,27 +740,27 @@ namespace dr45 { // dr45: yes }; } -namespace dr46 { // dr46: yes +namespace cwg46 { // cwg46: yes template struct A { template struct B {}; }; template template struct A::B; // expected-error@-1 {{expected unqualified-id}} } -namespace dr47 { // dr47: sup 329 +namespace cwg47 { // cwg47: sup 329 template struct A { - friend void f() { T t; } // #dr47-f + friend void f() { T t; } // #cwg47-f // expected-error@-1 {{redefinition of 'f'}} - // expected-note@#dr47-b {{in instantiation of template class 'dr47::A' requested here}} - // expected-note@#dr47-f {{previous definition is here}} + // expected-note@#cwg47-b {{in instantiation of template class 'cwg47::A' requested here}} + // expected-note@#cwg47-f {{previous definition is here}} }; A a; - A b; // #dr47-b + A b; // #cwg47-b void f(); void g() { f(); } } -namespace dr48 { // dr48: yes +namespace cwg48 { // cwg48: yes namespace { struct S { static const int m = 0; @@ -776,45 +776,45 @@ namespace dr48 { // dr48: yes const int &c = S::o; } -namespace dr49 { // dr49: 2.8 - template struct A {}; // #dr49-A +namespace cwg49 { // cwg49: 2.8 + template struct A {}; // #cwg49-A int k; #if __has_feature(cxx_constexpr) constexpr #endif - int *const p = &k; // #dr49-p + int *const p = &k; // #cwg49-p A<&k> a; - A

b; // #dr49-b - // cxx98-error@#dr49-b {{non-type template argument referring to object 'p' with internal linkage is a C++11 extension}} - // cxx98-note@#dr49-p {{non-type template argument refers to object here}} - // cxx98-14-error@#dr49-b {{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} - // cxx98-14-note@#dr49-A {{template parameter is declared here}} - int *q = &k; // #dr49-q - A c; // #dr49-c - // cxx98-error@#dr49-c {{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} - // cxx98-note@#dr49-A {{template parameter is declared here}} - // cxx11-14-error@#dr49-c {{non-type template argument of type 'int *' is not a constant expression}} - // cxx11-14-note@#dr49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}} - // cxx11-14-note@#dr49-q {{declared here}} - // cxx11-14-note@#dr49-A {{template parameter is declared here}} - // since-cxx17-error@#dr49-c {{non-type template argument is not a constant expression}} - // since-cxx17-note@#dr49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}} - // since-cxx17-note@#dr49-q {{declared here}} -} - -namespace dr50 { // dr50: yes - struct X; // #dr50-X + A

b; // #cwg49-b + // cxx98-error@#cwg49-b {{non-type template argument referring to object 'p' with internal linkage is a C++11 extension}} + // cxx98-note@#cwg49-p {{non-type template argument refers to object here}} + // cxx98-14-error@#cwg49-b {{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} + // cxx98-14-note@#cwg49-A {{template parameter is declared here}} + int *q = &k; // #cwg49-q + A c; // #cwg49-c + // cxx98-error@#cwg49-c {{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} + // cxx98-note@#cwg49-A {{template parameter is declared here}} + // cxx11-14-error@#cwg49-c {{non-type template argument of type 'int *' is not a constant expression}} + // cxx11-14-note@#cwg49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}} + // cxx11-14-note@#cwg49-q {{declared here}} + // cxx11-14-note@#cwg49-A {{template parameter is declared here}} + // since-cxx17-error@#cwg49-c {{non-type template argument is not a constant expression}} + // since-cxx17-note@#cwg49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}} + // since-cxx17-note@#cwg49-q {{declared here}} +} + +namespace cwg50 { // cwg50: yes + struct X; // #cwg50-X extern X *p; X *q = (X*)p; X *r = static_cast(p); X *s = const_cast(p); X *t = reinterpret_cast(p); X *u = dynamic_cast(p); - // expected-error@-1 {{'dr50::X' is an incomplete type}} - // expected-note@#dr50-X {{forward declaration of 'dr50::X'}} + // expected-error@-1 {{'cwg50::X' is an incomplete type}} + // expected-note@#cwg50-X {{forward declaration of 'cwg50::X'}} } -namespace dr51 { // dr51: 2.8 +namespace cwg51 { // cwg51: 2.8 struct A {}; struct B : A {}; struct S { @@ -824,57 +824,57 @@ namespace dr51 { // dr51: 2.8 A &a = s; } -namespace dr52 { // dr52: 2.8 - struct A { int n; }; // #dr52-A - struct B : private A {} b; // #dr52-B - int k = b.A::n; // #dr52-k +namespace cwg52 { // cwg52: 2.8 + struct A { int n; }; // #cwg52-A + struct B : private A {} b; // #cwg52-B + int k = b.A::n; // #cwg52-k // FIXME: This first diagnostic is very strangely worded, and seems to be bogus. - // expected-error@#dr52-k {{'A' is a private member of 'dr52::A'}} - // expected-note@#dr52-B {{constrained by private inheritance here}} - // expected-note@#dr52-A {{member is declared here}} - // expected-error@#dr52-k {{cannot cast 'struct B' to its private base class 'dr52::A'}} - // expected-note@#dr52-B {{declared private here}} + // expected-error@#cwg52-k {{'A' is a private member of 'cwg52::A'}} + // expected-note@#cwg52-B {{constrained by private inheritance here}} + // expected-note@#cwg52-A {{member is declared here}} + // expected-error@#cwg52-k {{cannot cast 'struct B' to its private base class 'cwg52::A'}} + // expected-note@#cwg52-B {{declared private here}} } -namespace dr53 { // dr53: yes +namespace cwg53 { // cwg53: yes int n = 0; enum E { e } x = static_cast(n); } -namespace dr54 { // dr54: 2.8 +namespace cwg54 { // cwg54: 2.8 struct A { int a; } a; struct V { int v; } v; - struct B : private A, virtual V { int b; } b; // #dr54-B + struct B : private A, virtual V { int b; } b; // #cwg54-B A &sab = static_cast(b); // expected-error@-1 {{cannot cast 'struct B' to its private base class 'A'}} - // expected-note@#dr54-B {{declared private here}} + // expected-note@#cwg54-B {{declared private here}} A *spab = static_cast(&b); // expected-error@-1 {{cannot cast 'struct B' to its private base class 'A'}} - // expected-note@#dr54-B {{declared private here}} + // expected-note@#cwg54-B {{declared private here}} int A::*smab = static_cast(&B::b); - // expected-error@-1 {{cannot cast 'dr54::B' to its private base class 'dr54::A'}} - // expected-note@#dr54-B {{declared private here}} + // expected-error@-1 {{cannot cast 'cwg54::B' to its private base class 'cwg54::A'}} + // expected-note@#cwg54-B {{declared private here}} B &sba = static_cast(a); - // expected-error@-1 {{cannot cast private base class 'dr54::A' to 'dr54::B'}} - // expected-note@#dr54-B {{declared private here}} + // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}} + // expected-note@#cwg54-B {{declared private here}} B *spba = static_cast(&a); - // expected-error@-1 {{cannot cast private base class 'dr54::A' to 'dr54::B'}} - // expected-note@#dr54-B {{declared private here}} + // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}} + // expected-note@#cwg54-B {{declared private here}} int B::*smba = static_cast(&A::a); - // expected-error@-1 {{cannot cast private base class 'dr54::A' to 'dr54::B'}} - // expected-note@#dr54-B {{declared private here}} + // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}} + // expected-note@#cwg54-B {{declared private here}} V &svb = static_cast(b); V *spvb = static_cast(&b); int V::*smvb = static_cast(&B::b); - // expected-error@-1 {{conversion from pointer to member of class 'dr54::B' to pointer to member of class 'dr54::V' via virtual base 'dr54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'cwg54::V' via virtual base 'cwg54::V' is not allowed}} B &sbv = static_cast(v); - // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'dr54::V'}} + // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}} B *spbv = static_cast(&v); - // expected-error@-1 {{cannot cast 'dr54::V *' to 'B *' via virtual base 'dr54::V'}} + // expected-error@-1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}} int B::*smbv = static_cast(&V::v); - // expected-error@-1 {{conversion from pointer to member of class 'dr54::V' to pointer to member of class 'dr54::B' via virtual base 'dr54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'cwg54::B' via virtual base 'cwg54::V' is not allowed}} A &cab = (A&)(b); A *cpab = (A*)(&b); @@ -886,37 +886,37 @@ namespace dr54 { // dr54: 2.8 V &cvb = (V&)(b); V *cpvb = (V*)(&b); int V::*cmvb = (int V::*)(&B::b); - // expected-error@-1 {{conversion from pointer to member of class 'dr54::B' to pointer to member of class 'dr54::V' via virtual base 'dr54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'cwg54::V' via virtual base 'cwg54::V' is not allowed}} B &cbv = (B&)(v); - // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'dr54::V'}} + // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}} B *cpbv = (B*)(&v); - // expected-error@-1 {{cannot cast 'dr54::V *' to 'B *' via virtual base 'dr54::V'}} + // expected-error@-1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}} int B::*cmbv = (int B::*)(&V::v); - // expected-error@-1 {{conversion from pointer to member of class 'dr54::V' to pointer to member of class 'dr54::B' via virtual base 'dr54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'cwg54::B' via virtual base 'cwg54::V' is not allowed}} } -namespace dr55 { // dr55: yes +namespace cwg55 { // cwg55: yes enum E { e = 5 }; int test[(e + 1 == 6) ? 1 : -1]; } -namespace dr56 { // dr56: yes +namespace cwg56 { // cwg56: yes struct A { - typedef int T; // #dr56-typedef-int-T-first + typedef int T; // #cwg56-typedef-int-T-first typedef int T; // expected-error@-1 {{redefinition of 'T'}} - // expected-note@#dr56-typedef-int-T-first {{previous definition is here}} + // expected-note@#cwg56-typedef-int-T-first {{previous definition is here}} }; struct B { struct X; - typedef X X; // #dr56-typedef-X-X-first + typedef X X; // #cwg56-typedef-X-X-first typedef X X; // expected-error@-1 {{redefinition of 'X'}} - // expected-note@#dr56-typedef-X-X-first {{previous definition is here}} + // expected-note@#cwg56-typedef-X-X-first {{previous definition is here}} }; } -namespace dr58 { // dr58: 3.1 +namespace cwg58 { // cwg58: 3.1 // FIXME: Ideally, we should have a CodeGen test for this. #if __cplusplus >= 201103L enum E1 { E1_0 = 0, E1_1 = 1 }; @@ -927,54 +927,54 @@ namespace dr58 { // dr58: 3.1 #endif } -namespace dr59 { // dr59: yes +namespace cwg59 { // cwg59: yes #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-volatile" template struct convert_to { operator T() const; }; - struct A {}; // #dr59-A - struct B : A {}; // #dr59-B + struct A {}; // #cwg59-A + struct B : A {}; // #cwg59-B A a1 = convert_to(); A a2 = convert_to(); A a3 = convert_to(); A a4 = convert_to(); - // cxx98-14-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::A'}} - // cxx98-14-note@#dr59-A {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile dr59::A') would lose volatile qualifier}} - // cxx11-14-note@#dr59-A {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile dr59::A') would lose const and volatile qualifiers}} - // cxx98-14-note@#dr59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // cxx98-14-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::A'}} + // cxx98-14-note@#cwg59-A {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile cwg59::A') would lose volatile qualifier}} + // cxx11-14-note@#cwg59-A {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile cwg59::A') would lose const and volatile qualifiers}} + // cxx98-14-note@#cwg59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} A a5 = convert_to(); - // expected-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::A'}} - // expected-note@#dr59-A {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile dr59::A') would lose volatile qualifier}} - // since-cxx11-note@#dr59-A {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile dr59::A') would lose const and volatile qualifiers}} - // expected-note@#dr59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // expected-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::A'}} + // expected-note@#cwg59-A {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile cwg59::A') would lose volatile qualifier}} + // since-cxx11-note@#cwg59-A {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile cwg59::A') would lose const and volatile qualifiers}} + // expected-note@#cwg59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} B b1 = convert_to(); B b2 = convert_to(); B b3 = convert_to(); B b4 = convert_to(); - // cxx98-14-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::B'}} - // cxx98-14-note@#dr59-B {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile dr59::B') would lose volatile qualifier}} - // cxx11-14-note@#dr59-B {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile dr59::B') would lose const and volatile qualifiers}} - // cxx98-14-note@#dr59-B {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // cxx98-14-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::B'}} + // cxx98-14-note@#cwg59-B {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile cwg59::B') would lose volatile qualifier}} + // cxx11-14-note@#cwg59-B {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile cwg59::B') would lose const and volatile qualifiers}} + // cxx98-14-note@#cwg59-B {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} B b5 = convert_to(); - // expected-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::B'}} - // expected-note@#dr59-B {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile dr59::B') would lose volatile qualifier}} - // since-cxx11-note@#dr59-B {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile dr59::B') would lose const and volatile qualifiers}} - // expected-note@#dr59-B {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // expected-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::B'}} + // expected-note@#cwg59-B {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile cwg59::B') would lose volatile qualifier}} + // since-cxx11-note@#cwg59-B {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile cwg59::B') would lose const and volatile qualifiers}} + // expected-note@#cwg59-B {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} A c1 = convert_to(); A c2 = convert_to(); A c3 = convert_to(); A c4 = convert_to(); - // expected-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::B'}} - // expected-note@#dr59-A {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const volatile dr59::B' to 'const A &' for 1st argument}} - // since-cxx11-note@#dr59-A {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'const volatile dr59::B' to 'A &&' for 1st argument}} - // expected-note@#dr59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // expected-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::B'}} + // expected-note@#cwg59-A {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const volatile cwg59::B' to 'const A &' for 1st argument}} + // since-cxx11-note@#cwg59-A {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'const volatile cwg59::B' to 'A &&' for 1st argument}} + // expected-note@#cwg59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} A c5 = convert_to(); - // expected-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::B'}} - // expected-note@#dr59-A {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const volatile dr59::B' to 'const A &' for 1st argument}} - // since-cxx11-note@#dr59-A {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'const volatile dr59::B' to 'A &&' for 1st argument}} - // expected-note@#dr59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // expected-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::B'}} + // expected-note@#cwg59-A {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const volatile cwg59::B' to 'const A &' for 1st argument}} + // since-cxx11-note@#cwg59-A {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'const volatile cwg59::B' to 'A &&' for 1st argument}} + // expected-note@#cwg59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} int n1 = convert_to(); int n2 = convert_to(); @@ -984,14 +984,14 @@ namespace dr59 { // dr59: yes #pragma clang diagnostic pop } -namespace dr60 { // dr60: yes +namespace cwg60 { // cwg60: yes void f(int &); int &f(...); const int k = 0; int &n = f(k); } -namespace dr61 { // dr61: 3.4 +namespace cwg61 { // cwg61: 3.4 struct X { static void f(); } x; @@ -1008,7 +1008,7 @@ namespace dr61 { // dr61: 3.4 // expected-error@-1 {{cannot create a non-constant pointer to member function}} } -namespace dr62 { // dr62: 2.9 +namespace cwg62 { // cwg62: 2.9 struct A { struct { int n; } b; }; @@ -1019,7 +1019,7 @@ namespace dr62 { // dr62: 2.9 X x1; A a = get(); - typedef struct { } *NoNameForLinkagePtr; // #dr62-unnamed + typedef struct { } *NoNameForLinkagePtr; // #cwg62-unnamed NoNameForLinkagePtr noNameForLinkagePtr; struct Danger { @@ -1028,19 +1028,19 @@ namespace dr62 { // dr62: 2.9 X x2; // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} X x3; // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} NoNameForLinkagePtr p1 = get(); // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} NoNameForLinkagePtr p2 = get(); // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} int n1 = take(noNameForLinkagePtr); // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} X x4; @@ -1061,13 +1061,13 @@ namespace dr62 { // dr62: 2.9 } } -namespace dr63 { // dr63: yes +namespace cwg63 { // cwg63: yes template struct S { typename T::error e; }; extern S *p; void *q = p; } -namespace dr64 { // dr64: yes +namespace cwg64 { // cwg64: yes template void f(T); template void f(T*); template<> void f(int*); @@ -1075,11 +1075,11 @@ namespace dr64 { // dr64: yes template<> void f(int); } -// dr65: na +// cwg65: na -namespace dr66 { // dr66: no +namespace cwg66 { // cwg66: no namespace X { - int f(int n); // #dr66-f-first + int f(int n); // #cwg66-f-first } using X::f; namespace X { @@ -1089,36 +1089,36 @@ namespace dr66 { // dr66: no // FIXME: The first two calls here should be accepted. int a = f(); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr66-f-first {{candidate function not viable: requires single argument 'n', but no arguments were provided}} + // expected-note@#cwg66-f-first {{candidate function not viable: requires single argument 'n', but no arguments were provided}} int b = f(1); int c = f(1, 2); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr66-f-first {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}} + // expected-note@#cwg66-f-first {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}} } -// dr67: na +// cwg67: na -namespace dr68 { // dr68: 2.8 +namespace cwg68 { // cwg68: 2.8 template struct X {}; - struct ::dr68::X x1; - struct ::dr68::template X x2; + struct ::cwg68::X x1; + struct ::cwg68::template X x2; // cxx98-error@-1 {{'template' keyword outside of a template}} struct Y { friend struct X; - friend struct ::dr68::X; - friend struct ::dr68::template X; + friend struct ::cwg68::X; + friend struct ::cwg68::template X; // cxx98-error@-1 {{'template' keyword outside of a template}} }; template struct Z { - friend struct ::dr68::template X; - friend typename ::dr68::X; - // cxx98-error@-1 {{unelaborated friend declaration is a C++11 extension; specify 'struct' to befriend 'typename ::dr68::X'}} + friend struct ::cwg68::template X; + friend typename ::cwg68::X; + // cxx98-error@-1 {{unelaborated friend declaration is a C++11 extension; specify 'struct' to befriend 'typename ::cwg68::X'}} }; } -namespace dr69 { // dr69: 9 - template static void f() {} // #dr69-f +namespace cwg69 { // cwg69: 9 + template static void f() {} // #cwg69-f // FIXME: Should we warn here? inline void g() { f(); } extern template void f(); @@ -1127,21 +1127,21 @@ namespace dr69 { // dr69: 9 template struct Q {}; Q<&f > q; // cxx98-error@-1 {{non-type template argument referring to function 'f' with internal linkage is a C++11 extension}} - // cxx98-note@#dr69-f {{non-type template argument refers to function here}} + // cxx98-note@#cwg69-f {{non-type template argument refers to function here}} } -namespace dr70 { // dr70: yes +namespace cwg70 { // cwg70: yes template struct A {}; template int f(int (&)[I + J], A, A); int arr[7]; int k = f(arr, A<3>(), A<4>()); } -// dr71: na -// dr72: dup 69 +// cwg71: na +// cwg72: dup 69 #if __cplusplus >= 201103L -namespace dr73 { // dr73: sup 1652 +namespace cwg73 { // cwg73: sup 1652 int a, b; static_assert(&a + 1 != &b, ""); // expected-error@-1 {{static assertion expression is not an integral constant expression}} @@ -1149,43 +1149,43 @@ namespace dr73 { // dr73: sup 1652 } #endif -namespace dr74 { // dr74: yes +namespace cwg74 { // cwg74: yes enum E { k = 5 }; int (*p)[k] = new int[k][k]; } -namespace dr75 { // dr75: yes +namespace cwg75 { // cwg75: yes struct S { static int n = 0; // expected-error@-1 {{non-const static data member must be initialized out of line}} }; } -namespace dr76 { // dr76: yes +namespace cwg76 { // cwg76: yes const volatile int n = 1; - int arr[n]; // #dr76-vla - // expected-error@#dr76-vla {{variable length arrays in C++ are a Clang extension}} - // expected-note@#dr76-vla {{read of volatile-qualified type 'const volatile int' is not allowed in a constant expression}} - // expected-error@#dr76-vla {{variable length array declaration not allowed at file scope}} + int arr[n]; // #cwg76-vla + // expected-error@#cwg76-vla {{variable length arrays in C++ are a Clang extension}} + // expected-note@#cwg76-vla {{read of volatile-qualified type 'const volatile int' is not allowed in a constant expression}} + // expected-error@#cwg76-vla {{variable length array declaration not allowed at file scope}} } -namespace dr77 { // dr77: yes +namespace cwg77 { // cwg77: yes struct A { struct B {}; friend struct B; }; } -namespace dr78 { // dr78: sup ???? - // Under DR78, this is valid, because 'k' has static storage duration, so is +namespace cwg78 { // cwg78: sup ???? + // Under CWG78, this is valid, because 'k' has static storage duration, so is // zero-initialized. const int k; // expected-error@-1 {{default initialization of an object of const type 'const int'}} } -// dr79: na +// cwg79: na -namespace dr80 { // dr80: 2.9 +namespace cwg80 { // cwg80: 2.9 struct A { int A; }; @@ -1205,22 +1205,22 @@ namespace dr80 { // dr80: 2.9 }; } -// dr81: na -// dr82: dup 48 +// cwg81: na +// cwg82: dup 48 -namespace dr83 { // dr83: yes +namespace cwg83 { // cwg83: yes int &f(const char*); char &f(char *); int &k = f("foo"); } -namespace dr84 { // dr84: yes +namespace cwg84 { // cwg84: yes struct B; struct A { operator B() const; }; struct C {}; struct B { - B(B&); // #dr84-copy-ctor - B(C); // #dr84-ctor-from-C + B(B&); // #cwg84-copy-ctor + B(C); // #cwg84-ctor-from-C operator C() const; }; A a; @@ -1228,78 +1228,78 @@ namespace dr84 { // dr84: yes // here. In C++17, we initialize the B object directly using 'A::operator B()'. B b = a; // cxx98-14-error@-1 {{no viable constructor copying variable of type 'B'}} - // cxx98-14-note@#dr84-copy-ctor {{candidate constructor not viable: expects an lvalue for 1st argument}} - // cxx98-14-note@#dr84-ctor-from-C {{candidate constructor not viable: no known conversion from 'B' to 'C' for 1st argument}} + // cxx98-14-note@#cwg84-copy-ctor {{candidate constructor not viable: expects an lvalue for 1st argument}} + // cxx98-14-note@#cwg84-ctor-from-C {{candidate constructor not viable: no known conversion from 'B' to 'C' for 1st argument}} } -namespace dr85 { // dr85: 3.4 +namespace cwg85 { // cwg85: 3.4 struct A { struct B; - struct B {}; // #dr85-B-def + struct B {}; // #cwg85-B-def struct B; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-B-def {{previous declaration is here}} + // expected-note@#cwg85-B-def {{previous declaration is here}} union U; - union U {}; // #dr85-U-def + union U {}; // #cwg85-U-def union U; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-U-def {{previous declaration is here}} + // expected-note@#cwg85-U-def {{previous declaration is here}} #if __cplusplus >= 201103L enum E1 : int; - enum E1 : int { e1 }; // #dr85-E1-def + enum E1 : int { e1 }; // #cwg85-E1-def enum E1 : int; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-E1-def {{previous declaration is here}} + // expected-note@#cwg85-E1-def {{previous declaration is here}} enum class E2; - enum class E2 { e2 }; // #dr85-E2-def + enum class E2 { e2 }; // #cwg85-E2-def enum class E2; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-E2-def {{previous declaration is here}} + // expected-note@#cwg85-E2-def {{previous declaration is here}} #endif }; template struct C { - struct B {}; // #dr85-C-B-def + struct B {}; // #cwg85-C-B-def struct B; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-C-B-def {{previous declaration is here}} + // expected-note@#cwg85-C-B-def {{previous declaration is here}} }; } -// dr86: dup 446 +// cwg86: dup 446 -namespace dr87 { // dr87: no - // FIXME: Superseded by dr1975 +namespace cwg87 { // cwg87: no + // FIXME: Superseded by cwg1975 template struct X {}; // FIXME: This is invalid. X x; - // This is valid under dr87 but not under dr1975. + // This is valid under cwg87 but not under cwg1975. X y; } -namespace dr88 { // dr88: 2.8 +namespace cwg88 { // cwg88: 2.8 template struct S { - static const int a = 1; // #dr88-a + static const int a = 1; // #cwg88-a static const int b; }; template<> const int S::a = 4; // expected-error@-1 {{static data member 'a' already has an initializer}} - // expected-note@#dr88-a {{previous initialization is here}} + // expected-note@#cwg88-a {{previous initialization is here}} template<> const int S::b = 4; } -// dr89: na +// cwg89: na -namespace dr90 { // dr90: yes +namespace cwg90 { // cwg90: yes struct A { - template friend void dr90_f(T); + template friend void cwg90_f(T); }; struct B : A { - template friend void dr90_g(T); + template friend void cwg90_g(T); struct C {}; union D {}; }; @@ -1307,41 +1307,41 @@ namespace dr90 { // dr90: yes struct F : B::C {}; void test() { - dr90_f(A()); - dr90_f(B()); - dr90_f(B::C()); - // expected-error@-1 {{use of undeclared identifier 'dr90_f'}} - dr90_f(B::D()); - // expected-error@-1 {{use of undeclared identifier 'dr90_f'}} - dr90_f(E()); - dr90_f(F()); - // expected-error@-1 {{use of undeclared identifier 'dr90_f'}} - - dr90_g(A()); - // expected-error@-1 {{use of undeclared identifier 'dr90_g'}} - dr90_g(B()); - dr90_g(B::C()); - dr90_g(B::D()); - dr90_g(E()); - dr90_g(F()); - // expected-error@-1 {{use of undeclared identifier 'dr90_g'}} + cwg90_f(A()); + cwg90_f(B()); + cwg90_f(B::C()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_f'}} + cwg90_f(B::D()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_f'}} + cwg90_f(E()); + cwg90_f(F()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_f'}} + + cwg90_g(A()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_g'}} + cwg90_g(B()); + cwg90_g(B::C()); + cwg90_g(B::D()); + cwg90_g(E()); + cwg90_g(F()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_g'}} } } -namespace dr91 { // dr91: yes +namespace cwg91 { // cwg91: yes union U { friend int f(U); }; int k = f(U()); } -namespace dr92 { // dr92: 4 c++17 +namespace cwg92 { // cwg92: 4 c++17 void f() throw(int, float); // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} - void (*p)() throw(int) = &f; // #dr92-p - // since-cxx17-error@#dr92-p {{ISO C++17 does not allow dynamic exception specifications}} - // since-cxx17-note@#dr92-p {{use 'noexcept(false)' instead}} - // cxx98-14-error@#dr92-p {{target exception specification is not superset of source}} - // since-cxx17-warning@#dr92-p {{target exception specification is not superset of source}} + void (*p)() throw(int) = &f; // #cwg92-p + // since-cxx17-error@#cwg92-p {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@#cwg92-p {{use 'noexcept(false)' instead}} + // cxx98-14-error@#cwg92-p {{target exception specification is not superset of source}} + // since-cxx17-warning@#cwg92-p {{target exception specification is not superset of source}} void (*q)() throw(int); // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} @@ -1349,17 +1349,17 @@ namespace dr92 { // dr92: 4 c++17 // cxx98-14-error@-1 {{exception specifications are not allowed beyond a single level of indirection}} // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (**)() throw()' with an rvalue of type 'void (**)() throw(int)'}} - void g(void() throw()); // #dr92-g + void g(void() throw()); // #cwg92-g // cxx98-14-warning@-1 {{mangled name of 'g' will change in C++17 due to non-throwing exception specification in function signature}} void h() throw() { g(f); // cxx98-14-error@-1 {{target exception specification is not superset of source}} // since-cxx17-error@-2 {{no matching function for call to 'g'}} - // since-cxx17-note@#dr92-g {{candidate function not viable: no known conversion from 'void () throw(int, float)' to 'void (*)() throw()' for 1st argument}} + // since-cxx17-note@#cwg92-g {{candidate function not viable: no known conversion from 'void () throw(int, float)' to 'void (*)() throw()' for 1st argument}} g(q); // cxx98-14-error@-1 {{target exception specification is not superset of source}} // since-cxx17-error@-2 {{no matching function for call to 'g'}} - // since-cxx17-note@#dr92-g {{candidate function not viable: no known conversion from 'void (*)() throw(int)' to 'void (*)() throw()' for 1st argument}} + // since-cxx17-note@#cwg92-g {{candidate function not viable: no known conversion from 'void (*)() throw(int)' to 'void (*)() throw()' for 1st argument}} } // Prior to C++17, this is OK because the exception specification is not @@ -1376,31 +1376,31 @@ namespace dr92 { // dr92: 4 c++17 Y<&h> yp; // ok } -// dr93: na +// cwg93: na -namespace dr94 { // dr94: yes +namespace cwg94 { // cwg94: yes struct A { static const int n = 5; }; int arr[A::n]; } -namespace dr95 { // dr95: 3.3 +namespace cwg95 { // cwg95: 3.3 struct A; struct B; namespace N { class C { friend struct A; friend struct B; - static void f(); // #dr95-C-f + static void f(); // #cwg95-C-f }; - struct A *p; // dr95::A, not dr95::N::A. + struct A *p; // cwg95::A, not cwg95::N::A. } A *q = N::p; // ok, same type struct B { void f() { N::C::f(); } }; - // expected-error@-1 {{'f' is a private member of 'dr95::N::C'}} - // expected-note@#dr95-C-f {{implicitly declared private here}} + // expected-error@-1 {{'f' is a private member of 'cwg95::N::C'}} + // expected-note@#cwg95-C-f {{implicitly declared private here}} } -namespace dr96 { // dr96: no +namespace cwg96 { // cwg96: no struct A { void f(int); template int f(T); @@ -1420,42 +1420,42 @@ namespace dr96 { // dr96: no } } -namespace dr97 { // dr97: yes +namespace cwg97 { // cwg97: yes struct A { static const int a = false; static const int b = !a; }; } -namespace dr98 { // dr98: yes +namespace cwg98 { // cwg98: yes void test(int n) { switch (n) { - try { // #dr98-try + try { // #cwg98-try case 0: // expected-error@-1 {{cannot jump from switch statement to this case label}} - // expected-note@#dr98-try {{jump bypasses initialization of try block}} + // expected-note@#cwg98-try {{jump bypasses initialization of try block}} x: throw n; - } catch (...) { // #dr98-catch + } catch (...) { // #cwg98-catch case 1: // expected-error@-1 {{cannot jump from switch statement to this case label}} - // expected-note@#dr98-catch {{jump bypasses initialization of catch block}} + // expected-note@#cwg98-catch {{jump bypasses initialization of catch block}} y: throw n; } case 2: goto x; // expected-error@-1 {{cannot jump from this goto statement to its label}} - // expected-note@#dr98-try {{jump bypasses initialization of try block}} + // expected-note@#cwg98-try {{jump bypasses initialization of try block}} case 3: goto y; // expected-error@-1 {{cannot jump from this goto statement to its label}} - // expected-note@#dr98-catch {{jump bypasses initialization of catch block}} + // expected-note@#cwg98-catch {{jump bypasses initialization of catch block}} } } } -namespace dr99 { // dr99: sup 214 +namespace cwg99 { // cwg99: sup 214 template void f(T&); template int &f(const T&); const int n = 0; diff --git a/clang/test/CXX/drs/dr10xx.cpp b/clang/test/CXX/drs/dr10xx.cpp index 77c59078414c..58d552942c77 100644 --- a/clang/test/CXX/drs/dr10xx.cpp +++ b/clang/test/CXX/drs/dr10xx.cpp @@ -14,26 +14,26 @@ namespace std { }; } -namespace dr1004 { // dr1004: 5 +namespace cwg1004 { // cwg1004: 5 template struct A {}; template struct B1 {}; template class> struct B2 {}; - template void f(); // #dr1004-f-1 - template class X> void f(); // #dr1004-f-2 - template class X> void g(); // #dr1004-g-1 - template void g(); // #dr1004-g-2 + template void f(); // #cwg1004-f-1 + template class X> void f(); // #cwg1004-f-2 + template class X> void g(); // #cwg1004-g-1 + template void g(); // #cwg1004-g-2 struct C : A { B1 b1a; B2 b2a; void h() { f(); // expected-error@-1 {{call to 'f' is ambiguous}} - // expected-note@#dr1004-f-1 {{candidate function [with X = dr1004::A]}} - // expected-note@#dr1004-f-2 {{candidate function [with X = dr1004::A]}} + // expected-note@#cwg1004-f-1 {{candidate function [with X = cwg1004::A]}} + // expected-note@#cwg1004-f-2 {{candidate function [with X = cwg1004::A]}} g(); // expected-error@-1 {{call to 'g' is ambiguous}} - // expected-note@#dr1004-g-1 {{candidate function [with X = dr1004::A]}} - // expected-note@#dr1004-g-2 {{candidate function [with X = dr1004::A]}} + // expected-note@#cwg1004-g-1 {{candidate function [with X = cwg1004::A]}} + // expected-note@#cwg1004-g-2 {{candidate function [with X = cwg1004::A]}} } }; @@ -41,17 +41,17 @@ namespace dr1004 { // dr1004: 5 // name lookup of "T::template A" names the constructor. template class U = T::template A> struct Third { }; // expected-error@-1 {{is a constructor name}} - // expected-note@#dr1004-t {{in instantiation of default argument}} - Third > t; // #dr1004-t + // expected-note@#cwg1004-t {{in instantiation of default argument}} + Third > t; // #cwg1004-t } -namespace dr1042 { // dr1042: 3.5 +namespace cwg1042 { // cwg1042: 3.5 #if __cplusplus >= 201402L // C++14 added an attribute that we can test the semantics of. - using foo [[deprecated]] = int; // #dr1042-using + using foo [[deprecated]] = int; // #cwg1042-using foo f = 12; // since-cxx14-warning@-1 {{'foo' is deprecated}} - // since-cxx14-note@#dr1042-using {{'foo' has been explicitly marked deprecated here}} + // since-cxx14-note@#cwg1042-using {{'foo' has been explicitly marked deprecated here}} #elif __cplusplus >= 201103L // C++11 did not have any attributes that could be applied to an alias // declaration, so the best we can test is that we accept an empty attribute @@ -60,7 +60,7 @@ namespace dr1042 { // dr1042: 3.5 #endif } -namespace dr1048 { // dr1048: 3.6 +namespace cwg1048 { // cwg1048: 3.6 struct A {}; const A f(); A g(); @@ -78,20 +78,20 @@ namespace dr1048 { // dr1048: 3.6 #endif } -namespace dr1054 { // dr1054: no +namespace cwg1054 { // cwg1054: no // FIXME: Test is incomplete. struct A {} volatile a; void f() { // FIXME: This is wrong: an lvalue-to-rvalue conversion is applied here, // which copy-initializes a temporary from 'a'. Therefore this is // ill-formed because A does not have a volatile copy constructor. - // (We might want to track this aspect under dr1383 instead?) + // (We might want to track this aspect under cwg1383 instead?) a; // expected-warning@-1 {{expression result unused; assign into a variable to force a volatile load}} } } -namespace dr1070 { // dr1070: 3.5 +namespace cwg1070 { // cwg1070: 3.5 #if __cplusplus >= 201103L struct A { A(std::initializer_list); diff --git a/clang/test/CXX/drs/dr11xx.cpp b/clang/test/CXX/drs/dr11xx.cpp index a71a105c7eb2..46a0e526be39 100644 --- a/clang/test/CXX/drs/dr11xx.cpp +++ b/clang/test/CXX/drs/dr11xx.cpp @@ -4,27 +4,27 @@ // RUN: %clang_cc1 -std=c++17 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2a %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1111 { // dr1111: 3.2 +namespace cwg1111 { // cwg1111: 3.2 namespace example1 { -template struct set; // #dr1111-struct-set +template struct set; // #cwg1111-struct-set struct X { - template void set(const T &value); // #dr1111-func-set + template void set(const T &value); // #cwg1111-func-set }; void foo() { X x; // FIXME: should we backport C++11 behavior? x.set(3.2); // cxx98-error@-1 {{lookup of 'set' in member access expression is ambiguous; using member of 'X'}} - // cxx98-note@#dr1111-func-set {{lookup in the object type 'X' refers here}} - // cxx98-note@#dr1111-struct-set {{lookup from the current scope refers here}} + // cxx98-note@#cwg1111-func-set {{lookup in the object type 'X' refers here}} + // cxx98-note@#cwg1111-struct-set {{lookup from the current scope refers here}} } struct Y {}; void bar() { Y y; y.set(3.2); - // expected-error@-1 {{no member named 'set' in 'dr1111::example1::Y'}} + // expected-error@-1 {{no member named 'set' in 'cwg1111::example1::Y'}} } } // namespace example1 @@ -42,14 +42,14 @@ void baz() { a.operator A(); } } // namespace example2 -} // namespace dr1111 +} // namespace cwg1111 -namespace dr1113 { // dr1113: partial +namespace cwg1113 { // cwg1113: partial namespace named { - extern int a; // #dr1113-a + extern int a; // #cwg1113-a static int a; // expected-error@-1 {{static declaration of 'a' follows non-static}} - // expected-note@#dr1113-a {{previous declaration is here}} + // expected-note@#cwg1113-a {{previous declaration is here}} } namespace { extern int a; @@ -57,7 +57,7 @@ namespace dr1113 { // dr1113: partial int b = a; } - // FIXME: Per DR1113 and DR4, this is ill-formed due to ambiguity: the second + // FIXME: Per CWG1113 and CWG4, this is ill-formed due to ambiguity: the second // 'f' has internal linkage, and so does not have C language linkage, so is // not a redeclaration of the first 'f'. // @@ -71,4 +71,4 @@ namespace dr1113 { // dr1113: partial void g() { f(); } } -// dr1150: na +// cwg1150: na diff --git a/clang/test/CXX/drs/dr12xx.cpp b/clang/test/CXX/drs/dr12xx.cpp index da5dd02a0067..cdfbc6d67265 100644 --- a/clang/test/CXX/drs/dr12xx.cpp +++ b/clang/test/CXX/drs/dr12xx.cpp @@ -5,9 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx17,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx17,since-cxx14,since-cxx11,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors -// dr1200: na +// cwg1200: na -namespace dr1213 { // dr1213: 7 +namespace cwg1213 { // cwg1213: 7 #if __cplusplus >= 201103L using T = int[3]; int &&r = T{}[1]; @@ -32,7 +32,7 @@ namespace dr1213 { // dr1213: 7 } #if __cplusplus >= 201103L -namespace dr1223 { // dr1223: 17 drafting 2023-05-12 +namespace cwg1223 { // cwg1223: 17 drafting 2023-05-12 struct M; template struct V; @@ -80,31 +80,31 @@ void g() { A b(auto ()->C); static_assert(sizeof(B ()->C[1] == sizeof(int)), ""); sizeof(auto () -> C[1]); - // since-cxx11-error@-1 {{function cannot return array type 'C[1]' (aka 'dr1223::BB[1]')}} + // since-cxx11-error@-1 {{function cannot return array type 'C[1]' (aka 'cwg1223::BB[1]')}} } } #endif #if __cplusplus >= 201103L -namespace dr1227 { // dr1227: 3.0 +namespace cwg1227 { // cwg1227: 3.0 template struct A { using X = typename T::X; }; // since-cxx11-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}} -// since-cxx11-note@#dr1227-g {{in instantiation of template class 'dr1227::A' requested here}} -// since-cxx11-note@#dr1227-g-int {{while substituting explicitly-specified template arguments into function template 'g'}} +// since-cxx11-note@#cwg1227-g {{in instantiation of template class 'cwg1227::A' requested here}} +// since-cxx11-note@#cwg1227-g-int {{while substituting explicitly-specified template arguments into function template 'g'}} template typename T::X f(typename A::X); template void f(...) { } -template auto g(typename A::X) -> typename T::X; // #dr1227-g +template auto g(typename A::X) -> typename T::X; // #cwg1227-g template void g(...) { } void h() { f(0); // OK, substituting return type causes deduction to fail - g(0); // #dr1227-g-int + g(0); // #cwg1227-g-int } } #endif -namespace dr1250 { // dr1250: 3.9 +namespace cwg1250 { // cwg1250: 3.9 struct Incomplete; struct Base { @@ -116,7 +116,7 @@ struct Derived : Base { }; } -namespace dr1265 { // dr1265: 5 +namespace cwg1265 { // cwg1265: 5 #if __cplusplus >= 201103L auto a = 0, b() -> int; // since-cxx11-error@-1 {{declaration with trailing return type must be the only declaration in its group}} @@ -136,9 +136,9 @@ namespace dr1265 { // dr1265: 5 #endif } -// dr1291: na +// cwg1291: na -namespace dr1295 { // dr1295: 4 +namespace cwg1295 { // cwg1295: 4 struct X { unsigned bitfield : 4; }; @@ -150,11 +150,11 @@ namespace dr1295 { // dr1295: 4 unsigned const &r2 = static_cast(x.bitfield); // cxx98-error@-1 {{rvalue references are a C++11 extension}} - template struct Y {}; // #dr1295-Y - Y y; // #dr1295-y + template struct Y {}; // #cwg1295-Y + Y y; // #cwg1295-y // cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}} - // cxx98-14-note@#dr1295-Y {{template parameter is declared here}} - // since-cxx17-error@#dr1295-y {{reference cannot bind to bit-field in converted constant expression}} + // cxx98-14-note@#cwg1295-Y {{template parameter is declared here}} + // since-cxx17-error@#cwg1295-y {{reference cannot bind to bit-field in converted constant expression}} #if __cplusplus >= 201103L const unsigned other = 0; diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index d8e3b5d87bd1..dad82c4e2829 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -17,18 +17,18 @@ namespace std { } #if __cplusplus >= 201103L -namespace dr1305 { // dr1305: 3.0 -struct Incomplete; // #dr1305-Incomplete +namespace cwg1305 { // cwg1305: 3.0 +struct Incomplete; // #cwg1305-Incomplete struct Complete {}; int incomplete = alignof(Incomplete(&)[]); // since-cxx11-error@-1 {{invalid application of 'alignof' to an incomplete type 'Incomplete'}} -// since-cxx11-note@#dr1305-Incomplete {{forward declaration of 'dr1305::Incomplete'}} +// since-cxx11-note@#cwg1305-Incomplete {{forward declaration of 'cwg1305::Incomplete'}} int complete = alignof(Complete(&)[]); } #endif -namespace dr1307 { // dr1307: 14 +namespace cwg1307 { // cwg1307: 14 #if __cplusplus >= 201103L void f(int const (&)[2]); void f(int const (&)[3]); @@ -38,11 +38,11 @@ void caller() { f({1, 2, 3}); } #endif // __cplusplus >= 201103L -} // namespace dr1307 +} // namespace cwg1307 -// dr1308: sup 1330 +// cwg1308: sup 1330 -namespace dr1310 { // dr1310: 5 +namespace cwg1310 { // cwg1310: 5 struct S {} * sp = new S::S; // expected-error@-1 {{qualified reference to 'S' is a constructor name rather than a type in this context}} void f() { @@ -126,8 +126,8 @@ namespace dr1310 { // dr1310: 5 void wt_test() { typename W::W w2a; // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a type in this context, despite preceding 'typename' keyword}} - // cxx98-note@#dr1310-W-int {{in instantiation of function template specialization 'dr1310::wt_test >' requested here}} - // since-cxx11-note@#dr1310-W-int {{in instantiation of function template specialization 'dr1310::wt_test>' requested here}} + // cxx98-note@#cwg1310-W-int {{in instantiation of function template specialization 'cwg1310::wt_test >' requested here}} + // since-cxx11-note@#cwg1310-W-int {{in instantiation of function template specialization 'cwg1310::wt_test>' requested here}} typename W::template W w4; // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a template name in this context, despite preceding 'template' keyword}} TTy tt2; @@ -148,11 +148,11 @@ namespace dr1310 { // dr1310: 5 (void)w.template W::W::n; (void)w.template W::template W::n; } - template void wt_test >(); // #dr1310-W-int + template void wt_test >(); // #cwg1310-W-int template void wt_test_good >(); } -namespace dr1315 { // dr1315: partial +namespace cwg1315 { // cwg1315: partial template struct A {}; template struct A {}; // expected-error@-1 {{class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used}} @@ -160,7 +160,7 @@ namespace dr1315 { // dr1315: partial template struct A {}; template struct B; - template struct B {}; // #dr1315-B-1 + template struct B {}; // #cwg1315-B-1 B<1, 2, 3> b1; // Multiple declarations with the same dependent expression are equivalent @@ -169,13 +169,13 @@ namespace dr1315 { // dr1315: partial B<1, 2, 2>::type b2; // Multiple declarations with differing dependent expressions are unordered. - template struct B {}; // #dr1315-B-2 + template struct B {}; // #cwg1315-B-2 B<1, 2, 4> b3; // expected-error@-1 {{ambiguous partial specializations of 'B<1, 2, 4>'}} - // expected-note@#dr1315-B-1 {{partial specialization matches [with I = 1, K = 4]}} - // expected-note@#dr1315-B-2 {{partial specialization matches [with I = 1, K = 4]}} + // expected-note@#cwg1315-B-1 {{partial specialization matches [with I = 1, K = 4]}} + // expected-note@#cwg1315-B-2 {{partial specialization matches [with I = 1, K = 4]}} - // FIXME: Under dr1315, this is perhaps valid, but that is not clear: this + // FIXME: Under cwg1315, this is perhaps valid, but that is not clear: this // fails the "more specialized than the primary template" test because the // dependent type of T::value is not the same as 'int'. // A core issue will be opened to decide what is supposed to happen here. @@ -184,7 +184,7 @@ namespace dr1315 { // dr1315: partial // expected-error@-1 {{type of specialized non-type template argument depends on a template parameter of the partial specialization}} } -namespace dr1330 { // dr1330: 4 c++11 +namespace cwg1330 { // cwg1330: 4 c++11 // exception-specifications are parsed in a context where the class is complete. struct A { void f() throw(T) {} @@ -204,7 +204,7 @@ namespace dr1330 { // dr1330: 4 c++11 // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} void (A::*af2)() throw() = &A::f; // cxx98-14-error@-1 {{target exception specification is not superset of source}} - // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (dr1330::A::*)() throw()' with an rvalue of type 'void (dr1330::A::*)() throw(T)': different exception specifications}} + // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (cwg1330::A::*)() throw()' with an rvalue of type 'void (cwg1330::A::*)() throw(T)': different exception specifications}} #if __cplusplus >= 201103L static_assert(noexcept(A().g()), ""); @@ -252,7 +252,7 @@ namespace dr1330 { // dr1330: 4 c++11 void (B

::*bpf3)() = &B

::f; void (B

::*bpf4)() throw() = &B

::f; // cxx98-14-error@-1 {{target exception specification is not superset of source}} - // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (B

::*)() throw()' with an rvalue of type 'void (dr1330::B::*)() throw(T, typename P::type)': different exception specifications}} + // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (B

::*)() throw()' with an rvalue of type 'void (cwg1330::B::*)() throw(T, typename P::type)': different exception specifications}} #if __cplusplus >= 201103L static_assert(noexcept(B

().g()), ""); @@ -260,73 +260,73 @@ namespace dr1330 { // dr1330: 4 c++11 static_assert(!noexcept(B().g()), ""); #endif - template int f() throw(typename T::error) { return 0; } // #dr1330-f - // expected-error@#dr1330-f {{type 'int' cannot be used prior to '::' because it has no members}} - // cxx98-note@#dr1330-f-int {{in instantiation of function template specialization 'dr1330::f' requested here}} - // since-cxx11-note@#dr1330-f-int {{in instantiation of exception specification for 'f' requested here}} - // cxx98-14-error@#dr1330-f {{type 'short' cannot be used prior to '::' because it has no members}} - // cxx98-14-note@#dr1330-f-short {{in instantiation of function template specialization 'dr1330::f' requested here}} - // cxx11-14-note@#dr1330-f {{in instantiation of exception specification for 'f' requested here}} - // since-cxx11-error@#dr1330-f {{type 'char' cannot be used prior to '::' because it has no members}} - // since-cxx11-note@#dr1330-f-char {{in instantiation of exception specification for 'f' requested here}} - // since-cxx11-error@#dr1330-f {{type 'float' cannot be used prior to '::' because it has no members}} - // since-cxx11-note@#dr1330-f-float {{in instantiation of exception specification for 'f' requested here}} - // since-cxx17-error@#dr1330-f {{ISO C++17 does not allow dynamic exception specifications}} - // since-cxx17-note@#dr1330-f {{use 'noexcept(false)' instead}} + template int f() throw(typename T::error) { return 0; } // #cwg1330-f + // expected-error@#cwg1330-f {{type 'int' cannot be used prior to '::' because it has no members}} + // cxx98-note@#cwg1330-f-int {{in instantiation of function template specialization 'cwg1330::f' requested here}} + // since-cxx11-note@#cwg1330-f-int {{in instantiation of exception specification for 'f' requested here}} + // cxx98-14-error@#cwg1330-f {{type 'short' cannot be used prior to '::' because it has no members}} + // cxx98-14-note@#cwg1330-f-short {{in instantiation of function template specialization 'cwg1330::f' requested here}} + // cxx11-14-note@#cwg1330-f {{in instantiation of exception specification for 'f' requested here}} + // since-cxx11-error@#cwg1330-f {{type 'char' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#cwg1330-f-char {{in instantiation of exception specification for 'f' requested here}} + // since-cxx11-error@#cwg1330-f {{type 'float' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#cwg1330-f-float {{in instantiation of exception specification for 'f' requested here}} + // since-cxx17-error@#cwg1330-f {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@#cwg1330-f {{use 'noexcept(false)' instead}} // An exception-specification is needed even if the function is only used in // an unevaluated operand. - int f1 = sizeof(f()); // #dr1330-f-int + int f1 = sizeof(f()); // #cwg1330-f-int #if __cplusplus >= 201103L - decltype(f()) f2; // #dr1330-f-char - bool f3 = noexcept(f()); /// #dr1330-f-float + decltype(f()) f2; // #cwg1330-f-char + bool f3 = noexcept(f()); /// #cwg1330-f-float #endif // In C++17 onwards, substituting explicit template arguments into the // function type substitutes into the exception specification (because it's // part of the type). In earlier languages, we don't notice there's a problem // until we've already started to instantiate. - template int f(); // #dr1330-f-short + template int f(); // #cwg1330-f-short // since-cxx17-error@-1 {{explicit instantiation of 'f' does not refer to a function template, variable template, member function, member class, or static data member}} - // since-cxx17-note@#dr1330-f {{candidate template ignored: substitution failure [with T = short]: type 'short' cannot be used prior to '::' because it has no members}} + // since-cxx17-note@#cwg1330-f {{candidate template ignored: substitution failure [with T = short]: type 'short' cannot be used prior to '::' because it has no members}} template struct C { - C() throw(typename T::type); // #dr1330-C + C() throw(typename T::type); // #cwg1330-C // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} - // cxx98-error@#dr1330-C {{type 'void' cannot be used prior to '::' because it has no members}} - // cxx98-note@#dr1330-C-void {{in instantiation of template class 'dr1330::C' requested here}} - // expected-error@#dr1330-C {{type 'int' cannot be used prior to '::' because it has no members}} - // cxx98-note@#dr1330-C-int {{in instantiation of template class 'dr1330::C' requested here}} - // since-cxx11-note@#dr1330-C-int {{in instantiation of exception specification for 'C' requested here}} - // since-cxx11-note@#dr1330-e {{in evaluation of exception specification for 'dr1330::E::E' needed here}} + // cxx98-error@#cwg1330-C {{type 'void' cannot be used prior to '::' because it has no members}} + // cxx98-note@#cwg1330-C-void {{in instantiation of template class 'cwg1330::C' requested here}} + // expected-error@#cwg1330-C {{type 'int' cannot be used prior to '::' because it has no members}} + // cxx98-note@#cwg1330-C-int {{in instantiation of template class 'cwg1330::C' requested here}} + // since-cxx11-note@#cwg1330-C-int {{in instantiation of exception specification for 'C' requested here}} + // since-cxx11-note@#cwg1330-e {{in evaluation of exception specification for 'cwg1330::E::E' needed here}} }; - struct D : C {}; // #dr1330-C-void + struct D : C {}; // #cwg1330-C-void void f(D &d) { d = d; } // ok - struct E : C {}; // #dr1330-C-int - E e; // #dr1330-e + struct E : C {}; // #cwg1330-C-int + E e; // #cwg1330-e } -// dr1334: sup 1719 +// cwg1334: sup 1719 -namespace dr1341 { // dr1341: sup P0683R1 +namespace cwg1341 { // cwg1341: sup P0683R1 #if __cplusplus >= 202002L int a; -const int b = 0; // #dr1341-b +const int b = 0; // #cwg1341-b struct S { int x1 : 8 = 42; int x2 : 8 { 42 }; int y1 : true ? 8 : a = 42; int y2 : true ? 8 : b = 42; // since-cxx20-error@-1 {{cannot assign to variable 'b' with const-qualified type 'const int'}} - // since-cxx20-note@#dr1341-b {{variable 'b' declared const here}} + // since-cxx20-note@#cwg1341-b {{variable 'b' declared const here}} int y3 : (true ? 8 : b) = 42; int z : 1 || new int { 0 }; }; #endif } -namespace dr1346 { // dr1346: 3.5 +namespace cwg1346 { // cwg1346: 3.5 auto a(1); // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} auto b(1, 2); @@ -345,9 +345,9 @@ namespace dr1346 { // dr1346: 3.5 auto x(ts...); // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} // expected-error@-2 {{initializer for variable 'x' with type 'auto' is empty}} - // expected-note@#dr1346-f {{in instantiation of function template specialization 'dr1346::f<>' requested here}} + // expected-note@#cwg1346-f {{in instantiation of function template specialization 'cwg1346::f<>' requested here}} } - template void f(); // #dr1346-f + template void f(); // #cwg1346-f #if __cplusplus >= 201103L void init_capture() { @@ -369,7 +369,7 @@ namespace dr1346 { // dr1346: 3.5 #endif } -namespace dr1347 { // dr1347: 3.1 +namespace cwg1347 { // cwg1347: 3.1 auto x = 5, *y = &x; // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} auto z = y, *q = y; @@ -383,7 +383,7 @@ namespace dr1347 { // dr1347: 3.1 #endif } -namespace dr1350 { // dr1350: 3.5 +namespace cwg1350 { // cwg1350: 3.5 #if __cplusplus >= 201103L struct NoexceptCtor { NoexceptCtor(int) noexcept {} @@ -452,12 +452,12 @@ struct D4 : NoexceptCtor, ThrowingDefaultArgTemplate { static_assert(!__is_nothrow_constructible(D4, int), ""); #endif -} // namespace dr1350 +} // namespace cwg1350 -namespace dr1358 { // dr1358: 3.1 +namespace cwg1358 { // cwg1358: 3.1 #if __cplusplus >= 201103L struct Lit { constexpr operator int() const { return 0; } }; - struct NonLit { NonLit(); operator int(); }; // #dr1358-NonLit + struct NonLit { NonLit(); operator int(); }; // #cwg1358-NonLit struct NonConstexprConv { constexpr operator int() const; }; struct Virt { virtual int f(int) const; }; @@ -486,83 +486,83 @@ namespace dr1358 { // dr1358: 3.1 int member; constexpr B(NonLit u) : member(u) {} // cxx11-20-error@-1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}} - // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-note@#cwg1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} constexpr NonLit f(NonLit u) const { return NonLit(); } // cxx11-20-error@-1 {{constexpr function's return type 'NonLit' is not a literal type}} - // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-note@#cwg1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} }; #endif } -namespace dr1359 { // dr1359: 3.5 +namespace cwg1359 { // cwg1359: 3.5 #if __cplusplus >= 201103L union A { constexpr A() = default; }; - union B { constexpr B() = default; int a; }; // #dr1359-B + union B { constexpr B() = default; int a; }; // #cwg1359-B // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr before C++23}} - union C { constexpr C() = default; int a, b; }; // #dr1359-C + union C { constexpr C() = default; int a, b; }; // #cwg1359-C // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} struct X { constexpr X() = default; union {}; }; // since-cxx11-error@-1 {{declaration does not declare anything}} - struct Y { constexpr Y() = default; union { int a; }; }; // #dr1359-Y + struct Y { constexpr Y() = default; union { int a; }; }; // #cwg1359-Y // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} constexpr A a = A(); constexpr B b = B(); // cxx11-17-error@-1 {{no matching constructor for initialization of 'B'}} - // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} - // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-B {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-B {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} constexpr C c = C(); // cxx11-17-error@-1 {{no matching constructor for initialization of 'C'}} - // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} - // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-C {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-C {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} constexpr X x = X(); constexpr Y y = Y(); // cxx11-17-error@-1 {{no matching constructor for initialization of 'Y'}} - // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} - // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-Y {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-Y {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} #endif } -namespace dr1388 { // dr1388: 4 - template void f(T..., A); // #dr1388-f +namespace cwg1388 { // cwg1388: 4 + template void f(T..., A); // #cwg1388-f // cxx98-error@-1 {{variadic templates are a C++11 extension}} - template void g(T..., int); // #dr1388-g + template void g(T..., int); // #cwg1388-g // cxx98-error@-1 {{variadic templates are a C++11 extension}} - template void h(T..., A); // #dr1388-h + template void h(T..., A); // #cwg1388-h // cxx98-error@-1 {{variadic templates are a C++11 extension}} void test_f() { f(0); // ok, trailing parameter pack deduced to empty f(0, 0); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} + // expected-note@#cwg1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} f(0); f(0, 0); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} + // expected-note@#cwg1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} f(0, 0); f(0, 0); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr1388-f {{candidate function [with A = int, T = ] not viable: requires 3 arguments, but 2 were provided}} + // expected-note@#cwg1388-f {{candidate function [with A = int, T = ] not viable: requires 3 arguments, but 2 were provided}} g(0); g(0, 0); // expected-error@-1 {{no matching function for call to 'g'}} - // expected-note@#dr1388-g {{candidate function [with T = <>] not viable: requires 1 argument, but 2 were provided}} + // expected-note@#cwg1388-g {{candidate function [with T = <>] not viable: requires 1 argument, but 2 were provided}} g<>(0); g(0); // expected-error@-1 {{no matching function for call to 'g'}} - // expected-note@#dr1388-g {{candidate function [with T = ] not viable: requires 2 arguments, but 1 was provided}} + // expected-note@#cwg1388-g {{candidate function [with T = ] not viable: requires 2 arguments, but 1 was provided}} g(0, 0); h(0); h(0, 0); // expected-error@-1 {{no matching function for call to 'h'}} - // expected-note@#dr1388-h {{candidate function [with T = <>, A = int] not viable: requires 1 argument, but 2 were provided}} + // expected-note@#cwg1388-h {{candidate function [with T = <>, A = int] not viable: requires 1 argument, but 2 were provided}} h(0, 0); h(0, 0); // expected-error@-1 {{no matching function for call to 'h'}} - // expected-note@#dr1388-h {{candidate template ignored: couldn't infer template argument 'A'}} + // expected-note@#cwg1388-h {{candidate template ignored: couldn't infer template argument 'A'}} } // A non-trailing parameter pack is still a non-deduced context, even though @@ -570,40 +570,40 @@ namespace dr1388 { // dr1388: 4 template struct pair {}; template struct tuple { typedef char type; }; // // cxx98-error@-1 {{variadic templates are a C++11 extension}} - template void f_pair_1(pair..., int); // #dr1388-f-1 + template void f_pair_1(pair..., int); // #cwg1388-f-1 // cxx98-error@-1 {{variadic templates are a C++11 extension}} // cxx98-error@-2 {{variadic templates are a C++11 extension}} template void f_pair_2(pair..., U); // cxx98-error@-1 {{variadic templates are a C++11 extension}} - template void f_pair_3(pair..., tuple); // #dr1388-f-3 + template void f_pair_3(pair..., tuple); // #cwg1388-f-3 // cxx98-error@-1 {{variadic templates are a C++11 extension}} // cxx98-error@-2 {{variadic templates are a C++11 extension}} - template void f_pair_4(pair..., T...); // #dr1388-f-4 + template void f_pair_4(pair..., T...); // #cwg1388-f-4 // cxx98-error@-1 {{variadic templates are a C++11 extension}} void g(pair a, pair b, tuple c) { f_pair_1(a, b, 0); // expected-error@-1 {{no matching function for call to 'f_pair_1'}} - // expected-note@#dr1388-f-1 {{candidate template ignored: substitution failure [with T = ]: deduced incomplete pack <(no value), (no value)> for template parameter 'U'}} + // expected-note@#cwg1388-f-1 {{candidate template ignored: substitution failure [with T = ]: deduced incomplete pack <(no value), (no value)> for template parameter 'U'}} f_pair_2(a, b, 0); f_pair_3(a, b, c); f_pair_3(a, b, tuple()); // expected-error@-1 {{no matching function for call to 'f_pair_3'}} - // expected-note@#dr1388-f-3 {{candidate template ignored: deduced packs of different lengths for parameter 'U' (<(no value), (no value)> vs. )}} + // expected-note@#cwg1388-f-3 {{candidate template ignored: deduced packs of different lengths for parameter 'U' (<(no value), (no value)> vs. )}} f_pair_4(a, b, 0, 0L); f_pair_4(a, b, 0, 0L, "foo"); // expected-error@-1 {{no matching function for call to 'f_pair_4'}} - // expected-note@#dr1388-f-4 {{candidate template ignored: deduced packs of different lengths for parameter 'T' ( vs. )}} + // expected-note@#cwg1388-f-4 {{candidate template ignored: deduced packs of different lengths for parameter 'T' ( vs. )}} } } -namespace dr1391 { // dr1391: partial +namespace cwg1391 { // cwg1391: partial struct A {}; struct B : A {}; - template struct C { C(int); typename T::error error; }; // #dr1391-C - // expected-error@#dr1391-C {{type 'int' cannot be used prior to '::' because it has no members}} - // expected-note@#dr1391-b {{in instantiation of template class 'dr1391::C' requested here}} - // expected-note@#dr1391-b {{while substituting deduced template arguments into function template 'b' [with T = int]}} - // expected-error@#dr1391-C {{type 'double' cannot be used prior to '::' because it has no members}} - // expected-note@#dr1391-c {{in instantiation of template class 'dr1391::C' requested here}} + template struct C { C(int); typename T::error error; }; // #cwg1391-C + // expected-error@#cwg1391-C {{type 'int' cannot be used prior to '::' because it has no members}} + // expected-note@#cwg1391-b {{in instantiation of template class 'cwg1391::C' requested here}} + // expected-note@#cwg1391-b {{while substituting deduced template arguments into function template 'b' [with T = int]}} + // expected-error@#cwg1391-C {{type 'double' cannot be used prior to '::' because it has no members}} + // expected-note@#cwg1391-c {{in instantiation of template class 'cwg1391::C' requested here}} template struct D {}; // No deduction is performed for parameters with no deducible template-parameters, therefore types do not need to match. @@ -644,42 +644,42 @@ namespace dr1391 { // dr1391: partial void test_b() { b(0, 0); // ok, deduction fails prior to forming a conversion sequence and instantiating C // FIXME: The "while substituting" note should point at the overload candidate. - b(0, 0); // #dr1391-b + b(0, 0); // #cwg1391-b } template struct Id { typedef T type; }; template void c(T, typename Id >::type); void test_c() { // Implicit conversion sequences for dependent types are checked later. - c(0.0, 0); // #dr1391-c + c(0.0, 0); // #cwg1391-c } namespace partial_ordering { // FIXME: Second template should be considered more specialized because non-dependent parameter is ignored. - template int a(T, short) = delete; // #dr1391-a-short + template int a(T, short) = delete; // #cwg1391-a-short // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} - template int a(T*, char); // #dr1391-a-char + template int a(T*, char); // #cwg1391-a-char int test_a = a((int*)0, 0); // expected-error@-1 {{call to 'a' is ambiguous}} FIXME - // expected-note@#dr1391-a-short {{candidate function [with T = int *] has been explicitly deleted}} - // expected-note@#dr1391-a-char {{candidate function [with T = int]}} + // expected-note@#cwg1391-a-short {{candidate function [with T = int *] has been explicitly deleted}} + // expected-note@#cwg1391-a-char {{candidate function [with T = int]}} // FIXME: Second template should be considered more specialized: // deducing #1 from #2 ignores the second P/A pair, so deduction succeeds, // deducing #2 from #1 fails to deduce T, so deduction fails. - template int b(T, int) = delete; // #dr1391-b-int + template int b(T, int) = delete; // #cwg1391-b-int // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} - template int b(T*, U); // #dr1391-b-U + template int b(T*, U); // #cwg1391-b-U int test_b = b((int*)0, 0); // expected-error@-1 {{call to 'b' is ambiguous}} FIXME - // expected-note@#dr1391-b-int {{candidate function [with T = int *] has been explicitly deleted}} - // expected-note@#dr1391-b-U {{candidate function [with T = int, U = int]}} + // expected-note@#cwg1391-b-int {{candidate function [with T = int *] has been explicitly deleted}} + // expected-note@#cwg1391-b-U {{candidate function [with T = int, U = int]}} // Unintended consequences: because partial ordering does not consider // explicit template arguments, and deduction from a non-dependent type // vacuously succeeds, a non-dependent template is less specialized than // anything else! - // According to DR1391, this is ambiguous! + // According to CWG1391, this is ambiguous! template int c(int); template int c(T); int test_c1 = c(0); // ok @@ -687,46 +687,46 @@ namespace dr1391 { // dr1391: partial } } -namespace dr1394 { // dr1394: 15 +namespace cwg1394 { // cwg1394: 15 #if __cplusplus >= 201103L struct Incomplete; Incomplete f(Incomplete) = delete; // well-formed #endif } -namespace dr1395 { // dr1395: 16 +namespace cwg1395 { // cwg1395: 16 #if __cplusplus >= 201103L template void f(T, U...); template void f(T); void h(int i) { - // This is made ambiguous by dr692, but made valid again by dr1395. + // This is made ambiguous by cwg692, but made valid again by cwg1395. f(&i); } #endif } -namespace dr1397 { // dr1397: 3.2 +namespace cwg1397 { // cwg1397: 3.2 #if __cplusplus >= 201103L struct A { // cxx11-error@-1 {{default member initializer for 'p' needed within definition of enclosing class 'A' outside of member functions}} -// cxx11-note@#dr1397-p {{in evaluation of exception specification for 'dr1397::A::A' needed here}} -// cxx11-note@#dr1397-p {{default member initializer declared here}} - void *p = A{}; // #dr1397-p +// cxx11-note@#cwg1397-p {{in evaluation of exception specification for 'cwg1397::A::A' needed here}} +// cxx11-note@#cwg1397-p {{default member initializer declared here}} + void *p = A{}; // #cwg1397-p // since-cxx14-error@-1 {{default member initializer for 'p' needed within definition of enclosing class 'A' outside of member functions}} // since-cxx14-note@-2 {{default member initializer declared here}} operator void*() const { return nullptr; } }; #endif -} // namespace dr1397 +} // namespace cwg1397 -namespace dr1399 { // dr1399: dup 1388 - template void f(T..., int, T...) {} // #dr1399-f +namespace cwg1399 { // cwg1399: dup 1388 + template void f(T..., int, T...) {} // #cwg1399-f // cxx98-error@-1 {{variadic templates are a C++11 extension}} void g() { f(0); f(0, 0, 0); f(0, 0, 0); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr1399-f {{candidate template ignored: deduced packs of different lengths for parameter 'T' (<> vs. )}} + // expected-note@#cwg1399-f {{candidate template ignored: deduced packs of different lengths for parameter 'T' (<> vs. )}} } } diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp index ed6dda731fd5..9ff9a68dc13c 100644 --- a/clang/test/CXX/drs/dr14xx.cpp +++ b/clang/test/CXX/drs/dr14xx.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1413 { // dr1413: 12 +namespace cwg1413 { // cwg1413: 12 template struct Check { typedef int type; }; @@ -21,28 +21,28 @@ namespace dr1413 { // dr1413: 12 // expected-error@-1 {{use of undeclared identifier 'var1'}} // ok, variable declaration - Check::type *var2; // #dr1413-var2 + Check::type *var2; // #cwg1413-var2 Check::type *var3; // expected-error@-1 {{use of undeclared identifier 'var3'}} - // expected-note@#dr1413-var2 {{'var2' declared here}} + // expected-note@#cwg1413-var2 {{'var2' declared here}} Check::type *var4; // expected-error@-1 {{use of undeclared identifier 'var4'}} - // expected-note@#dr1413-var2 {{'var2' declared here}} + // expected-note@#cwg1413-var2 {{'var2' declared here}} // value-dependent because of the implied type-dependent 'this->', not because of 'd' Check::type *var5; // expected-error@-1 {{use of undeclared identifier 'var5'}} - // expected-note@#dr1413-var2 {{'var2' declared here}} + // expected-note@#cwg1413-var2 {{'var2' declared here}} // value-dependent because of the value-dependent '&' operator, not because of 'A::d' Check::type *var5; // expected-error@-1 {{use of undeclared identifier 'var5'}} - // expected-note@#dr1413-var2 {{'var2' declared here}} + // expected-note@#cwg1413-var2 {{'var2' declared here}} } }; } -namespace dr1423 { // dr1423: 11 +namespace cwg1423 { // cwg1423: 11 #if __cplusplus >= 201103L bool b1 = nullptr; // since-cxx11-error@-1 {{cannot initialize a variable of type 'bool' with an rvalue of type 'std::nullptr_t'}} @@ -55,9 +55,9 @@ namespace dr1423 { // dr1423: 11 #endif } -// dr1425: na abi +// cwg1425: na abi -namespace dr1432 { // dr1432: 16 +namespace cwg1432 { // cwg1432: 16 #if __cplusplus >= 201103L template T declval(); @@ -78,7 +78,7 @@ namespace dr1432 { // dr1432: 16 #endif } -namespace dr1443 { // dr1443: yes +namespace cwg1443 { // cwg1443: yes struct A { int i; A() { void foo(int=i); } @@ -86,7 +86,7 @@ struct A { }; } -namespace dr1460 { // dr1460: 3.5 +namespace cwg1460 { // cwg1460: 3.5 #if __cplusplus >= 201103L namespace DRExample { union A { @@ -121,23 +121,23 @@ namespace dr1460 { // dr1460: 3.5 } union A {}; - union B { int n; }; // #dr1460-B + union B { int n; }; // #cwg1460-B union C { int n = 0; }; struct D { union {}; }; // expected-error@-1 {{declaration does not declare anything}} - struct E { union { int n; }; }; // #dr1460-E + struct E { union { int n; }; }; // #cwg1460-E struct F { union { int n = 0; }; }; struct X { friend constexpr A::A() noexcept; friend constexpr B::B() noexcept; // cxx11-17-error@-1 {{constexpr declaration of 'B' follows non-constexpr declaration}} - // cxx11-17-note@#dr1460-B {{previous declaration is here}} + // cxx11-17-note@#cwg1460-B {{previous declaration is here}} friend constexpr C::C() noexcept; friend constexpr D::D() noexcept; friend constexpr E::E() noexcept; // cxx11-17-error@-1 {{constexpr declaration of 'E' follows non-constexpr declaration}} - // cxx11-17-note@#dr1460-E {{previous declaration is here}} + // cxx11-17-note@#cwg1460-E {{previous declaration is here}} friend constexpr F::F() noexcept; }; @@ -167,63 +167,63 @@ namespace dr1460 { // dr1460: 3.5 union { int n = 0; }; - union { // #dr1460-H-union + union { // #cwg1460-H-union int m; }; constexpr H() {} // cxx11-17-error@-1 {{constexpr constructor that does not initialize all members is a C++20 extension}} - // cxx11-17-note@#dr1460-H-union {{member not initialized by constructor}} + // cxx11-17-note@#cwg1460-H-union {{member not initialized by constructor}} constexpr H(bool) : m(1) {} constexpr H(char) : n(1) {} // cxx11-17-error@-1 {{constexpr constructor that does not initialize all members is a C++20 extension}} - // cxx11-17-note@#dr1460-H-union {{member not initialized by constructor}} + // cxx11-17-note@#cwg1460-H-union {{member not initialized by constructor}} constexpr H(double) : m(1), n(1) {} }; } #if __cplusplus >= 201403L template constexpr bool check() { - T t; // #dr1460-t + T t; // #cwg1460-t return true; } static_assert(check(), ""); - static_assert(check(), ""); // #dr1460-check-B + static_assert(check(), ""); // #cwg1460-check-B // cxx14-17-error@-1 {{static assertion expression is not an integral constant expression}} - // cxx14-17-note@#dr1460-t {{non-constexpr constructor 'B' cannot be used in a constant expression}} - // cxx14-17-note@#dr1460-check-B {{in call to 'check()'}} - // cxx14-17-note@#dr1460-B {{declared here}} + // cxx14-17-note@#cwg1460-t {{non-constexpr constructor 'B' cannot be used in a constant expression}} + // cxx14-17-note@#cwg1460-check-B {{in call to 'check()'}} + // cxx14-17-note@#cwg1460-B {{declared here}} static_assert(check(), ""); static_assert(check(), ""); - static_assert(check(), ""); // #dr1460-check-E + static_assert(check(), ""); // #cwg1460-check-E // cxx14-17-error@-1 {{static assertion expression is not an integral constant expression}} - // cxx14-17-note@#dr1460-t {{non-constexpr constructor 'E' cannot be used in a constant expression}} - // cxx14-17-note@#dr1460-check-E {{in call to 'check()'}} - // cxx14-17-note@#dr1460-E {{declared here}} + // cxx14-17-note@#cwg1460-t {{non-constexpr constructor 'E' cannot be used in a constant expression}} + // cxx14-17-note@#cwg1460-check-E {{in call to 'check()'}} + // cxx14-17-note@#cwg1460-E {{declared here}} static_assert(check(), ""); #endif union G { - int a = 0; // #dr1460-G-a + int a = 0; // #cwg1460-G-a int b = 0; // expected-error@-1 {{initializing multiple members of union}} - // expected-note@#dr1460-G-a {{previous initialization is here}} + // expected-note@#cwg1460-G-a {{previous initialization is here}} }; union H { union { - int a = 0; // #dr1460-H-a + int a = 0; // #cwg1460-H-a }; union { int b = 0; // expected-error@-1 {{initializing multiple members of union}} - // expected-note@#dr1460-H-a {{previous initialization is here}} + // expected-note@#cwg1460-H-a {{previous initialization is here}} }; }; struct I { union { - int a = 0; // #dr1460-I-a + int a = 0; // #cwg1460-I-a int b = 0; // expected-error@-1 {{initializing multiple members of union}} - // expected-note@#dr1460-I-a {{previous initialization is here}} + // expected-note@#cwg1460-I-a {{previous initialization is here}} }; }; struct J { @@ -374,9 +374,9 @@ namespace std { } // std #endif -namespace dr1467 { // dr1467: 3.7 c++11 +namespace cwg1467 { // cwg1467: 3.7 c++11 #if __cplusplus >= 201103L - // Note that the change to [over.best.ics] was partially undone by DR2076; + // Note that the change to [over.best.ics] was partially undone by CWG2076; // the resulting rule is tested with the tests for that change. // List-initialization of aggregate from same-type object @@ -441,12 +441,12 @@ namespace dr1467 { // dr1467: 3.7 c++11 X x; X x2{x}; - void f1(int); // #dr1467-f1 - void f1(std::initializer_list) = delete; // #dr1467-f1-deleted + void f1(int); // #cwg1467-f1 + void f1(std::initializer_list) = delete; // #cwg1467-f1-deleted void g1() { f1({42}); } // since-cxx11-error@-1 {{call to deleted function 'f1'}} - // since-cxx11-note@#dr1467-f1 {{candidate function}} - // since-cxx11-note@#dr1467-f1-deleted {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f1 {{candidate function}} + // since-cxx11-note@#cwg1467-f1-deleted {{candidate function has been explicitly deleted}} template struct Pair { @@ -456,12 +456,12 @@ namespace dr1467 { // dr1467: 3.7 c++11 String(const char *); }; - void f2(Pair); // #dr1467-f2 - void f2(std::initializer_list) = delete; // #dr1467-f2-deleted + void f2(Pair); // #cwg1467-f2 + void f2(std::initializer_list) = delete; // #cwg1467-f2-deleted void g2() { f2({"foo", "bar"}); } // since-cxx11-error@-1 {{call to deleted function 'f2'}} - // since-cxx11-note@#dr1467-f2 {{candidate function}} - // since-cxx11-note@#dr1467-f2-deleted {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f2 {{candidate function}} + // since-cxx11-note@#cwg1467-f2-deleted {{candidate function has been explicitly deleted}} } // dr_example namespace nonaggregate { @@ -522,88 +522,88 @@ namespace dr1467 { // dr1467: 3.7 c++11 // When the array size is 4 the call will attempt to bind an lvalue to an // rvalue and fail. Therefore #2 will be called. (rsmith will bring this // issue to CWG) - void f(const char(&&)[4]); // #dr1467-f-char-4 - void f(const char(&&)[5]) = delete; // #dr1467-f-char-5 - void f(const wchar_t(&&)[4]); // #dr1467-f-wchar-4 - void f(const wchar_t(&&)[5]) = delete; // #dr1467-f-wchar-5 + void f(const char(&&)[4]); // #cwg1467-f-char-4 + void f(const char(&&)[5]) = delete; // #cwg1467-f-char-5 + void f(const wchar_t(&&)[4]); // #cwg1467-f-wchar-4 + void f(const wchar_t(&&)[5]) = delete; // #cwg1467-f-wchar-5 #if __cplusplus >= 202002L - void f2(const char8_t(&&)[4]); // #dr1467-f2-char8-4 - void f2(const char8_t(&&)[5]) = delete; // #dr1467-f2-char8-5 + void f2(const char8_t(&&)[4]); // #cwg1467-f2-char8-4 + void f2(const char8_t(&&)[5]) = delete; // #cwg1467-f2-char8-5 #endif - void f(const char16_t(&&)[4]); // #dr1467-f-char16-4 - void f(const char16_t(&&)[5]) = delete; // #dr1467-f-char16-5 - void f(const char32_t(&&)[4]); // #dr1467-f-char32-4 - void f(const char32_t(&&)[5]) = delete; // #dr1467-f-char32-5 + void f(const char16_t(&&)[4]); // #cwg1467-f-char16-4 + void f(const char16_t(&&)[5]) = delete; // #cwg1467-f-char16-5 + void f(const char32_t(&&)[4]); // #cwg1467-f-char32-4 + void f(const char32_t(&&)[5]) = delete; // #cwg1467-f-char32-5 void g() { f({"abc"}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} f({((("abc")))}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} f({L"abc"}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: expects an rvalue for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} #if __cplusplus >= 202002L f2({u8"abc"}); // since-cxx20-error@-1 {{call to deleted function 'f2'}} - // since-cxx20-note@#dr1467-f2-char8-5 {{candidate function has been explicitly deleted}} - // since-cxx20-note@#dr1467-f2-char8-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx20-note@#cwg1467-f2-char8-5 {{candidate function has been explicitly deleted}} + // since-cxx20-note@#cwg1467-f2-char8-4 {{candidate function not viable: expects an rvalue for 1st argument}} #endif f({uR"(abc)"}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: expects an rvalue for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} f({(UR"(abc)")}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: expects an rvalue for 1st argument}} } } // namespace StringLiterals #endif -} // dr1467 +} // cwg1467 -namespace dr1479 { // dr1479: 3.1 +namespace cwg1479 { // cwg1479: 3.1 #if __cplusplus >= 201103L int operator"" _a(const char*, std::size_t = 0); // since-cxx11-error@-1 {{literal operator cannot have a default argument}} #endif } -namespace dr1482 { // dr1482: 3.0 +namespace cwg1482 { // cwg1482: 3.0 // NB: sup 2516, test reused there #if __cplusplus >= 201103L template struct S { @@ -612,11 +612,11 @@ template struct S { enum E2 : S::I { e }; // since-cxx11-error@-1 {{use of undeclared identifier 'E2'}} #endif -} // namespace dr1482 +} // namespace cwg1482 -namespace dr1487 { // dr1487: 3.3 +namespace cwg1487 { // cwg1487: 3.3 #if __cplusplus >= 201103L -struct A { // #dr1482-A +struct A { // #cwg1482-A struct B { using A::A; // since-cxx11-error@-1 {{using declaration refers into 'A::', which is not a base class of 'B'}} @@ -624,7 +624,7 @@ struct A { // #dr1482-A struct C : A { // since-cxx11-error@-1 {{base class has incomplete type}} - // since-cxx11-note@#dr1482-A {{definition of 'dr1487::A' is not complete until the closing '}'}} + // since-cxx11-note@#cwg1482-A {{definition of 'cwg1487::A' is not complete until the closing '}'}} using A::A; // since-cxx11-error@-1 {{using declaration refers into 'A::', which is not a base class of 'C'}} }; @@ -636,9 +636,9 @@ struct D : A { using A::A; }; #endif -} // namespace dr1487 +} // namespace cwg1487 -namespace dr1490 { // dr1490: 3.7 c++11 +namespace cwg1490 { // cwg1490: 3.7 c++11 #if __cplusplus >= 201103L // List-initialization from a string literal @@ -646,51 +646,51 @@ namespace dr1490 { // dr1490: 3.7 c++11 std::initializer_list{"abc"}; // since-cxx11-error@-1 {{expected unqualified-id}}} #endif -} // dr1490 +} // cwg1490 -namespace dr1495 { // dr1495: 4 +namespace cwg1495 { // cwg1495: 4 #if __cplusplus >= 201103L // Deduction succeeds in both directions. - template struct A {}; // #dr1495-A + template struct A {}; // #cwg1495-A template struct A {}; // since-cxx11-error@-1 {{class template partial specialization is not more specialized than the primary template}} - // since-cxx11-note@#dr1495-A {{template is declared here}} + // since-cxx11-note@#cwg1495-A {{template is declared here}} // Primary template is more specialized. - template struct B {}; // #dr1495-B + template struct B {}; // #cwg1495-B template struct B {}; // since-cxx11-error@-1 {{class template partial specialization is not more specialized than the primary template}} - // since-cxx11-note@#dr1495-B {{template is declared here}} + // since-cxx11-note@#cwg1495-B {{template is declared here}} // Deduction fails in both directions. - template struct C {}; // #dr1495-C + template struct C {}; // #cwg1495-C template struct C<0, Ts...> {}; // since-cxx11-error@-1 {{class template partial specialization is not more specialized than the primary template}} - // since-cxx11-note@#dr1495-C {{template is declared here}} + // since-cxx11-note@#cwg1495-C {{template is declared here}} #if __cplusplus >= 201402L // Deduction succeeds in both directions. - template int a; // #dr1495-a + template int a; // #cwg1495-a template int a; // since-cxx14-error@-1 {{variable template partial specialization is not more specialized than the primary template}} - // since-cxx14-note@#dr1495-a {{template is declared here}} + // since-cxx14-note@#cwg1495-a {{template is declared here}} // Primary template is more specialized. - template int b; // #dr1495-b + template int b; // #cwg1495-b template int b; // since-cxx14-error@-1 {{variable template partial specialization is not more specialized than the primary template}} - // since-cxx14-note@#dr1495-b {{template is declared here}} + // since-cxx14-note@#cwg1495-b {{template is declared here}} // Deduction fails in both directions. - template int c; // #dr1495-c + template int c; // #cwg1495-c template int c<0, Ts...>; // since-cxx14-error@-1 {{variable template partial specialization is not more specialized than the primary template}} - // since-cxx14-note@#dr1495-c {{template is declared here}} + // since-cxx14-note@#cwg1495-c {{template is declared here}} #endif #endif } -namespace dr1496 { // dr1496: no +namespace cwg1496 { // cwg1496: no #if __cplusplus >= 201103L struct A { A() = delete; diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp index 6e3ad41c748f..21a392a5141e 100644 --- a/clang/test/CXX/drs/dr15xx.cpp +++ b/clang/test/CXX/drs/dr15xx.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1512 { // dr1512: 4 +namespace cwg1512 { // cwg1512: 4 void f(char *p) { if (p > 0) {} // expected-error@-1 {{ordered comparison between pointer and zero ('char *' and 'int')}} @@ -33,11 +33,11 @@ namespace dr1512 { // dr1512: 4 template void composite_pointer_type_is_ord() { composite_pointer_type_is_base(); - typedef __typeof(val() < val()) cmp; // #dr1512-lt - // since-cxx17-warning@#dr1512-lt {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} - // since-cxx17-note@#dr1512-noexcept-1st {{in instantiation of function template specialization 'dr1512::composite_pointer_type_is_ord' requested here}} - // since-cxx17-warning@#dr1512-lt {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} - // since-cxx17-note@#dr1512-noexcept-2nd {{in instantiation of function template specialization 'dr1512::composite_pointer_type_is_ord' requested here}} + typedef __typeof(val() < val()) cmp; // #cwg1512-lt + // since-cxx17-warning@#cwg1512-lt {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} + // since-cxx17-note@#cwg1512-noexcept-1st {{in instantiation of function template specialization 'cwg1512::composite_pointer_type_is_ord' requested here}} + // since-cxx17-warning@#cwg1512-lt {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} + // since-cxx17-note@#cwg1512-noexcept-2nd {{in instantiation of function template specialization 'cwg1512::composite_pointer_type_is_ord' requested here}} typedef __typeof(val() <= val()) cmp; // since-cxx17-warning@-1 {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} // since-cxx17-warning@-2 {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} @@ -95,8 +95,8 @@ namespace dr1512 { // dr1512: 4 // since-cxx20-warning@-1 {{volatile-qualified return type 'volatile int' is deprecated}} #if __cplusplus >= 201703L - composite_pointer_type_is_ord(); // #dr1512-noexcept-1st - composite_pointer_type_is_ord(); // #dr1512-noexcept-2nd + composite_pointer_type_is_ord(); // #cwg1512-noexcept-1st + composite_pointer_type_is_ord(); // #cwg1512-noexcept-2nd composite_pointer_type_is_unord(); composite_pointer_type_is_unord(); // FIXME: This looks like a standard defect; these should probably all have type 'int (B::*)()'. @@ -129,7 +129,7 @@ namespace dr1512 { // dr1512: 4 } #if __cplusplus >= 201103L - template struct Wrap { operator T(); }; // #dr1512-Wrap + template struct Wrap { operator T(); }; // #cwg1512-Wrap void test_overload() { using nullptr_t = decltype(nullptr); void(Wrap() == Wrap()); @@ -143,75 +143,75 @@ namespace dr1512 { // dr1512: 4 void(Wrap() >= Wrap()); // since-cxx11-error@-1 {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap' (aka 'Wrap'))}} - // Under dr1213, this is ill-formed: we select the builtin operator<(int*, int*) + // Under cwg1213, this is ill-formed: we select the builtin operator<(int*, int*) // but then only convert as far as 'nullptr_t', which we then can't convert to 'int*'. void(Wrap() == Wrap()); void(Wrap() != Wrap()); void(Wrap() < Wrap()); // since-cxx11-error@-1 {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap')}} - // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} - // since-cxx11-note@#dr1512-Wrap {{second operand was implicitly converted to type 'int *'}} + // since-cxx11-note@#cwg1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#cwg1512-Wrap {{second operand was implicitly converted to type 'int *'}} void(Wrap() > Wrap()); // since-cxx11-error@-1 {{invalid operands}} - // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} - // since-cxx11-note@#dr1512-Wrap{{second operand was implicitly converted to type 'int *'}} + // since-cxx11-note@#cwg1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#cwg1512-Wrap{{second operand was implicitly converted to type 'int *'}} void(Wrap() <= Wrap()); // since-cxx11-error@-1 {{invalid operands}} - // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} - // since-cxx11-note@#dr1512-Wrap {{second operand was implicitly converted to type 'int *'}} + // since-cxx11-note@#cwg1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#cwg1512-Wrap {{second operand was implicitly converted to type 'int *'}} void(Wrap() >= Wrap()); // since-cxx11-error@-1 {{invalid operands}} - // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} - // since-cxx11-note@#dr1512-Wrap {{second operand was implicitly converted to type 'int *'}} + // since-cxx11-note@#cwg1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#cwg1512-Wrap {{second operand was implicitly converted to type 'int *'}} } #endif } -namespace dr1514 { // dr1514: 11 +namespace cwg1514 { // cwg1514: 11 #if __cplusplus >= 201103L struct S { - enum E : int {}; // #dr1514-E + enum E : int {}; // #cwg1514-E enum E : int {}; // since-cxx11-error@-1 {{redefinition of 'E'}} - // since-cxx11-note@#dr1514-E {{previous definition is here}} + // since-cxx11-note@#cwg1514-E {{previous definition is here}} }; S::E se; // OK, complete type, not zero-width bitfield. - // The behavior in other contexts is superseded by DR1966. + // The behavior in other contexts is superseded by CWG1966. #endif } -namespace dr1518 { // dr1518: 4 +namespace cwg1518 { // cwg1518: 4 #if __cplusplus >= 201103L -struct Z0 { // #dr1518-Z0 - explicit Z0() = default; // #dr1518-Z0-ctor +struct Z0 { // #cwg1518-Z0 + explicit Z0() = default; // #cwg1518-Z0-ctor }; -struct Z { // #dr1518-Z - explicit Z(); // #dr1518-Z-ctor - explicit Z(int); // #dr1518-Z-int - explicit Z(int, int); // #dr1518-Z-int-int +struct Z { // #cwg1518-Z + explicit Z(); // #cwg1518-Z-ctor + explicit Z(int); // #cwg1518-Z-int + explicit Z(int, int); // #cwg1518-Z-int-int }; -template int Eat(T); // #dr1518-Eat +template int Eat(T); // #cwg1518-Eat Z0 a; Z0 b{}; Z0 c = {}; // since-cxx11-error@-1 {{chosen constructor is explicit in copy-initialization}} -// since-cxx11-note@#dr1518-Z0-ctor {{explicit constructor declared here}} +// since-cxx11-note@#cwg1518-Z0-ctor {{explicit constructor declared here}} int i = Eat({}); // since-cxx11-error@-1 {{no matching function for call to 'Eat'}} -// since-cxx11-note@#dr1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z0'}} +// since-cxx11-note@#cwg1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z0'}} Z c2 = {}; // since-cxx11-error@-1 {{chosen constructor is explicit in copy-initialization}} -// since-cxx11-note@#dr1518-Z-ctor {{explicit constructor declared here}} +// since-cxx11-note@#cwg1518-Z-ctor {{explicit constructor declared here}} int i2 = Eat({}); // since-cxx11-error@-1 {{no matching function for call to 'Eat'}} -// since-cxx11-note@#dr1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z'}} +// since-cxx11-note@#cwg1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z'}} Z a1 = 1; // since-cxx11-error@-1 {{no viable conversion from 'int' to 'Z'}} -// since-cxx11-note@#dr1518-Z {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Z &' for 1st argument}} -// since-cxx11-note@#dr1518-Z {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Z &&' for 1st argument}} -// since-cxx11-note@#dr1518-Z-int {{explicit constructor is not a candidate}} +// since-cxx11-note@#cwg1518-Z {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Z &' for 1st argument}} +// since-cxx11-note@#cwg1518-Z {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Z &&' for 1st argument}} +// since-cxx11-note@#cwg1518-Z-int {{explicit constructor is not a candidate}} Z a3 = Z(1); Z a2(1); Z *p = new Z(1); @@ -219,129 +219,129 @@ Z a4 = (Z)1; Z a5 = static_cast(1); Z a6 = {4, 3}; // since-cxx11-error@-1 {{chosen constructor is explicit in copy-initialization}} -// since-cxx11-note@#dr1518-Z-int-int {{explicit constructor declared here}} +// since-cxx11-note@#cwg1518-Z-int-int {{explicit constructor declared here}} -struct UserProvidedBaseCtor { // #dr1518-U +struct UserProvidedBaseCtor { // #cwg1518-U UserProvidedBaseCtor() {} }; -struct DoesntInheritCtor : UserProvidedBaseCtor { // #dr1518-D-U +struct DoesntInheritCtor : UserProvidedBaseCtor { // #cwg1518-D-U int x; }; DoesntInheritCtor I{{}, 42}; // cxx11-14-error@-1 {{no matching constructor for initialization of 'DoesntInheritCtor'}} -// cxx11-14-note@#dr1518-D-U {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} -// cxx11-14-note@#dr1518-D-U {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} -// cxx11-14-note@#dr1518-D-U {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} +// cxx11-14-note@#cwg1518-D-U {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} +// cxx11-14-note@#cwg1518-D-U {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} +// cxx11-14-note@#cwg1518-D-U {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} -struct BaseCtor { BaseCtor() = default; }; // #dr1518-BC -struct InheritsCtor : BaseCtor { // #dr1518-I - using BaseCtor::BaseCtor; // #dr1518-I-using +struct BaseCtor { BaseCtor() = default; }; // #cwg1518-BC +struct InheritsCtor : BaseCtor { // #cwg1518-I + using BaseCtor::BaseCtor; // #cwg1518-I-using int x; }; InheritsCtor II = {{}, 42}; // since-cxx11-error@-1 {{no matching constructor for initialization of 'InheritsCtor'}} -// since-cxx11-note@#dr1518-BC {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} -// since-cxx11-note@#dr1518-I-using {{constructor from base class 'BaseCtor' inherited here}} -// since-cxx11-note@#dr1518-BC {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} -// since-cxx11-note@#dr1518-I-using {{constructor from base class 'BaseCtor' inherited here}} -// since-cxx11-note@#dr1518-I {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} -// since-cxx11-note@#dr1518-I {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} -// since-cxx11-note@#dr1518-I {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} +// since-cxx11-note@#cwg1518-BC {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#cwg1518-I-using {{constructor from base class 'BaseCtor' inherited here}} +// since-cxx11-note@#cwg1518-BC {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#cwg1518-I-using {{constructor from base class 'BaseCtor' inherited here}} +// since-cxx11-note@#cwg1518-I {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#cwg1518-I {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#cwg1518-I {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} namespace std_example { struct A { - explicit A() = default; // #dr1518-A + explicit A() = default; // #cwg1518-A }; struct B : A { - explicit B() = default; // #dr1518-B + explicit B() = default; // #cwg1518-B }; struct C { - explicit C(); // #dr1518-C + explicit C(); // #cwg1518-C }; struct D : A { C c; - explicit D() = default; // #dr1518-D + explicit D() = default; // #cwg1518-D }; template void f() { T t; // ok T u{}; // ok - T v = {}; // #dr1518-v - // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-f-A {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} - // since-cxx11-note@#dr1518-A {{explicit constructor declared here}} - // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-f-B {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} - // since-cxx11-note@#dr1518-B {{explicit constructor declared here}} - // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-f-C {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} - // since-cxx11-note@#dr1518-C {{explicit constructor declared here}} - // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-f-D {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} - // since-cxx11-note@#dr1518-D {{explicit constructor declared here}} + T v = {}; // #cwg1518-v + // since-cxx11-error@#cwg1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-f-A {{in instantiation of function template specialization 'cwg1518::std_example::f' requested here}} + // since-cxx11-note@#cwg1518-A {{explicit constructor declared here}} + // since-cxx11-error@#cwg1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-f-B {{in instantiation of function template specialization 'cwg1518::std_example::f' requested here}} + // since-cxx11-note@#cwg1518-B {{explicit constructor declared here}} + // since-cxx11-error@#cwg1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-f-C {{in instantiation of function template specialization 'cwg1518::std_example::f' requested here}} + // since-cxx11-note@#cwg1518-C {{explicit constructor declared here}} + // since-cxx11-error@#cwg1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-f-D {{in instantiation of function template specialization 'cwg1518::std_example::f' requested here}} + // since-cxx11-note@#cwg1518-D {{explicit constructor declared here}} } template void g() { - void x(T t); // #dr1518-x - x({}); // #dr1518-x-call - // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-g-A {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} - // since-cxx11-note@#dr1518-A {{explicit constructor declared here}} - // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} - // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-g-B {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} - // since-cxx11-note@#dr1518-B {{explicit constructor declared here}} - // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} - // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-g-C {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} - // since-cxx11-note@#dr1518-C {{explicit constructor declared here}} - // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} - // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-g-D {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} - // since-cxx11-note@#dr1518-D {{explicit constructor declared here}} - // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} + void x(T t); // #cwg1518-x + x({}); // #cwg1518-x-call + // since-cxx11-error@#cwg1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-g-A {{in instantiation of function template specialization 'cwg1518::std_example::g' requested here}} + // since-cxx11-note@#cwg1518-A {{explicit constructor declared here}} + // since-cxx11-note@#cwg1518-x {{passing argument to parameter 't' here}} + // since-cxx11-error@#cwg1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-g-B {{in instantiation of function template specialization 'cwg1518::std_example::g' requested here}} + // since-cxx11-note@#cwg1518-B {{explicit constructor declared here}} + // since-cxx11-note@#cwg1518-x {{passing argument to parameter 't' here}} + // since-cxx11-error@#cwg1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-g-C {{in instantiation of function template specialization 'cwg1518::std_example::g' requested here}} + // since-cxx11-note@#cwg1518-C {{explicit constructor declared here}} + // since-cxx11-note@#cwg1518-x {{passing argument to parameter 't' here}} + // since-cxx11-error@#cwg1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-g-D {{in instantiation of function template specialization 'cwg1518::std_example::g' requested here}} + // since-cxx11-note@#cwg1518-D {{explicit constructor declared here}} + // since-cxx11-note@#cwg1518-x {{passing argument to parameter 't' here}} } void test() { - f(); // #dr1518-f-A - f(); // #dr1518-f-B - f(); // #dr1518-f-C - f(); // #dr1518-f-D - g(); // #dr1518-g-A - g(); // #dr1518-g-B - g(); // #dr1518-g-C - g(); // #dr1518-g-D + f(); // #cwg1518-f-A + f(); // #cwg1518-f-B + f(); // #cwg1518-f-C + f(); // #cwg1518-f-D + g(); // #cwg1518-g-A + g(); // #cwg1518-g-B + g(); // #cwg1518-g-C + g(); // #cwg1518-g-D } } #endif // __cplusplus >= 201103L } -namespace dr1550 { // dr1550: 3.4 +namespace cwg1550 { // cwg1550: 3.4 int f(bool b, int n) { return (b ? (throw 0) : n) + (b ? n : (throw 0)); } } -namespace dr1558 { // dr1558: 12 +namespace cwg1558 { // cwg1558: 12 #if __cplusplus >= 201103L template using first_of = T; - template first_of f(int); // #dr1558-f - template void f(...) = delete; // #dr1558-f-deleted + template first_of f(int); // #cwg1558-f + template void f(...) = delete; // #cwg1558-f-deleted struct X { typedef void type; }; void test() { f(0); f(0); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1558-f-deleted {{candidate function [with T = int] has been explicitly deleted}} - // since-cxx11-note@#dr1558-f {{candidate template ignored: substitution failure [with T = int]: type 'int' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#cwg1558-f-deleted {{candidate function [with T = int] has been explicitly deleted}} + // since-cxx11-note@#cwg1558-f {{candidate template ignored: substitution failure [with T = int]: type 'int' cannot be used prior to '::' because it has no members}} } #endif } -namespace dr1560 { // dr1560: 3.5 +namespace cwg1560 { // cwg1560: 3.5 void f(bool b, int n) { (b ? throw 0 : n) = (b ? n : throw 0) = 0; } @@ -350,7 +350,7 @@ namespace dr1560 { // dr1560: 3.5 const X &x = true ? get() : throw 0; } -namespace dr1563 { // dr1563: yes +namespace cwg1563 { // cwg1563: yes #if __cplusplus >= 201103L double bar(double) { return 0.0; } float bar(float) { return 0.0f; } @@ -360,7 +360,7 @@ namespace dr1563 { // dr1563: yes #endif } -namespace dr1567 { // dr1567: 3.3 +namespace cwg1567 { // cwg1567: 3.3 #if __cplusplus >= 201103L struct B; struct A { @@ -368,12 +368,12 @@ struct A { A(const B&) = delete; A(A&&); A(B&&) = delete; - A(int); // #dr1567-A-int + A(int); // #cwg1567-A-int }; -struct B: A { // #dr1567-B - using A::A; // #dr1567-using-A - B(double); // #dr1567-B-double +struct B: A { // #cwg1567-B + using A::A; // #cwg1567-using-A + B(double); // #cwg1567-B-double }; A a{0}; @@ -384,22 +384,22 @@ B b3{B{1.0}}; // Good, copy/move ctors are not inherited B b4{a}; // since-cxx11-error@-1 {{no matching constructor for initialization of 'B'}} -// since-cxx11-note@#dr1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} -// since-cxx11-note@#dr1567-using-A {{constructor from base class 'A' inherited here}} -// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} -// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} -// since-cxx11-note@#dr1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} +// since-cxx11-note@#cwg1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} +// since-cxx11-note@#cwg1567-using-A {{constructor from base class 'A' inherited here}} +// since-cxx11-note@#cwg1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} +// since-cxx11-note@#cwg1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} +// since-cxx11-note@#cwg1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} B b5{A{0}}; // since-cxx11-error@-1 {{no matching constructor for initialization of 'B'}} -// since-cxx11-note@#dr1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} -// since-cxx11-note@#dr1567-using-A {{constructor from base class 'A' inherited here}} -// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} -// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} -// since-cxx11-note@#dr1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} +// since-cxx11-note@#cwg1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} +// since-cxx11-note@#cwg1567-using-A {{constructor from base class 'A' inherited here}} +// since-cxx11-note@#cwg1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} +// since-cxx11-note@#cwg1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} +// since-cxx11-note@#cwg1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} #endif } -namespace dr1573 { // dr1573: 3.9 +namespace cwg1573 { // cwg1573: 3.9 #if __cplusplus >= 201103L // ellipsis is inherited (p0136r1 supersedes this part). struct A { A(); A(int, char, ...); }; @@ -407,38 +407,38 @@ namespace dr1573 { // dr1573: 3.9 B b(1, 'x', 4.0, "hello"); // ok // inherited constructor is effectively constexpr if the user-written constructor would be - struct C { C(); constexpr C(int) {} }; // #dr1573-C + struct C { C(); constexpr C(int) {} }; // #cwg1573-C struct D : C { using C::C; }; constexpr D d = D(0); // ok - struct E : C { using C::C; A a; }; // #dr1573-E + struct E : C { using C::C; A a; }; // #cwg1573-E constexpr E e = E(0); // since-cxx11-error@-1 {{constexpr variable cannot have non-literal type 'const E'}} - // since-cxx11-note@#dr1573-E {{'E' is not literal because it has data member 'a' of non-literal type 'A'}} + // since-cxx11-note@#cwg1573-E {{'E' is not literal because it has data member 'a' of non-literal type 'A'}} // FIXME: This diagnostic is pretty bad; we should explain that the problem // is that F::c would be initialized by a non-constexpr constructor. - struct F : C { using C::C; C c; }; // #dr1573-F + struct F : C { using C::C; C c; }; // #cwg1573-F constexpr F f = F(0); // since-cxx11-error@-1 {{constexpr variable 'f' must be initialized by a constant expression}} // cxx11-20-note@-2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}} // since-cxx23-note@-3 {{in implicit initialization for inherited constructor of 'F'}} - // since-cxx23-note@#dr1573-F {{non-constexpr constructor 'C' cannot be used in a constant expression}} - // cxx11-20-note@#dr1573-F {{declared here}} - // since-cxx23-note@#dr1573-C {{declared here}} + // since-cxx23-note@#cwg1573-F {{non-constexpr constructor 'C' cannot be used in a constant expression}} + // cxx11-20-note@#cwg1573-F {{declared here}} + // since-cxx23-note@#cwg1573-C {{declared here}} // inherited constructor is effectively deleted if the user-written constructor would be struct G { G(int); }; - struct H : G { using G::G; G g; }; // #dr1573-H + struct H : G { using G::G; G g; }; // #cwg1573-H H h(0); // since-cxx11-error@-1 {{constructor inherited by 'H' from base class 'G' is implicitly deleted}} - // since-cxx11-note@#dr1573-H {{constructor inherited by 'H' is implicitly deleted because field 'g' has no default constructor}} + // since-cxx11-note@#cwg1573-H {{constructor inherited by 'H' is implicitly deleted because field 'g' has no default constructor}} // deleted definition of constructor is inherited - struct I { I(int) = delete; }; // #dr1573-I + struct I { I(int) = delete; }; // #cwg1573-I struct J : I { using I::I; }; J j(0); // since-cxx11-error@-1 {{call to deleted constructor of 'J'}} - // since-cxx11-note@#dr1573-I {{'I' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1573-I {{'I' has been explicitly marked deleted here}} #endif } @@ -483,18 +483,18 @@ namespace std { } // std #endif -namespace dr1579 { // dr1579: 3.9 +namespace cwg1579 { // cwg1579: 3.9 #if __cplusplus >= 201103L template struct GenericMoveOnly { GenericMoveOnly(); - template GenericMoveOnly(const GenericMoveOnly &) = delete; // #dr1579-deleted-U - GenericMoveOnly(const int &) = delete; // #dr1579-deleted-int + template GenericMoveOnly(const GenericMoveOnly &) = delete; // #cwg1579-deleted-U + GenericMoveOnly(const int &) = delete; // #cwg1579-deleted-int template GenericMoveOnly(GenericMoveOnly &&); GenericMoveOnly(int &&); }; -GenericMoveOnly DR1579_Eligible(GenericMoveOnly CharMO) { +GenericMoveOnly CWG1579_Eligible(GenericMoveOnly CharMO) { int i; GenericMoveOnly GMO; @@ -510,7 +510,7 @@ GenericMoveOnly DR1579_Eligible(GenericMoveOnly CharMO) { GenericMoveOnly GlobalMO; -GenericMoveOnly DR1579_Ineligible(int &AnInt, +GenericMoveOnly CWG1579_Ineligible(int &AnInt, GenericMoveOnly &CharMO) { static GenericMoveOnly StaticMove; extern GenericMoveOnly ExternMove; @@ -518,63 +518,63 @@ GenericMoveOnly DR1579_Ineligible(int &AnInt, if (0) return AnInt; // since-cxx11-error@-1 {{conversion function from 'int' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) return GlobalMO; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) return StaticMove; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) return ExternMove; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) return AnInt; // since-cxx11-error@-1 {{conversion function from 'int' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} else return CharMO; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} } -auto DR1579_lambda_valid = [](GenericMoveOnly mo) -> +auto CWG1579_lambda_valid = [](GenericMoveOnly mo) -> GenericMoveOnly { return mo; }; -auto DR1579_lambda_invalid = []() -> GenericMoveOnly { +auto CWG1579_lambda_invalid = []() -> GenericMoveOnly { static GenericMoveOnly mo; return mo; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} }; #endif -} // end namespace dr1579 +} // end namespace cwg1579 -namespace dr1584 { // dr1584: 7 drafting 2015-05 +namespace cwg1584 { // cwg1584: 7 drafting 2015-05 #if __cplusplus >= 201103L // Deducing function types from cv-qualified types - template void f(const T *); // #dr1584-f + template void f(const T *); // #cwg1584-f template void g(T *, const T * = 0); template void h(T *) { T::error; } // since-cxx11-error@-1 {{type 'void ()' cannot be used prior to '::' because it has no members}} - // since-cxx11-note@#dr1584-h {{in instantiation of function template specialization 'dr1584::h' requested here}} + // since-cxx11-note@#cwg1584-h {{in instantiation of function template specialization 'cwg1584::h' requested here}} template void h(const T *); void i() { f(&i); // since-cxx11-error@-1 {{no matching function for call to 'f'}} - // since-cxx11-note@#dr1584-f {{candidate template ignored: could not match 'const T *' against 'void (*)()'}} + // since-cxx11-note@#cwg1584-f {{candidate template ignored: could not match 'const T *' against 'void (*)()'}} g(&i); - h(&i); // #dr1584-h + h(&i); // #cwg1584-h } #endif } -namespace dr1589 { // dr1589: 3.7 c++11 +namespace cwg1589 { // cwg1589: 3.7 c++11 #if __cplusplus >= 201103L // Ambiguous ranking of list-initialization sequences @@ -595,33 +595,33 @@ namespace dr1589 { // dr1589: 3.7 c++11 namespace with_error { void f0(long); - void f0(std::initializer_list); // #dr1589-f0-ilist - void f0(std::initializer_list, int = 0); // #dr1589-f0-ilist-int + void f0(std::initializer_list); // #cwg1589-f0-ilist + void f0(std::initializer_list, int = 0); // #cwg1589-f0-ilist-int void g0() { f0({1L}); } // since-cxx11-error@-1 {{call to 'f0' is ambiguous}} - // since-cxx11-note@#dr1589-f0-ilist {{candidate function}} - // since-cxx11-note@#dr1589-f0-ilist-int {{candidate function}} + // since-cxx11-note@#cwg1589-f0-ilist {{candidate function}} + // since-cxx11-note@#cwg1589-f0-ilist-int {{candidate function}} void f1(int); - void f1(std::initializer_list); // #dr1589-f1-ilist - void f1(std::initializer_list, int = 0); // #dr1589-f1-ilist-long + void f1(std::initializer_list); // #cwg1589-f1-ilist + void f1(std::initializer_list, int = 0); // #cwg1589-f1-ilist-long void g1() { f1({42}); } // since-cxx11-error@-1 {{call to 'f1' is ambiguous}} - // since-cxx11-note@#dr1589-f1-ilist {{candidate function}} - // since-cxx11-note@#dr1589-f1-ilist-long {{candidate function}} + // since-cxx11-note@#cwg1589-f1-ilist {{candidate function}} + // since-cxx11-note@#cwg1589-f1-ilist-long {{candidate function}} void f2(std::pair); - void f2(std::initializer_list); // #dr1589-f2-ilist - void f2(std::initializer_list, int = 0); // #dr1589-f2-ilist-int + void f2(std::initializer_list); // #cwg1589-f2-ilist + void f2(std::initializer_list, int = 0); // #cwg1589-f2-ilist-int void g2() { f2({"foo","bar"}); } // since-cxx11-error@-1 {{call to 'f2' is ambiguous}} - // since-cxx11-note@#dr1589-f2-ilist {{candidate function}} - // since-cxx11-note@#dr1589-f2-ilist-int {{candidate function}} + // since-cxx11-note@#cwg1589-f2-ilist {{candidate function}} + // since-cxx11-note@#cwg1589-f2-ilist-int {{candidate function}} } #endif -} // dr1589 +} // cwg1589 -namespace dr1591 { //dr1591. Deducing array bound and element type from initializer list +namespace cwg1591 { //cwg1591. Deducing array bound and element type from initializer list #if __cplusplus >= 201103L template int h(T const(&)[N]); int X = h({1,2,3}); // T deduced to int, N deduced to 3 @@ -630,10 +630,10 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial int Y = j({42}); // T deduced to int, array bound not considered struct Aggr { int i; int j; }; - template int k(Aggr const(&)[N]); // #dr1591-k + template int k(Aggr const(&)[N]); // #cwg1591-k int Y0 = k({1,2,3}); // since-cxx11-error@-1 {{no matching function for call to 'k'}} - // since-cxx11-note@#dr1591-k {{candidate function [with N = 3] not viable: no known conversion from 'int' to 'const Aggr' for 1st argument}} + // since-cxx11-note@#cwg1591-k {{candidate function [with N = 3] not viable: no known conversion from 'int' to 'const Aggr' for 1st argument}} int Z = k({{1},{2},{3}}); // OK, N deduced to 3 template int m(int const(&)[M][N]); @@ -644,31 +644,31 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial namespace check_multi_dim_arrays { - template int ***f(const T (&a)[N][M][O]); // #dr1591-f-3 - template int **f(const T (&a)[N][M]); // #dr1591-f-2 + template int ***f(const T (&a)[N][M][O]); // #cwg1591-f-3 + template int **f(const T (&a)[N][M]); // #cwg1591-f-2 - template int *f(const T (&a)[N]); // #dr1591-f-1 + template int *f(const T (&a)[N]); // #cwg1591-f-1 int ***p3 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12} } }); int ***p33 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); // since-cxx11-error@-1 {{no matching function for call to 'f'}} - // since-cxx11-note@#dr1591-f-2 {{candidate template ignored: couldn't infer template argument 'T'}} - // since-cxx11-note@#dr1591-f-1 {{candidate template ignored: couldn't infer template argument 'T'}} - // since-cxx11-note@#dr1591-f-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} + // since-cxx11-note@#cwg1591-f-2 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#cwg1591-f-1 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#cwg1591-f-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} int **p2 = f({ {1,2,3}, {3, 4, 5} }); int **p22 = f({ {1,2}, {3, 4} }); int *p1 = f({1, 2, 3}); } namespace check_multi_dim_arrays_rref { - template int ***g(T (&&a)[N][M][O]); // #dr1591-g-3 - template int **g(T (&&a)[N][M]); // #dr1591-g-2 + template int ***g(T (&&a)[N][M][O]); // #cwg1591-g-3 + template int **g(T (&&a)[N][M]); // #cwg1591-g-2 - template int *g(T (&&a)[N]); // #dr1591-g-1 + template int *g(T (&&a)[N]); // #cwg1591-g-1 int ***p3 = g({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12} } }); int ***p33 = g({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); // since-cxx11-error@-1 {{no matching function for call to 'g'}} - // since-cxx11-note@#dr1591-g-2 {{candidate template ignored: couldn't infer template argument 'T'}} - // since-cxx11-note@#dr1591-g-1 {{candidate template ignored: couldn't infer template argument 'T'}} - // since-cxx11-note@#dr1591-g-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} + // since-cxx11-note@#cwg1591-g-2 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#cwg1591-g-1 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#cwg1591-g-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} int **p2 = g({ {1,2,3}, {3, 4, 5} }); int **p22 = g({ {1,2}, {3, 4} }); int *p1 = g({1, 2, 3}); @@ -684,8 +684,8 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial template int *i(T (&&)[N]); // #1 template char *i(std::initializer_list &&); // #2 - template int **i(T (&&)[N][M]); // #3 #dr1591-i-2 - template char **i(std::initializer_list (&&)[N]); // #4 #dr1591-i-1 + template int **i(T (&&)[N][M]); // #3 #cwg1591-i-2 + template char **i(std::initializer_list (&&)[N]); // #4 #cwg1591-i-1 template short *i(T (&&)[2]); // #5 @@ -697,11 +697,11 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial void *pv1 = i({ {1, 2, 3}, {4, 5, 6} }); // ambiguous btw 3 & 4 // since-cxx11-error@-1 {{call to 'i' is ambiguous}} - // since-cxx11-note@#dr1591-i-2 {{candidate function [with T = int, N = 2, M = 3]}} - // since-cxx11-note@#dr1591-i-1 {{candidate function [with T = int, N = 2]}} + // since-cxx11-note@#cwg1591-i-2 {{candidate function [with T = int, N = 2, M = 3]}} + // since-cxx11-note@#cwg1591-i-1 {{candidate function [with T = int, N = 2]}} char **pcc = i({ {1}, {2, 3} }); // OK #4 short *ps = i(Arr{1, 2}); // OK #5 } #endif -} // dr1591 +} // cwg1591 diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index f4d6c04fb8e0..6d7bb7619f8b 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -25,7 +25,7 @@ namespace std { } // std #endif -namespace dr1601 { // dr1601: 10 +namespace cwg1601 { // cwg1601: 10 enum E : char { e }; // cxx98-error@-1 {{enumeration types with a fixed underlying type are a C++11 extension}} void f(char); @@ -33,9 +33,9 @@ void f(int); void g() { f(e); } -} // namespace dr1601 +} // namespace cwg1601 -namespace dr1606 { // dr1606: 3.1 +namespace cwg1606 { // cwg1606: 3.1 #if __cplusplus >= 201103L std::size_t test() { int i = 1; @@ -44,16 +44,16 @@ namespace dr1606 { // dr1606: 3.1 return sizeof(f); } #endif -} // namespace dr1606 +} // namespace cwg1606 -namespace dr1611 { // dr1611: dup 1658 +namespace cwg1611 { // cwg1611: dup 1658 struct A { A(int); }; struct B : virtual A { virtual void f() = 0; }; struct C : B { C() : A(0) {} void f(); }; C c; } -namespace dr1631 { // dr1631: 3.7 +namespace cwg1631 { // cwg1631: 3.7 #if __cplusplus >= 201103L // Incorrect overload resolution for single-element initializer-list @@ -70,24 +70,24 @@ namespace dr1631 { // dr1631: 3.7 namespace with_error { void f(B, int); // TODO: expected- note {{candidate function}} - void f(int, A); // #dr1631-f - void f(int, A, int = 0); // #dr1631-f-int + void f(int, A); // #cwg1631-f + void f(int, A, int = 0); // #cwg1631-f-int void test() { f({0}, {{1}}); // since-cxx11-error@-1 {{call to 'f' is ambiguous}} - // since-cxx11-note@#dr1631-f {{candidate function}} - // since-cxx11-note@#dr1631-f-int {{candidate function}} + // since-cxx11-note@#cwg1631-f {{candidate function}} + // since-cxx11-note@#cwg1631-f-int {{candidate function}} } } #endif } -namespace dr1638 { // dr1638: 3.1 +namespace cwg1638 { // cwg1638: 3.1 #if __cplusplus >= 201103L template struct A { - enum class E; // #dr1638-E - enum class F : T; // #dr1638-F + enum class E; // #cwg1638-E + enum class F : T; // #cwg1638-F }; template<> enum class A::E; @@ -100,13 +100,13 @@ namespace dr1638 { // dr1638: 3.1 template<> enum class A::F; // since-cxx11-error@-1 {{enumeration redeclared with different underlying type 'int' (was 'short')}} - // since-cxx11-note@#dr1638-F {{previous declaration is here}} + // since-cxx11-note@#cwg1638-F {{previous declaration is here}} template<> enum class A::E : char; // since-cxx11-error@-1 {{enumeration redeclared with different underlying type 'char' (was 'int')}} - // since-cxx11-note@#dr1638-E {{previous declaration is here}} + // since-cxx11-note@#cwg1638-E {{previous declaration is here}} template<> enum class A::F : int; // since-cxx11-error@-1 {{enumeration redeclared with different underlying type 'int' (was 'char')}} - // since-cxx11-note@#dr1638-F {{previous declaration is here}} + // since-cxx11-note@#cwg1638-F {{previous declaration is here}} enum class A::E; // since-cxx11-error@-1 {{template specialization requires 'template<>'}} @@ -124,34 +124,34 @@ namespace dr1638 { // dr1638: 3.1 #endif } -namespace dr1645 { // dr1645: 3.9 +namespace cwg1645 { // cwg1645: 3.9 #if __cplusplus >= 201103L struct A { - constexpr A(int, float = 0); // #dr1645-int-float - explicit A(int, int = 0); // #dr1645-int-int - A(int, int, int = 0) = delete; // #dr1645-int-int-int + constexpr A(int, float = 0); // #cwg1645-int-float + explicit A(int, int = 0); // #cwg1645-int-int + A(int, int, int = 0) = delete; // #cwg1645-int-int-int }; struct B : A { - using A::A; // #dr1645-using + using A::A; // #cwg1645-using }; constexpr B a(0); // since-cxx11-error@-1 {{call to constructor of 'const B' is ambiguous}} - // since-cxx11-note@#dr1645-int-float {{candidate inherited constructor}} - // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} - // since-cxx11-note@#dr1645-int-int {{candidate inherited constructor}} - // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#cwg1645-int-float {{candidate inherited constructor}} + // since-cxx11-note@#cwg1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#cwg1645-int-int {{candidate inherited constructor}} + // since-cxx11-note@#cwg1645-using {{constructor from base class 'A' inherited here}} constexpr B b(0, 0); // since-cxx11-error@-1 {{call to constructor of 'const B' is ambiguous}} - // since-cxx11-note@#dr1645-int-int {{candidate inherited constructor}} - // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} - // since-cxx11-note@#dr1645-int-int-int {{candidate inherited constructor has been explicitly deleted}} - // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#cwg1645-int-int {{candidate inherited constructor}} + // since-cxx11-note@#cwg1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#cwg1645-int-int-int {{candidate inherited constructor has been explicitly deleted}} + // since-cxx11-note@#cwg1645-using {{constructor from base class 'A' inherited here}} #endif } -namespace dr1652 { // dr1652: 3.6 +namespace cwg1652 { // cwg1652: 3.6 int a, b; int arr[&a + 1 == &b ? 1 : 2]; // expected-error@-1 {{variable length arrays in C++ are a Clang extension}} @@ -159,7 +159,7 @@ namespace dr1652 { // dr1652: 3.6 // expected-error@-3 {{variable length array declaration not allowed at file scope}} } -namespace dr1653 { // dr1653: 4 c++17 +namespace cwg1653 { // cwg1653: 4 c++17 void f(bool b) { ++b; // cxx98-14-warning@-1 {{incrementing expression of type bool is deprecated and incompatible with C++17}} @@ -176,10 +176,10 @@ namespace dr1653 { // dr1653: 4 c++17 } } -namespace dr1658 { // dr1658: 5 +namespace cwg1658 { // cwg1658: 5 namespace DefCtor { - class A { A(); }; // #dr1658-A1 - class B { ~B(); }; // #dr1658-B1 + class A { A(); }; // #cwg1658-A1 + class B { ~B(); }; // #cwg1658-B1 // The stars align! An abstract class does not construct its virtual bases. struct C : virtual A { C(); virtual void foo() = 0; }; @@ -190,76 +190,76 @@ namespace dr1658 { // dr1658: 5 // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // In all other cases, we are not so lucky. - struct E : A { E(); virtual void foo() = 0; }; // #dr1658-E1 - E::E() = default; // #dr1658-E1-ctor + struct E : A { E(); virtual void foo() = 0; }; // #cwg1658-E1 + E::E() = default; // #cwg1658-E1-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-2 {{base class 'A' has private default constructor}} - // cxx98-note@-3 {{in defaulted default constructor for 'dr1658::DefCtor::E' first required here}} - // cxx98-note@#dr1658-A1 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-E1-ctor {{defaulting this default constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-E1 {{default constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible default constructor}} - struct F : virtual A { F(); }; // #dr1658-F1 - F::F() = default; // #dr1658-F1-ctor + // cxx98-note@-3 {{in defaulted default constructor for 'cwg1658::DefCtor::E' first required here}} + // cxx98-note@#cwg1658-A1 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-E1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-E1 {{default constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible default constructor}} + struct F : virtual A { F(); }; // #cwg1658-F1 + F::F() = default; // #cwg1658-F1-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-2 {{inherited virtual base class 'A' has private default constructor}} - // cxx98-note@-3 {{in defaulted default constructor for 'dr1658::DefCtor::F' first required here}} - // cxx98-note@#dr1658-A1 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-F1-ctor {{defaulting this default constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-F1 {{default constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible default constructor}} + // cxx98-note@-3 {{in defaulted default constructor for 'cwg1658::DefCtor::F' first required here}} + // cxx98-note@#cwg1658-A1 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-F1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-F1 {{default constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible default constructor}} - struct G : B { G(); virtual void foo() = 0; }; // #dr1658-G1 - G::G() = default; // #dr1658-G1-ctor + struct G : B { G(); virtual void foo() = 0; }; // #cwg1658-G1 + G::G() = default; // #cwg1658-G1-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - // cxx98-error@#dr1658-G1 {{base class 'B' has private destructor}} - // cxx98-note@#dr1658-G1-ctor {{in defaulted default constructor for 'dr1658::DefCtor::G' first required here}} - // cxx98-note@#dr1658-B1 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-G1-ctor {{defaulting this default constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-G1 {{default constructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} - struct H : virtual B { H(); }; // #dr1658-H1 - H::H() = default; // #dr1658-H1-ctor + // cxx98-error@#cwg1658-G1 {{base class 'B' has private destructor}} + // cxx98-note@#cwg1658-G1-ctor {{in defaulted default constructor for 'cwg1658::DefCtor::G' first required here}} + // cxx98-note@#cwg1658-B1 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-G1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-G1 {{default constructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} + struct H : virtual B { H(); }; // #cwg1658-H1 + H::H() = default; // #cwg1658-H1-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - // cxx98-error@#dr1658-H1 {{base class 'B' has private destructor}} - // cxx98-note@#dr1658-H1-ctor {{in defaulted default constructor for 'dr1658::DefCtor::H' first required here}} - // cxx98-note@#dr1658-B1 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-H1-ctor {{defaulting this default constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-H1 {{default constructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} + // cxx98-error@#cwg1658-H1 {{base class 'B' has private destructor}} + // cxx98-note@#cwg1658-H1-ctor {{in defaulted default constructor for 'cwg1658::DefCtor::H' first required here}} + // cxx98-note@#cwg1658-B1 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-H1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-H1 {{default constructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} } namespace Dtor { - class B { ~B(); }; // #dr1658-B2 + class B { ~B(); }; // #cwg1658-B2 struct D : virtual B { ~D(); virtual void foo() = 0; }; D::~D() = default; // ok, not deleted // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - struct G : B { ~G(); virtual void foo() = 0; }; // #dr1658-G2 - G::~G() = default; // #dr1658-G2-dtor + struct G : B { ~G(); virtual void foo() = 0; }; // #cwg1658-G2 + G::~G() = default; // #cwg1658-G2-dtor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - // cxx98-error@#dr1658-G2 {{base class 'B' has private destructor}} - // cxx98-note@#dr1658-G2-dtor {{in defaulted destructor for 'dr1658::Dtor::G' first required here}} - // cxx98-note@#dr1658-B2 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-G2-dtor {{defaulting this destructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-G2 {{destructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} - struct H : virtual B { ~H(); }; // #dr1658-H2 - H::~H() = default; // #dr1658-H2-dtor + // cxx98-error@#cwg1658-G2 {{base class 'B' has private destructor}} + // cxx98-note@#cwg1658-G2-dtor {{in defaulted destructor for 'cwg1658::Dtor::G' first required here}} + // cxx98-note@#cwg1658-B2 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-G2-dtor {{defaulting this destructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-G2 {{destructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} + struct H : virtual B { ~H(); }; // #cwg1658-H2 + H::~H() = default; // #cwg1658-H2-dtor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - // cxx98-error@#dr1658-H2 {{base class 'B' has private destructor}} - // cxx98-note@#dr1658-H2-dtor {{in defaulted destructor for 'dr1658::Dtor::H' first required here}} - // cxx98-note@#dr1658-B2 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-H2-dtor {{defaulting this destructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-H2 {{destructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} + // cxx98-error@#cwg1658-H2 {{base class 'B' has private destructor}} + // cxx98-note@#cwg1658-H2-dtor {{in defaulted destructor for 'cwg1658::Dtor::H' first required here}} + // cxx98-note@#cwg1658-B2 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-H2-dtor {{defaulting this destructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-H2 {{destructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} } namespace MemInit { - struct A { A(int); }; // #dr1658-A3 + struct A { A(int); }; // #cwg1658-A3 struct B : virtual A { B() {} virtual void f() = 0; }; struct C : virtual A { C() {} - // expected-error@-1 {{constructor for 'dr1658::MemInit::C' must explicitly initialize the base class 'A' which does not have a default constructor}} - // expected-note@#dr1658-A3 {{'dr1658::MemInit::A' declared here}} + // expected-error@-1 {{constructor for 'cwg1658::MemInit::C' must explicitly initialize the base class 'A' which does not have a default constructor}} + // expected-note@#cwg1658-A3 {{'cwg1658::MemInit::A' declared here}} }; } @@ -277,7 +277,7 @@ namespace dr1658 { // dr1658: 5 } namespace CopyCtor { - class A { A(const A&); A(A&&); }; // #dr1658-A5 + class A { A(const A&); A(A&&); }; // #cwg1658-A5 // cxx98-error@-1 {{rvalue references are a C++11 extension}} struct C : virtual A { C(const C&); C(C&&); virtual void foo() = 0; }; @@ -288,46 +288,46 @@ namespace dr1658 { // dr1658: 5 // cxx98-error@-1 {{rvalue references are a C++11 extension}} // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} - struct E : A { E(const E&); E(E&&); virtual void foo() = 0; }; // #dr1658-E5 + struct E : A { E(const E&); E(E&&); virtual void foo() = 0; }; // #cwg1658-E5 // cxx98-error@-1 {{rvalue references are a C++11 extension}} - E::E(const E&) = default; // #dr1658-E5-copy-ctor + E::E(const E&) = default; // #cwg1658-E5-copy-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-2 {{base class 'A' has private copy constructor}} - // cxx98-note@-3 {{in defaulted copy constructor for 'dr1658::CopyCtor::E' first required here}} - // cxx98-note@#dr1658-A5 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-E5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-E5 {{copy constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} - E::E(E&&) = default; // #dr1658-E5-move-ctor + // cxx98-note@-3 {{in defaulted copy constructor for 'cwg1658::CopyCtor::E' first required here}} + // cxx98-note@#cwg1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-E5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-E5 {{copy constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} + E::E(E&&) = default; // #cwg1658-E5-move-ctor // cxx98-error@-1 {{rvalue references are a C++11 extension}} // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-3 {{base class 'A' has private move constructor}} - // cxx98-note@-4 {{in defaulted move constructor for 'dr1658::CopyCtor::E' first required here}} - // cxx98-note@#dr1658-A5 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-E5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-E5 {{move constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible move constructor}} - struct F : virtual A { F(const F&); F(F&&); }; // #dr1658-F5 + // cxx98-note@-4 {{in defaulted move constructor for 'cwg1658::CopyCtor::E' first required here}} + // cxx98-note@#cwg1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-E5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-E5 {{move constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible move constructor}} + struct F : virtual A { F(const F&); F(F&&); }; // #cwg1658-F5 // cxx98-error@-1 {{rvalue references are a C++11 extension}} - F::F(const F&) = default; // #dr1658-F5-copy-ctor + F::F(const F&) = default; // #cwg1658-F5-copy-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-2 {{inherited virtual base class 'A' has private copy constructor}} - // cxx98-note@-3 {{in defaulted copy constructor for 'dr1658::CopyCtor::F' first required here}} - // cxx98-note@#dr1658-A5 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-F5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-F5 {{copy constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} - F::F(F&&) = default; // #dr1658-F5-move-ctor + // cxx98-note@-3 {{in defaulted copy constructor for 'cwg1658::CopyCtor::F' first required here}} + // cxx98-note@#cwg1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-F5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-F5 {{copy constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} + F::F(F&&) = default; // #cwg1658-F5-move-ctor // cxx98-error@-1 {{rvalue references are a C++11 extension}} // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-3 {{inherited virtual base class 'A' has private move constructor}} - // cxx98-note@-4 {{in defaulted move constructor for 'dr1658::CopyCtor::F' first required here}} - // cxx98-note@#dr1658-A5 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-F5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-F5 {{move constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible move constructor}} + // cxx98-note@-4 {{in defaulted move constructor for 'cwg1658::CopyCtor::F' first required here}} + // cxx98-note@#cwg1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-F5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-F5 {{move constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible move constructor}} } - // assignment case is superseded by dr2180 + // assignment case is superseded by cwg2180 } -namespace dr1672 { // dr1672: 7 +namespace cwg1672 { // cwg1672: 7 struct Empty {}; struct A : Empty {}; struct B { Empty e; }; @@ -352,9 +352,9 @@ namespace dr1672 { // dr1672: 7 static_assert(!__is_standard_layout(Y), ""); } -namespace dr1684 { // dr1684: 3.6 +namespace cwg1684 { // cwg1684: 3.6 #if __cplusplus >= 201103L - struct NonLiteral { // #dr1684-struct + struct NonLiteral { // #cwg1684-struct NonLiteral(); constexpr int f() { return 0; } // cxx11-warning@-1 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior}} @@ -362,34 +362,34 @@ namespace dr1684 { // dr1684: 3.6 constexpr int f(NonLiteral &) { return 0; } constexpr int f(NonLiteral) { return 0; } // cxx11-20-error@-1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} - // cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-note@#cwg1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} #endif } -namespace dr1687 { // dr1687: 7 +namespace cwg1687 { // cwg1687: 7 template struct To { - operator T(); // #dr1687-op-T + operator T(); // #cwg1687-op-T }; int *a = To() + 100.0; // expected-error@-1 {{invalid operands to binary expression ('To' and 'double')}} - // expected-note@#dr1687-op-T {{first operand was implicitly converted to type 'int *'}} - // since-cxx20-note@#dr1687-op-T {{second operand was implicitly converted to type 'dr1687::E2'}} + // expected-note@#cwg1687-op-T {{first operand was implicitly converted to type 'int *'}} + // since-cxx20-note@#cwg1687-op-T {{second operand was implicitly converted to type 'cwg1687::E2'}} int *b = To() + To(); // expected-error@-1 {{invalid operands to binary expression ('To' and 'To')}} - // expected-note@#dr1687-op-T {{first operand was implicitly converted to type 'int *'}} - // expected-note@#dr1687-op-T {{second operand was implicitly converted to type 'double'}} + // expected-note@#cwg1687-op-T {{first operand was implicitly converted to type 'int *'}} + // expected-note@#cwg1687-op-T {{second operand was implicitly converted to type 'double'}} #if __cplusplus >= 202002L enum E1 {}; enum E2 {}; auto c = To() <=> To(); // since-cxx20-error@-1 {{invalid operands to binary expression ('To' and 'To')}} - // since-cxx20-note@#dr1687-op-T {{operand was implicitly converted to type 'dr1687::E}} + // since-cxx20-note@#cwg1687-op-T {{operand was implicitly converted to type 'cwg1687::E}} #endif } -namespace dr1690 { // dr1690: 9 +namespace cwg1690 { // cwg1690: 9 // See also the various tests in "CXX/basic/basic.lookup/basic.lookup.argdep". #if __cplusplus >= 201103L namespace N { @@ -404,7 +404,7 @@ namespace dr1690 { // dr1690: 9 #endif } -namespace dr1691 { // dr1691: 9 +namespace cwg1691 { // cwg1691: 9 #if __cplusplus >= 201103L namespace N { namespace M { @@ -412,19 +412,19 @@ namespace dr1691 { // dr1691: 9 void f(E); } enum M::E : int {}; - void g(M::E); // #dr1691-g + void g(M::E); // #cwg1691-g } void test() { N::M::E e; f(e); // ok g(e); // since-cxx11-error@-1 {{use of undeclared identifier 'g'; did you mean 'N::g'?}} - // since-cxx11-note@#dr1691-g {{'N::g' declared here}} + // since-cxx11-note@#cwg1691-g {{'N::g' declared here}} } #endif } -namespace dr1692 { // dr1692: 9 +namespace cwg1692 { // cwg1692: 9 namespace N { struct A { struct B { @@ -439,7 +439,7 @@ namespace dr1692 { // dr1692: 9 } } -namespace dr1696 { // dr1696: 7 +namespace cwg1696 { // cwg1696: 7 namespace std_examples { #if __cplusplus >= 201402L extern struct A a; @@ -456,66 +456,66 @@ namespace dr1696 { // dr1696: 7 struct A { A(); ~A(); }; #if __cplusplus >= 201103L struct B { - A &&a; // #dr1696-a + A &&a; // #cwg1696-a B() : a{} {} // since-cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-a {{reference member declared here}} + // since-cxx11-note@#cwg1696-a {{reference member declared here}} } b; #endif struct C { C(); - const A &a; // #dr1696-C-a + const A &a; // #cwg1696-C-a }; C::C() : a(A()) {} // expected-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // expected-note@#dr1696-C-a {{reference member declared here}} + // expected-note@#cwg1696-C-a {{reference member declared here}} #if __cplusplus >= 201103L - // This is OK in C++14 onwards, per DR1815, though we don't support that yet: + // This is OK in C++14 onwards, per CWG1815, though we don't support that yet: // D1 d1 = {}; // is equivalent to // D1 d1 = {A()}; // ... which lifetime-extends the A temporary. struct D1 { // cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // cxx11-note@#dr1696-d1 {{in implicit default constructor for 'dr1696::D1' first required here}} - // cxx11-note@#dr1696-D1-a {{initializing field 'a' with default member initializer}} - const A &a = A(); // #dr1696-D1-a + // cxx11-note@#cwg1696-d1 {{in implicit default constructor for 'cwg1696::D1' first required here}} + // cxx11-note@#cwg1696-D1-a {{initializing field 'a' with default member initializer}} + const A &a = A(); // #cwg1696-D1-a }; - D1 d1 = {}; // #dr1696-d1 + D1 d1 = {}; // #cwg1696-d1 // since-cxx14-warning@-1 {{lifetime extension of temporary created by aggregate initialization using a default member initializer is not yet supported; lifetime of temporary will end at the end of the full-expression}} - // since-cxx14-note@#dr1696-D1-a {{initializing field 'a' with default member initializer}} + // since-cxx14-note@#cwg1696-D1-a {{initializing field 'a' with default member initializer}} struct D2 { - const A &a = A(); // #dr1696-D2-a + const A &a = A(); // #cwg1696-D2-a D2() {} // since-cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-D2-a {{initializing field 'a' with default member initializer}} + // since-cxx11-note@#cwg1696-D2-a {{initializing field 'a' with default member initializer}} }; struct D3 { // since-cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-d3 {{in implicit default constructor for 'dr1696::D3' first required here}} - // since-cxx11-note@#dr1696-D3-a {{initializing field 'a' with default member initializer}} - const A &a = A(); // #dr1696-D3-a + // since-cxx11-note@#cwg1696-d3 {{in implicit default constructor for 'cwg1696::D3' first required here}} + // since-cxx11-note@#cwg1696-D3-a {{initializing field 'a' with default member initializer}} + const A &a = A(); // #cwg1696-D3-a }; - D3 d3; // #dr1696-d3 + D3 d3; // #cwg1696-d3 struct haslist1 { - std::initializer_list il; // #dr1696-il-1 + std::initializer_list il; // #cwg1696-il-1 haslist1(int i) : il{i, 2, 3} {} // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-il-1 {{'std::initializer_list' member declared here}} + // since-cxx11-note@#cwg1696-il-1 {{'std::initializer_list' member declared here}} }; struct haslist2 { - std::initializer_list il; // #dr1696-il-2 + std::initializer_list il; // #cwg1696-il-2 haslist2(); }; haslist2::haslist2() : il{1, 2} {} // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-il-2 {{'std::initializer_list' member declared here}} + // since-cxx11-note@#cwg1696-il-2 {{'std::initializer_list' member declared here}} struct haslist3 { std::initializer_list il = {1, 2, 3}; @@ -523,17 +523,17 @@ namespace dr1696 { // dr1696: 7 struct haslist4 { // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-hl4 {{in implicit default constructor for 'dr1696::haslist4' first required here}} - // since-cxx11-note@#dr1696-il-4 {{initializing field 'il' with default member initializer}} - std::initializer_list il = {1, 2, 3}; // #dr1696-il-4 + // since-cxx11-note@#cwg1696-hl4 {{in implicit default constructor for 'cwg1696::haslist4' first required here}} + // since-cxx11-note@#cwg1696-il-4 {{initializing field 'il' with default member initializer}} + std::initializer_list il = {1, 2, 3}; // #cwg1696-il-4 }; - haslist4 hl4; // #dr1696-hl4 + haslist4 hl4; // #cwg1696-hl4 struct haslist5 { - std::initializer_list il = {1, 2, 3}; // #dr1696-il-5 + std::initializer_list il = {1, 2, 3}; // #cwg1696-il-5 haslist5() {} // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-il-5 {{nitializing field 'il' with default member initializer}} + // since-cxx11-note@#cwg1696-il-5 {{nitializing field 'il' with default member initializer}} }; #endif } diff --git a/clang/test/CXX/drs/dr17xx.cpp b/clang/test/CXX/drs/dr17xx.cpp index d3cb5e58f06b..fb53a56923b1 100644 --- a/clang/test/CXX/drs/dr17xx.cpp +++ b/clang/test/CXX/drs/dr17xx.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1710 { // dr1710: no +namespace cwg1710 { // cwg1710: no // FIXME: all of the following is well-formed template struct D1 : T::template B::template C {}; template struct D2 : T::B::template C {}; @@ -16,9 +16,9 @@ template struct D3 : T::template B::C {}; template struct D4 : T::B::C {}; // expected-error@-1 {{use 'template' keyword to treat 'B' as a dependent template name}} // expected-error@-2 {{use 'template' keyword to treat 'C' as a dependent template name}} -} // namespace dr1710 +} // namespace cwg1710 -namespace dr1715 { // dr1715: 3.9 +namespace cwg1715 { // cwg1715: 3.9 #if __cplusplus >= 201103L struct B { template B(T, typename T::Q); @@ -32,21 +32,21 @@ namespace dr1715 { // dr1715: 3.9 struct D : B { using B::B; }; - struct E : B { // #dr1715-E - template E(T t, typename T::Q q) : B(t, q) {} // #dr1715-E-ctor + struct E : B { // #cwg1715-E + template E(T t, typename T::Q q) : B(t, q) {} // #cwg1715-E-ctor }; B b(S(), 1); D d(S(), 2); E e(S(), 3); // since-cxx11-error@-1 {{no matching constructor for initialization of 'E'}} - // since-cxx11-note@#dr1715-E-ctor {{candidate template ignored: substitution failure [with T = S]: 'Q' is a private member of 'dr1715::S'}} - // since-cxx11-note@#dr1715-E {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} - // since-cxx11-note@#dr1715-E {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} + // since-cxx11-note@#cwg1715-E-ctor {{candidate template ignored: substitution failure [with T = S]: 'Q' is a private member of 'cwg1715::S'}} + // since-cxx11-note@#cwg1715-E {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} + // since-cxx11-note@#cwg1715-E {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} #endif } -namespace dr1719 { // dr1719: 19 +namespace cwg1719 { // cwg1719: 19 #if __cplusplus >= 201103L struct CStruct { int one; @@ -72,9 +72,9 @@ static_assert(__is_layout_compatible(const int, volatile int), ""); static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), ""); static_assert(__is_layout_compatible(int[], const volatile int[]), ""); #endif -} // namespace dr1719 +} // namespace cwg1719 -namespace dr1722 { // dr1722: 9 +namespace cwg1722 { // cwg1722: 9 #if __cplusplus >= 201103L void f() { const auto lambda = [](int x) { return x + 1; }; @@ -84,9 +84,9 @@ void f() { "Lambda-to-function-pointer conversion is expected to be noexcept"); } #endif -} // namespace dr1722 +} // namespace cwg1722 -namespace dr1734 { // dr1734: no +namespace cwg1734 { // cwg1734: no #if __cplusplus >= 201103L struct A { A(const A&) = delete; @@ -98,7 +98,7 @@ static_assert(__is_trivially_copyable(A), ""); #endif } -namespace dr1736 { // dr1736: 3.9 +namespace cwg1736 { // cwg1736: 3.9 #if __cplusplus >= 201103L struct S { template S(T t) { @@ -107,17 +107,17 @@ struct S { }; typename T::type value; // since-cxx11-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}} - // since-cxx11-note@#dr1736-l {{in instantiation of function template specialization 'dr1736::S::S' requested here}} - // since-cxx11-note@#dr1736-s {{in instantiation of function template specialization 'dr1736::S::S' requested here}} - L l(value); // #dr1736-l + // since-cxx11-note@#cwg1736-l {{in instantiation of function template specialization 'cwg1736::S::S' requested here}} + // since-cxx11-note@#cwg1736-s {{in instantiation of function template specialization 'cwg1736::S::S' requested here}} + L l(value); // #cwg1736-l } }; struct Q { typedef int type; } q; -S s(q); // #dr1736-s +S s(q); // #cwg1736-s #endif } -namespace dr1738 { // dr1738: sup P0136R1 +namespace cwg1738 { // cwg1738: sup P0136R1 #if __cplusplus >= 201103L struct A { template @@ -134,9 +134,9 @@ template B::B(int, double); #endif } -// dr1748 is in dr1748.cpp +// cwg1748 is in cwg1748.cpp -namespace dr1753 { // dr1753: 11 +namespace cwg1753 { // cwg1753: 11 typedef int T; struct A { typedef int T; }; namespace B { typedef int T; } @@ -145,9 +145,9 @@ namespace dr1753 { // dr1753: 11 n.~T(); n.T::~T(); - n.dr1753::~T(); - // expected-error@-1 {{'dr1753' does not refer to a type name in pseudo-destructor expression; expected the name of type 'T' (aka 'int')}} - n.dr1753::T::~T(); + n.cwg1753::~T(); + // expected-error@-1 {{'cwg1753' does not refer to a type name in pseudo-destructor expression; expected the name of type 'T' (aka 'int')}} + n.cwg1753::T::~T(); n.A::~T(); // expected-error@-1 {{the type of object expression ('T' (aka 'int')) does not match the type being destroyed ('A') in pseudo-destructor expression}} @@ -167,7 +167,7 @@ namespace dr1753 { // dr1753: 11 } } -namespace dr1756 { // dr1756: 3.7 +namespace cwg1756 { // cwg1756: 3.7 #if __cplusplus >= 201103L // Direct-list-initialization of a non-class object @@ -178,7 +178,7 @@ namespace dr1756 { // dr1756: 3.7 #endif } -namespace dr1758 { // dr1758: 3.7 +namespace cwg1758 { // cwg1758: 3.7 #if __cplusplus >= 201103L // Explicit conversion in copy/move list initialization @@ -197,7 +197,7 @@ namespace dr1758 { // dr1758: 3.7 #endif } -namespace dr1762 { // dr1762: 14 +namespace cwg1762 { // cwg1762: 14 #if __cplusplus >= 201103L float operator ""_E(const char *); float operator ""E(const char *); @@ -206,9 +206,9 @@ namespace dr1762 { // dr1762: 14 #endif } -// dr1772 is in dr177x.cpp +// cwg1772 is in cwg177x.cpp -namespace dr1778 { // dr1778: 9 +namespace cwg1778 { // cwg1778: 9 // Superseded by P1286R2. #if __cplusplus >= 201103L struct A { A() noexcept(true) = default; }; @@ -223,9 +223,9 @@ namespace dr1778 { // dr1778: 9 #endif } -// dr1779 is in dr177x.cpp +// cwg1779 is in cwg177x.cpp -namespace dr1794 { // dr1794: yes +namespace cwg1794 { // cwg1794: yes // NB: dup 1710 #if __cplusplus >= 201103L template