[llvm-branch-commits] [llvm] dde78a2 - Revert "Revert "[X86] combineBROADCAST_LOAD - merge across chains" (#128380)"
Author: Vitaly Buka Date: 2025-02-22T16:15:48-08:00 New Revision: dde78a2e84edc0fe987266a7fcae774dd36532c3 URL: https://github.com/llvm/llvm-project/commit/dde78a2e84edc0fe987266a7fcae774dd36532c3 DIFF: https://github.com/llvm/llvm-project/commit/dde78a2e84edc0fe987266a7fcae774dd36532c3.diff LOG: Revert "Revert "[X86] combineBROADCAST_LOAD - merge across chains" (#128380)" This reverts commit 50b0669e8468279518ae0be27c8b6a134c4d95d1. Added: Modified: llvm/lib/Target/X86/X86ISelLowering.cpp llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll llvm/test/CodeGen/X86/zero_extend_vector_inreg_of_broadcast_from_memory.ll Removed: diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 2bc76d3814792..a4357197e2843 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -59360,21 +59360,14 @@ static SDValue combineFP_EXTEND(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::FP_EXTEND, dl, VT, Cvt); } -// Try to find a larger VBROADCAST_LOAD/SUBV_BROADCAST_LOAD that we can extract -// from. Limit this to cases where the loads have the same input chain and the -// output chains are unused. This avoids any memory ordering issues. +// Try to find a larger VBROADCAST_LOAD/SUBV_BROADCAST_LOAD that we can extract. static SDValue combineBROADCAST_LOAD(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI) { assert((N->getOpcode() == X86ISD::VBROADCAST_LOAD || N->getOpcode() == X86ISD::SUBV_BROADCAST_LOAD) && "Unknown broadcast load type"); - // Only do this if the chain result is unused. - if (N->hasAnyUseOfValue(1)) -return SDValue(); - auto *MemIntrin = cast(N); - SDValue Ptr = MemIntrin->getBasePtr(); SDValue Chain = MemIntrin->getChain(); EVT VT = N->getSimpleValueType(0); @@ -59388,12 +59381,15 @@ static SDValue combineBROADCAST_LOAD(SDNode *N, SelectionDAG &DAG, cast(User)->getChain() == Chain && cast(User)->getMemoryVT().getSizeInBits() == MemVT.getSizeInBits() && -!User->hasAnyUseOfValue(1) && User->getValueSizeInBits(0).getFixedValue() > VT.getFixedSizeInBits()) { + assert(cast(User)->isSimple() && + MemIntrin->isSimple() && "Illegal broadcast load type"); SDValue Extract = extractSubVector(SDValue(User, 0), 0, DAG, SDLoc(N), VT.getSizeInBits()); Extract = DAG.getBitcast(VT, Extract); - return DCI.CombineTo(N, Extract, SDValue(User, 1)); + Extract = DCI.CombineTo(N, Extract, SDValue(User, 1)); + DAG.makeEquivalentMemoryOrdering(SDValue(N, 1), Extract.getValue(1)); + return Extract; } return SDValue(); diff --git a/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll b/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll index d617cfb6aedee..ca589e63b671a 100644 --- a/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll +++ b/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll @@ -1888,15 +1888,14 @@ define void @vec384_i8_widen_to_i16_factor2_broadcast_to_v24i16_factor24(ptr %in ; ; AVX2-LABEL: vec384_i8_widen_to_i16_factor2_broadcast_to_v24i16_factor24: ; AVX2: # %bb.0: -; AVX2-NEXT:vpbroadcastb (%rdi), %xmm0 -; AVX2-NEXT:vmovdqa 48(%rdi), %xmm1 -; AVX2-NEXT:vpshufb {{.*#+}} xmm1 = xmm1[1,3,5,7,9,11,13,15,u,u,u,u,u,u,u,u] -; AVX2-NEXT:vpbroadcastb (%rdi), %ymm2 -; AVX2-NEXT:vpunpcklbw {{.*#+}} ymm1 = ymm2[0],ymm1[0],ymm2[1],ymm1[1],ymm2[2],ymm1[2],ymm2[3],ymm1[3],ymm2[4],ymm1[4],ymm2[5],ymm1[5],ymm2[6],ymm1[6],ymm2[7],ymm1[7],ymm2[16],ymm1[16],ymm2[17],ymm1[17],ymm2[18],ymm1[18],ymm2[19],ymm1[19],ymm2[20],ymm1[20],ymm2[21],ymm1[21],ymm2[22],ymm1[22],ymm2[23],ymm1[23] -; AVX2-NEXT:vpaddb (%rsi), %ymm1, %ymm1 -; AVX2-NEXT:vpaddb 32(%rsi), %ymm0, %ymm0 -; AVX2-NEXT:vmovdqa %ymm0, 32(%rdx) -; AVX2-NEXT:vmovdqa %ymm1, (%rdx) +; AVX2-NEXT:vmovdqa 48(%rdi), %xmm0 +; AVX2-NEXT:vpshufb {{.*#+}} xmm0 = xmm0[1,3,5,7,9,11,13,15,u,u,u,u,u,u,u,u] +; AVX2-NEXT:vpbroadcastb (%rdi), %ymm1 +; AVX2-NEXT:vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; AVX2-NEXT:vpaddb (%rsi), %ymm0, %ymm0 +; AVX2-NEXT:vpaddb 32(%rsi), %ymm1, %ymm1 +; AVX2-NEXT:vmovdqa %ymm1, 32(%rdx) +; AVX2-NEXT:vmovdqa %ymm0, (%rdx) ; AVX2-NEXT:vzeroupper ; AVX2-NEXT:retq ; @@ -2112,15 +2111,14 @@ define void @vec384_i8_widen_to_i32_factor4_broadcast_t
[llvm-branch-commits] [llvm] 1aacd31 - Revert "[X86] combineBROADCAST_LOAD - merge across chains (#128209)"
Author: Vitaly Buka Date: 2025-02-22T16:02:11-08:00 New Revision: 1aacd3108d3fb66c1f2483e973b52a97006eba9b URL: https://github.com/llvm/llvm-project/commit/1aacd3108d3fb66c1f2483e973b52a97006eba9b DIFF: https://github.com/llvm/llvm-project/commit/1aacd3108d3fb66c1f2483e973b52a97006eba9b.diff LOG: Revert "[X86] combineBROADCAST_LOAD - merge across chains (#128209)" This reverts commit e21a1737f3523488a04169096fa27d0914a142a7. Added: Modified: llvm/lib/Target/X86/X86ISelLowering.cpp llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll llvm/test/CodeGen/X86/zero_extend_vector_inreg_of_broadcast_from_memory.ll Removed: diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index a4357197e2843..2bc76d3814792 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -59360,14 +59360,21 @@ static SDValue combineFP_EXTEND(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::FP_EXTEND, dl, VT, Cvt); } -// Try to find a larger VBROADCAST_LOAD/SUBV_BROADCAST_LOAD that we can extract. +// Try to find a larger VBROADCAST_LOAD/SUBV_BROADCAST_LOAD that we can extract +// from. Limit this to cases where the loads have the same input chain and the +// output chains are unused. This avoids any memory ordering issues. static SDValue combineBROADCAST_LOAD(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI) { assert((N->getOpcode() == X86ISD::VBROADCAST_LOAD || N->getOpcode() == X86ISD::SUBV_BROADCAST_LOAD) && "Unknown broadcast load type"); + // Only do this if the chain result is unused. + if (N->hasAnyUseOfValue(1)) +return SDValue(); + auto *MemIntrin = cast(N); + SDValue Ptr = MemIntrin->getBasePtr(); SDValue Chain = MemIntrin->getChain(); EVT VT = N->getSimpleValueType(0); @@ -59381,15 +59388,12 @@ static SDValue combineBROADCAST_LOAD(SDNode *N, SelectionDAG &DAG, cast(User)->getChain() == Chain && cast(User)->getMemoryVT().getSizeInBits() == MemVT.getSizeInBits() && +!User->hasAnyUseOfValue(1) && User->getValueSizeInBits(0).getFixedValue() > VT.getFixedSizeInBits()) { - assert(cast(User)->isSimple() && - MemIntrin->isSimple() && "Illegal broadcast load type"); SDValue Extract = extractSubVector(SDValue(User, 0), 0, DAG, SDLoc(N), VT.getSizeInBits()); Extract = DAG.getBitcast(VT, Extract); - Extract = DCI.CombineTo(N, Extract, SDValue(User, 1)); - DAG.makeEquivalentMemoryOrdering(SDValue(N, 1), Extract.getValue(1)); - return Extract; + return DCI.CombineTo(N, Extract, SDValue(User, 1)); } return SDValue(); diff --git a/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll b/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll index ca589e63b671a..d617cfb6aedee 100644 --- a/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll +++ b/llvm/test/CodeGen/X86/any_extend_vector_inreg_of_broadcast_from_memory.ll @@ -1888,14 +1888,15 @@ define void @vec384_i8_widen_to_i16_factor2_broadcast_to_v24i16_factor24(ptr %in ; ; AVX2-LABEL: vec384_i8_widen_to_i16_factor2_broadcast_to_v24i16_factor24: ; AVX2: # %bb.0: -; AVX2-NEXT:vmovdqa 48(%rdi), %xmm0 -; AVX2-NEXT:vpshufb {{.*#+}} xmm0 = xmm0[1,3,5,7,9,11,13,15,u,u,u,u,u,u,u,u] -; AVX2-NEXT:vpbroadcastb (%rdi), %ymm1 -; AVX2-NEXT:vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] -; AVX2-NEXT:vpaddb (%rsi), %ymm0, %ymm0 -; AVX2-NEXT:vpaddb 32(%rsi), %ymm1, %ymm1 -; AVX2-NEXT:vmovdqa %ymm1, 32(%rdx) -; AVX2-NEXT:vmovdqa %ymm0, (%rdx) +; AVX2-NEXT:vpbroadcastb (%rdi), %xmm0 +; AVX2-NEXT:vmovdqa 48(%rdi), %xmm1 +; AVX2-NEXT:vpshufb {{.*#+}} xmm1 = xmm1[1,3,5,7,9,11,13,15,u,u,u,u,u,u,u,u] +; AVX2-NEXT:vpbroadcastb (%rdi), %ymm2 +; AVX2-NEXT:vpunpcklbw {{.*#+}} ymm1 = ymm2[0],ymm1[0],ymm2[1],ymm1[1],ymm2[2],ymm1[2],ymm2[3],ymm1[3],ymm2[4],ymm1[4],ymm2[5],ymm1[5],ymm2[6],ymm1[6],ymm2[7],ymm1[7],ymm2[16],ymm1[16],ymm2[17],ymm1[17],ymm2[18],ymm1[18],ymm2[19],ymm1[19],ymm2[20],ymm1[20],ymm2[21],ymm1[21],ymm2[22],ymm1[22],ymm2[23],ymm1[23] +; AVX2-NEXT:vpaddb (%rsi), %ymm1, %ymm1 +; AVX2-NEXT:vpaddb 32(%rsi), %ymm0, %ymm0 +; AVX2-NEXT:vmovdqa %ymm0, 32(%rdx) +; AVX2-NEXT:vmovdqa %ymm1, (%rdx) ; AVX2-NEXT:vzeroupper ; AVX2-NEXT:retq ; @@ -2111,14 +2112,15 @@ define void @vec384_i8_widen_to_i32_factor4_broadcast_to_v12i32_f
[llvm-branch-commits] [clang] [clang][NFC] Remove CXXRecordDecl::lookupDependentName() and its helpers (PR #128392)
https://github.com/HighCommander4 created https://github.com/llvm/llvm-project/pull/128392 This function has been superseded by HeuristicResolver::lookupDependentName(), which implements the same heuristics and more. Porting note for any out-of-tree callers: ``` RD->lookupDependentName(Name, Filter); ``` can be replaced with: ``` HeuristicResolver(RD->getASTContext())->lookupDependentName(Name, Filter); ``` >From 4bb5f832edc9370e3d782427db8cd51b8ffdc835 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sat, 22 Feb 2025 22:48:03 -0500 Subject: [PATCH] [clang][NFC] Remove CXXRecordDecl::lookupDependentName() and its helpers This function has been superseded by HeuristicResolver::lookupDependentName(), which implements the same heuristics and more. Porting note for any out-of-tree callers: ``` RD->lookupDependentName(Name, Filter); ``` can be replaced with: ``` HeuristicResolver(RD->getASTContext())->lookupDependentName(Name, Filter); ``` --- clang/include/clang/AST/DeclCXX.h | 8 - clang/lib/AST/CXXInheritance.cpp | 53 --- 2 files changed, 61 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 266b93a64a390..dbd02ef7f8011 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1720,14 +1720,6 @@ class CXXRecordDecl : public RecordDecl { /// static analysis, or similar. bool hasMemberName(DeclarationName N) const; - /// Performs an imprecise lookup of a dependent name in this class. - /// - /// This function does not follow strict semantic rules and should be used - /// only when lookup rules can be relaxed, e.g. indexing. - std::vector - lookupDependentName(DeclarationName Name, - llvm::function_ref Filter); - /// Renders and displays an inheritance diagram /// for this C++ class and all of its base classes (transitively) using /// GraphViz. diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index ee5775837d535..ab862d57eae89 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -411,59 +411,6 @@ bool CXXRecordDecl::hasMemberName(DeclarationName Name) const { Paths); } -static bool -findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, DeclarationName Name) { - const TemplateSpecializationType *TST = - Specifier->getType()->getAs(); - if (!TST) { -auto *RT = Specifier->getType()->getAs(); -if (!RT) - return false; -return findOrdinaryMember(cast(RT->getDecl()), Path, Name); - } - TemplateName TN = TST->getTemplateName(); - const auto *TD = dyn_cast_or_null(TN.getAsTemplateDecl()); - if (!TD) -return false; - CXXRecordDecl *RD = TD->getTemplatedDecl(); - if (!RD) -return false; - return findOrdinaryMember(RD, Path, Name); -} - -std::vector CXXRecordDecl::lookupDependentName( -DeclarationName Name, -llvm::function_ref Filter) { - std::vector Results; - // Lookup in the class. - bool AnyOrdinaryMembers = false; - for (const NamedDecl *ND : lookup(Name)) { -if (isOrdinaryMember(ND)) - AnyOrdinaryMembers = true; -if (Filter(ND)) - Results.push_back(ND); - } - if (AnyOrdinaryMembers) -return Results; - - // Perform lookup into our base classes. - CXXBasePaths Paths; - Paths.setOrigin(this); - if (!lookupInBases( - [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { -return findOrdinaryMemberInDependentClasses(Specifier, Path, Name); - }, - Paths, /*LookupInDependent=*/true)) -return Results; - for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end(); - I != E; ++I) { -if (isOrdinaryMember(*I) && Filter(*I)) - Results.push_back(*I); - } - return Results; -} - void OverridingMethods::add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding) { SmallVectorImpl &SubobjectOverrides ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [clang][NFC] Remove CXXRecordDecl::lookupDependentName() and its helpers (PR #128392)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Nathan Ridge (HighCommander4) Changes This function has been superseded by HeuristicResolver::lookupDependentName(), which implements the same heuristics and more. Porting note for any out-of-tree callers: ``` RD->lookupDependentName(Name, Filter); ``` can be replaced with: ``` HeuristicResolver(RD->getASTContext())->lookupDependentName(Name, Filter); ``` --- Full diff: https://github.com/llvm/llvm-project/pull/128392.diff 2 Files Affected: - (modified) clang/include/clang/AST/DeclCXX.h (-8) - (modified) clang/lib/AST/CXXInheritance.cpp (-53) ``diff diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 266b93a64a390..dbd02ef7f8011 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1720,14 +1720,6 @@ class CXXRecordDecl : public RecordDecl { /// static analysis, or similar. bool hasMemberName(DeclarationName N) const; - /// Performs an imprecise lookup of a dependent name in this class. - /// - /// This function does not follow strict semantic rules and should be used - /// only when lookup rules can be relaxed, e.g. indexing. - std::vector - lookupDependentName(DeclarationName Name, - llvm::function_ref Filter); - /// Renders and displays an inheritance diagram /// for this C++ class and all of its base classes (transitively) using /// GraphViz. diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index ee5775837d535..ab862d57eae89 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -411,59 +411,6 @@ bool CXXRecordDecl::hasMemberName(DeclarationName Name) const { Paths); } -static bool -findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, DeclarationName Name) { - const TemplateSpecializationType *TST = - Specifier->getType()->getAs(); - if (!TST) { -auto *RT = Specifier->getType()->getAs(); -if (!RT) - return false; -return findOrdinaryMember(cast(RT->getDecl()), Path, Name); - } - TemplateName TN = TST->getTemplateName(); - const auto *TD = dyn_cast_or_null(TN.getAsTemplateDecl()); - if (!TD) -return false; - CXXRecordDecl *RD = TD->getTemplatedDecl(); - if (!RD) -return false; - return findOrdinaryMember(RD, Path, Name); -} - -std::vector CXXRecordDecl::lookupDependentName( -DeclarationName Name, -llvm::function_ref Filter) { - std::vector Results; - // Lookup in the class. - bool AnyOrdinaryMembers = false; - for (const NamedDecl *ND : lookup(Name)) { -if (isOrdinaryMember(ND)) - AnyOrdinaryMembers = true; -if (Filter(ND)) - Results.push_back(ND); - } - if (AnyOrdinaryMembers) -return Results; - - // Perform lookup into our base classes. - CXXBasePaths Paths; - Paths.setOrigin(this); - if (!lookupInBases( - [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { -return findOrdinaryMemberInDependentClasses(Specifier, Path, Name); - }, - Paths, /*LookupInDependent=*/true)) -return Results; - for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end(); - I != E; ++I) { -if (isOrdinaryMember(*I) && Filter(*I)) - Results.push_back(*I); - } - return Results; -} - void OverridingMethods::add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding) { SmallVectorImpl &SubobjectOverrides `` https://github.com/llvm/llvm-project/pull/128392 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [clang][NFC] Remove CXXRecordDecl::lookupDependentName() and its helpers (PR #128392)
HighCommander4 wrote: For reference, the callers of `CXXRecordDecl::lookupDependentName()` have been ported over to `HeuristicResolver` over the following series of patches: https://github.com/llvm/llvm-project/pull/124888 https://github.com/llvm/llvm-project/pull/125153 https://github.com/llvm/llvm-project/pull/128106 https://github.com/llvm/llvm-project/pull/128391 https://github.com/llvm/llvm-project/pull/128392 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [flang][draft] update fir.coordinate_of to carry the fields (PR #127231)
razvanlupusoru wrote: Nice work! https://github.com/llvm/llvm-project/pull/127231 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies (PR #127294)
https://github.com/nikic closed https://github.com/llvm/llvm-project/pull/127294 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] RegAllocFast: Fix verifier errors after assigning to reserved registers (PR #128281)
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/128281 >From d93b45487feba452868706b31e6e59e0bb1a5d19 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 12 Dec 2024 10:53:41 +0900 Subject: [PATCH] RegAllocFast: Fix verifier errors after assigning to reserved registers --- llvm/lib/CodeGen/RegAllocFast.cpp | 41 --- ...ut-of-registers-error-all-regs-reserved.ll | 3 +- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 14128dafbe4ee..9f92c11826cce 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -206,6 +206,7 @@ class RegAllocFastImpl { bool Error = false; ///< Could not allocate. explicit LiveReg(Register VirtReg) : VirtReg(VirtReg) {} +explicit LiveReg() {} unsigned getSparseSetIndex() const { return VirtReg.virtRegIndex(); } }; @@ -216,7 +217,7 @@ class RegAllocFastImpl { LiveRegMap LiveVirtRegs; /// Stores assigned virtual registers present in the bundle MI. - DenseMap BundleVirtRegsMap; + DenseMap BundleVirtRegsMap; DenseMap> LiveDbgValueMap; /// List of DBG_VALUE that we encountered without the vreg being assigned @@ -374,7 +375,8 @@ class RegAllocFastImpl { SmallSet &PrologLiveIns) const; void reloadAtBegin(MachineBasicBlock &MBB); - bool setPhysReg(MachineInstr &MI, MachineOperand &MO, MCPhysReg PhysReg); + bool setPhysReg(MachineInstr &MI, MachineOperand &MO, + const LiveReg &Assignment); Register traceCopies(Register VirtReg) const; Register traceCopyChain(Register Reg) const; @@ -1005,7 +1007,8 @@ void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) { MO.setSubReg(0); } MO.setReg(PhysReg); - MO.setIsRenamable(true); + if (!LRI->Error) +MO.setIsRenamable(true); } /// Variation of defineVirtReg() with special handling for livethrough regs @@ -1109,10 +1112,10 @@ bool RegAllocFastImpl::defineVirtReg(MachineInstr &MI, unsigned OpNum, LRI->Reloaded = false; } if (MI.getOpcode() == TargetOpcode::BUNDLE) { -BundleVirtRegsMap[VirtReg] = PhysReg; +BundleVirtRegsMap[VirtReg] = *LRI; } markRegUsedInInstr(PhysReg); - return setPhysReg(MI, MO, PhysReg); + return setPhysReg(MI, MO, *LRI); } /// Allocates a register for a VirtReg use. @@ -1158,10 +1161,10 @@ bool RegAllocFastImpl::useVirtReg(MachineInstr &MI, MachineOperand &MO, LRI->LastUse = &MI; if (MI.getOpcode() == TargetOpcode::BUNDLE) { -BundleVirtRegsMap[VirtReg] = LRI->PhysReg; +BundleVirtRegsMap[VirtReg] = *LRI; } markRegUsedInInstr(LRI->PhysReg); - return setPhysReg(MI, MO, LRI->PhysReg); + return setPhysReg(MI, MO, *LRI); } /// Query a physical register to use as a filler in contexts where the @@ -1215,16 +1218,27 @@ MCPhysReg RegAllocFastImpl::getErrorAssignment(const LiveReg &LR, /// Changes operand OpNum in MI the refer the PhysReg, considering subregs. /// \return true if MI's MachineOperands were re-arranged/invalidated. bool RegAllocFastImpl::setPhysReg(MachineInstr &MI, MachineOperand &MO, - MCPhysReg PhysReg) { + const LiveReg &Assignment) { + MCPhysReg PhysReg = Assignment.PhysReg; + assert(PhysReg && "assignments should always be to a valid physreg"); + + if (LLVM_UNLIKELY(Assignment.Error)) { +// Make sure we don't set renamable in error scenarios, as we may have +// assigned to a reserved register. +if (MO.isUse()) + MO.setIsUndef(true); + } + if (!MO.getSubReg()) { MO.setReg(PhysReg); -MO.setIsRenamable(true); +MO.setIsRenamable(!Assignment.Error); return false; } // Handle subregister index. - MO.setReg(PhysReg ? TRI->getSubReg(PhysReg, MO.getSubReg()) : MCRegister()); - MO.setIsRenamable(true); + MO.setReg(TRI->getSubReg(PhysReg, MO.getSubReg())); + MO.setIsRenamable(!Assignment.Error); + // Note: We leave the subreg number around a little longer in case of defs. // This is so that the register freeing logic in allocateInstruction can still // recognize this as subregister defs. The code there will clear the number. @@ -1706,7 +1720,7 @@ void RegAllocFastImpl::handleDebugValue(MachineInstr &MI) { if (LRI != LiveVirtRegs.end() && LRI->PhysReg) { // Update every use of Reg within MI. for (auto &RegMO : DbgOps) -setPhysReg(MI, *RegMO, LRI->PhysReg); +setPhysReg(MI, *RegMO, *LRI); } else { DanglingDbgValues[Reg].push_back(&MI); } @@ -1729,8 +1743,7 @@ void RegAllocFastImpl::handleBundle(MachineInstr &MI) { if (!Reg.isVirtual() || !shouldAllocateRegister(Reg)) continue; - DenseMap::iterator DI; - DI = BundleVirtRegsMap.find(Reg); + DenseMap::iterator DI = BundleVirtRegsMap.find(Reg); assert(DI != BundleVirtRegsMap
[llvm-branch-commits] [llvm] Reapply "RegAlloc: Fix verifier error after failed allocation (#119690)" (PR #128400)
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/128400 Reapply "RegAlloc: Fix verifier error after failed allocation (#119690)" This reverts commit 0c50054820799578be8f62b6fd2cc3fbc751c01e. Reapply with more fixes to avoid expensive_checks failures. Make sure to call splitSeparateComponents after shrinkToUses, and update the VirtRegMap with the split registers. Also set undef on all physical register aliases to the assigned register. Move physreg handling. Not sure if necessary Remove intervals from regunits. Not sure if necessary >From c8e70d9b94b799014f41264f67c3dd298c0e42e5 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 22 Feb 2025 10:02:04 +0700 Subject: [PATCH 1/3] Reapply "RegAlloc: Fix verifier error after failed allocation (#119690)" This reverts commit 0c50054820799578be8f62b6fd2cc3fbc751c01e. Reapply with more fixes to avoid expensive_checks failures. Make sure to call splitSeparateComponents after shrinkToUses, and update the VirtRegMap with the split registers. Also set undef on all physical register aliases to the assigned register. --- llvm/lib/CodeGen/RegAllocBase.cpp | 55 + llvm/lib/CodeGen/RegAllocBase.h | 6 ++ llvm/lib/CodeGen/RegAllocBasic.cpp| 1 + llvm/lib/CodeGen/RegAllocGreedy.cpp | 1 + .../AMDGPU/illegal-eviction-assert.mir| 6 +- ...-reg-class-snippet-copy-use-after-free.mir | 16 ++--- llvm/test/CodeGen/AMDGPU/issue48473.mir | 2 +- ...ster-killed-error-after-alloc-failure0.mir | 59 +++ ...ister-killed-error-after-alloc-failure1.ll | 30 ++ .../remaining-virtual-register-operands.ll| 2 +- 10 files changed, 165 insertions(+), 13 deletions(-) create mode 100644 llvm/test/CodeGen/AMDGPU/register-killed-error-after-alloc-failure0.mir create mode 100644 llvm/test/CodeGen/AMDGPU/register-killed-error-after-alloc-failure1.ll diff --git a/llvm/lib/CodeGen/RegAllocBase.cpp b/llvm/lib/CodeGen/RegAllocBase.cpp index 50addcbcca065..d17e92da0d2c5 100644 --- a/llvm/lib/CodeGen/RegAllocBase.cpp +++ b/llvm/lib/CodeGen/RegAllocBase.cpp @@ -65,6 +65,7 @@ void RegAllocBase::init(VirtRegMap &vrm, LiveIntervals &lis, Matrix = &mat; MRI->freezeReservedRegs(); RegClassInfo.runOnMachineFunction(vrm.getMachineFunction()); + FailedVRegs.clear(); } // Visit all the live registers. If they are already assigned to a physical @@ -128,6 +129,7 @@ void RegAllocBase::allocatePhysRegs() { // Keep going after reporting the error. VRM->assignVirt2Phys(VirtReg->reg(), AvailablePhysReg); + FailedVRegs.insert(VirtReg->reg()); } else if (AvailablePhysReg) Matrix->assign(*VirtReg, AvailablePhysReg); @@ -161,6 +163,59 @@ void RegAllocBase::postOptimization() { DeadRemats.clear(); } +void RegAllocBase::cleanupFailedVRegs() { + SmallSet JunkRegs; + + for (Register FailedReg : FailedVRegs) { +JunkRegs.insert(FailedReg); + +MCRegister PhysReg = VRM->getPhys(FailedReg); +LiveInterval &FailedInterval = LIS->getInterval(FailedReg); + +// The liveness information for the failed register and anything interfering +// with the physical register we arbitrarily chose is junk and needs to be +// deleted. +for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) { + LiveIntervalUnion::Query &Q = Matrix->query(FailedInterval, *Units); + for (const LiveInterval *InterferingReg : Q.interferingVRegs()) +JunkRegs.insert(InterferingReg->reg()); +} + +// The liveness of the assigned physical register is also now unreliable. +for (MCRegAliasIterator Aliases(PhysReg, TRI, true); Aliases.isValid(); + ++Aliases) { + for (MachineOperand &MO : MRI->reg_operands(*Aliases)) { +if (MO.readsReg()) + MO.setIsUndef(true); + } +} + } + + for (Register JunkReg : JunkRegs) { +MCRegister PhysReg = VRM->getPhys(JunkReg); +// We still should produce valid IR. Kill all the uses and reduce the live +// ranges so that we don't think it's possible to introduce kill flags +// later which will fail the verifier. +for (MachineOperand &MO : MRI->reg_operands(JunkReg)) { + if (MO.readsReg()) +MO.setIsUndef(true); +} + +LiveInterval &JunkLI = LIS->getInterval(JunkReg); +if (LIS->shrinkToUses(&JunkLI)) { + SmallVector SplitLIs; + LIS->splitSeparateComponents(JunkLI, SplitLIs); + + VRM->grow(); + Register Original = VRM->getOriginal(JunkReg); + for (LiveInterval *SplitLI : SplitLIs) { +VRM->setIsSplitFromReg(SplitLI->reg(), Original); +VRM->assignVirt2Phys(SplitLI->reg(), PhysReg); + } +} + } +} + void RegAllocBase::enqueue(const LiveInterval *LI) { const Register Reg = LI->reg(); diff --git a/llvm/lib/CodeGen/RegAllocBase.h b/llvm/lib/CodeGen/RegAllocBase.h index 5bd52da61f2dc..1fdbab694bb0e 100644 --- a/llvm/lib/CodeGen/RegAllocBase.
[llvm-branch-commits] [llvm] Reapply "RegAlloc: Fix verifier error after failed allocation (#119690)" (PR #128400)
llvmbot wrote: @llvm/pr-subscribers-backend-amdgpu Author: Matt Arsenault (arsenm) Changes Reapply "RegAlloc: Fix verifier error after failed allocation (#119690)" This reverts commit 0c50054820799578be8f62b6fd2cc3fbc751c01e. Reapply with more fixes to avoid expensive_checks failures. Make sure to call splitSeparateComponents after shrinkToUses, and update the VirtRegMap with the split registers. Also set undef on all physical register aliases to the assigned register. Move physreg handling. Not sure if necessary Remove intervals from regunits. Not sure if necessary --- Full diff: https://github.com/llvm/llvm-project/pull/128400.diff 10 Files Affected: - (modified) llvm/lib/CodeGen/RegAllocBase.cpp (+56) - (modified) llvm/lib/CodeGen/RegAllocBase.h (+6) - (modified) llvm/lib/CodeGen/RegAllocBasic.cpp (+1) - (modified) llvm/lib/CodeGen/RegAllocGreedy.cpp (+1) - (modified) llvm/test/CodeGen/AMDGPU/illegal-eviction-assert.mir (+3-3) - (modified) llvm/test/CodeGen/AMDGPU/inflated-reg-class-snippet-copy-use-after-free.mir (+8-8) - (modified) llvm/test/CodeGen/AMDGPU/issue48473.mir (+1-1) - (added) llvm/test/CodeGen/AMDGPU/register-killed-error-after-alloc-failure0.mir (+59) - (added) llvm/test/CodeGen/AMDGPU/register-killed-error-after-alloc-failure1.ll (+30) - (modified) llvm/test/CodeGen/AMDGPU/remaining-virtual-register-operands.ll (+1-1) ``diff diff --git a/llvm/lib/CodeGen/RegAllocBase.cpp b/llvm/lib/CodeGen/RegAllocBase.cpp index 50addcbcca065..d66d396a15018 100644 --- a/llvm/lib/CodeGen/RegAllocBase.cpp +++ b/llvm/lib/CodeGen/RegAllocBase.cpp @@ -65,6 +65,7 @@ void RegAllocBase::init(VirtRegMap &vrm, LiveIntervals &lis, Matrix = &mat; MRI->freezeReservedRegs(); RegClassInfo.runOnMachineFunction(vrm.getMachineFunction()); + FailedVRegs.clear(); } // Visit all the live registers. If they are already assigned to a physical @@ -128,6 +129,7 @@ void RegAllocBase::allocatePhysRegs() { // Keep going after reporting the error. VRM->assignVirt2Phys(VirtReg->reg(), AvailablePhysReg); + FailedVRegs.insert(VirtReg->reg()); } else if (AvailablePhysReg) Matrix->assign(*VirtReg, AvailablePhysReg); @@ -161,6 +163,60 @@ void RegAllocBase::postOptimization() { DeadRemats.clear(); } +void RegAllocBase::cleanupFailedVRegs() { + SmallSet JunkRegs; + + for (Register FailedReg : FailedVRegs) { +JunkRegs.insert(FailedReg); + +MCRegister PhysReg = VRM->getPhys(FailedReg); +LiveInterval &FailedInterval = LIS->getInterval(FailedReg); + +// The liveness information for the failed register and anything interfering +// with the physical register we arbitrarily chose is junk and needs to be +// deleted. +for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) { + LiveIntervalUnion::Query &Q = Matrix->query(FailedInterval, *Units); + for (const LiveInterval *InterferingReg : Q.interferingVRegs()) +JunkRegs.insert(InterferingReg->reg()); + LIS->removeRegUnit(*Units); +} + } + + for (Register JunkReg : JunkRegs) { +MCRegister PhysReg = VRM->getPhys(JunkReg); +// We still should produce valid IR. Kill all the uses and reduce the live +// ranges so that we don't think it's possible to introduce kill flags +// later which will fail the verifier. +for (MachineOperand &MO : MRI->reg_operands(JunkReg)) { + if (MO.readsReg()) +MO.setIsUndef(true); +} + +// The liveness of the assigned physical register is also now unreliable. +for (MCRegAliasIterator Aliases(PhysReg, TRI, true); Aliases.isValid(); + ++Aliases) { + for (MachineOperand &MO : MRI->reg_operands(*Aliases)) { +if (MO.readsReg()) + MO.setIsUndef(true); + } +} + +LiveInterval &JunkLI = LIS->getInterval(JunkReg); +if (LIS->shrinkToUses(&JunkLI)) { + SmallVector SplitLIs; + LIS->splitSeparateComponents(JunkLI, SplitLIs); + + VRM->grow(); + Register Original = VRM->getOriginal(JunkReg); + for (LiveInterval *SplitLI : SplitLIs) { +VRM->setIsSplitFromReg(SplitLI->reg(), Original); +VRM->assignVirt2Phys(SplitLI->reg(), PhysReg); + } +} + } +} + void RegAllocBase::enqueue(const LiveInterval *LI) { const Register Reg = LI->reg(); diff --git a/llvm/lib/CodeGen/RegAllocBase.h b/llvm/lib/CodeGen/RegAllocBase.h index 5bd52da61f2dc..1fdbab694bb0e 100644 --- a/llvm/lib/CodeGen/RegAllocBase.h +++ b/llvm/lib/CodeGen/RegAllocBase.h @@ -37,6 +37,7 @@ #define LLVM_LIB_CODEGEN_REGALLOCBASE_H #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegAllocCommon.h" #include "llvm/CodeGen/RegisterClassInfo.h" @@ -81,6 +82,7 @@ class RegAllocBase { /// always available for the remat of all the siblings of the original reg. SmallPtrSet DeadRemats; + SmallSet FailedVRegs; RegAllocBase(const RegAlloc
[llvm-branch-commits] [llvm] Reapply "RegAlloc: Fix verifier error after failed allocation (#119690)" (PR #128400)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/128400?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#128400** https://app.graphite.dev/github/pr/llvm/llvm-project/128400?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/128400?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#128281** https://app.graphite.dev/github/pr/llvm/llvm-project/128281?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#128280** https://app.graphite.dev/github/pr/llvm/llvm-project/128280?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/128400 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] Reapply "RegAlloc: Fix verifier error after failed allocation (#119690)" (PR #128400)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/128400 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] Reapply "RegAlloc: Fix verifier error after failed allocation (#119690)" (PR #128400)
github-actions[bot] wrote: :warning: undef deprecator found issues in your code. :warning: You can test this locally with the following command: ``bash git diff -U0 --pickaxe-regex -S '([^a-zA-Z0-9#_-]undef[^a-zA-Z0-9_-]|UndefValue::get)' d93b45487feba452868706b31e6e59e0bb1a5d19 a8b8cafcb1c5e252e23a1626a44eed4e4ef89316 llvm/test/CodeGen/AMDGPU/register-killed-error-after-alloc-failure1.ll llvm/lib/CodeGen/RegAllocBase.cpp llvm/lib/CodeGen/RegAllocBase.h llvm/lib/CodeGen/RegAllocBasic.cpp llvm/lib/CodeGen/RegAllocGreedy.cpp llvm/test/CodeGen/AMDGPU/remaining-virtual-register-operands.ll `` The following files introduce new uses of undef: - llvm/test/CodeGen/AMDGPU/register-killed-error-after-alloc-failure1.ll [Undef](https://llvm.org/docs/LangRef.html#undefined-values) is now deprecated and should only be used in the rare cases where no replacement is possible. For example, a load of uninitialized memory yields `undef`. You should use `poison` values for placeholders instead. In tests, avoid using `undef` and having tests that trigger undefined behavior. If you need an operand with some unimportant value, you can add a new argument to the function and use that instead. For example, this is considered a bad practice: ```llvm define void @fn() { ... br i1 undef, ... } ``` Please use the following instead: ```llvm define void @fn(i1 %cond) { ... br i1 %cond, ... } ``` Please refer to the [Undefined Behavior Manual](https://llvm.org/docs/UndefinedBehavior.html) for more information. https://github.com/llvm/llvm-project/pull/128400 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: Reland "[LV]: Teach LV to recursively (de)interleave." (#125094) (PR #128389)
llvmbot wrote: @fhahn What do you think about merging this PR to the release branch? https://github.com/llvm/llvm-project/pull/128389 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: Reland "[LV]: Teach LV to recursively (de)interleave." (#125094) (PR #128389)
https://github.com/llvmbot milestoned https://github.com/llvm/llvm-project/pull/128389 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: Reland "[LV]: Teach LV to recursively (de)interleave." (#125094) (PR #128389)
llvmbot wrote: @llvm/pr-subscribers-vectorizers Author: None (llvmbot) Changes Backport e9a20f77ee2117b4a6eb40826b7280e29ad29e1e Requested by: @hassnaaHamdi --- Patch is 194.18 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/128389.diff 6 Files Affected: - (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+7-7) - (modified) llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp (+56-23) - (modified) llvm/test/Transforms/LoopVectorize/AArch64/sve-interleaved-accesses.ll (+259-1) - (modified) llvm/test/Transforms/LoopVectorize/AArch64/sve-interleaved-masked-accesses.ll (+252) - (modified) llvm/test/Transforms/LoopVectorize/RISCV/interleaved-accesses.ll (+678-640) - (added) llvm/test/Transforms/PhaseOrdering/AArch64/sve-interleave-vectorization.ll (+135) ``diff diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 0ceeec48487f6..2ac58feaf39bb 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -3390,10 +3390,10 @@ bool LoopVectorizationCostModel::interleavedAccessCanBeWidened( if (hasIrregularType(ScalarTy, DL)) return false; - // We currently only know how to emit interleave/deinterleave with - // Factor=2 for scalable vectors. This is purely an implementation - // limit. - if (VF.isScalable() && InterleaveFactor != 2) + // For scalable vectors, the only interleave factor currently supported + // must be power of 2 since we require the (de)interleave2 intrinsics + // instead of shufflevectors. + if (VF.isScalable() && !isPowerOf2_32(InterleaveFactor)) return false; // If the group involves a non-integral pointer, we may not be able to @@ -9259,9 +9259,9 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { CM.getWideningDecision(IG->getInsertPos(), VF) == LoopVectorizationCostModel::CM_Interleave); // For scalable vectors, the only interleave factor currently supported - // is 2 since we require the (de)interleave2 intrinsics instead of - // shufflevectors. - assert((!Result || !VF.isScalable() || IG->getFactor() == 2) && + // must be power of 2 since we require the (de)interleave2 intrinsics + // instead of shufflevectors. + assert((!Result || !VF.isScalable() || isPowerOf2_32(IG->getFactor())) && "Unsupported interleave factor for scalable vectors"); return Result; }; diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index 97be2da24fc37..4f13116382796 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -2892,10 +2892,21 @@ static Value *interleaveVectors(IRBuilderBase &Builder, ArrayRef Vals, // Scalable vectors cannot use arbitrary shufflevectors (only splats), so // must use intrinsics to interleave. if (VecTy->isScalableTy()) { -VectorType *WideVecTy = VectorType::getDoubleElementsVectorType(VecTy); -return Builder.CreateIntrinsic(WideVecTy, Intrinsic::vector_interleave2, - Vals, - /*FMFSource=*/nullptr, Name); +assert(isPowerOf2_32(Factor) && "Unsupported interleave factor for " +"scalable vectors, must be power of 2"); +SmallVector InterleavingValues(Vals); +// When interleaving, the number of values will be shrunk until we have the +// single final interleaved value. +auto *InterleaveTy = cast(InterleavingValues[0]->getType()); +for (unsigned Midpoint = Factor / 2; Midpoint > 0; Midpoint /= 2) { + InterleaveTy = VectorType::getDoubleElementsVectorType(InterleaveTy); + for (unsigned I = 0; I < Midpoint; ++I) +InterleavingValues[I] = Builder.CreateIntrinsic( +InterleaveTy, Intrinsic::vector_interleave2, +{InterleavingValues[I], InterleavingValues[Midpoint + I]}, +/*FMFSource=*/nullptr, Name); +} +return InterleavingValues[0]; } // Fixed length. Start by concatenating all vectors into a wide vector. @@ -2981,15 +2992,11 @@ void VPInterleaveRecipe::execute(VPTransformState &State) { &InterleaveFactor](Value *MaskForGaps) -> Value * { if (State.VF.isScalable()) { assert(!MaskForGaps && "Interleaved groups with gaps are not supported."); - assert(InterleaveFactor == 2 && + assert(isPowerOf2_32(InterleaveFactor) && "Unsupported deinterleave factor for scalable vectors"); auto *ResBlockInMask = State.get(BlockInMask); - SmallVector Ops = {ResBlockInMask, ResBlockInMask}; - auto *MaskTy = VectorType::get(State.Builder.getInt1Ty(), - State.VF.getKnownMinValue() * 2, true); - return State
[llvm-branch-commits] [llvm] release/20.x: Reland "[LV]: Teach LV to recursively (de)interleave." (#125094) (PR #128389)
llvmbot wrote: @llvm/pr-subscribers-llvm-transforms Author: None (llvmbot) Changes Backport e9a20f77ee2117b4a6eb40826b7280e29ad29e1e Requested by: @hassnaaHamdi --- Patch is 194.18 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/128389.diff 6 Files Affected: - (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+7-7) - (modified) llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp (+56-23) - (modified) llvm/test/Transforms/LoopVectorize/AArch64/sve-interleaved-accesses.ll (+259-1) - (modified) llvm/test/Transforms/LoopVectorize/AArch64/sve-interleaved-masked-accesses.ll (+252) - (modified) llvm/test/Transforms/LoopVectorize/RISCV/interleaved-accesses.ll (+678-640) - (added) llvm/test/Transforms/PhaseOrdering/AArch64/sve-interleave-vectorization.ll (+135) ``diff diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 0ceeec48487f6..2ac58feaf39bb 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -3390,10 +3390,10 @@ bool LoopVectorizationCostModel::interleavedAccessCanBeWidened( if (hasIrregularType(ScalarTy, DL)) return false; - // We currently only know how to emit interleave/deinterleave with - // Factor=2 for scalable vectors. This is purely an implementation - // limit. - if (VF.isScalable() && InterleaveFactor != 2) + // For scalable vectors, the only interleave factor currently supported + // must be power of 2 since we require the (de)interleave2 intrinsics + // instead of shufflevectors. + if (VF.isScalable() && !isPowerOf2_32(InterleaveFactor)) return false; // If the group involves a non-integral pointer, we may not be able to @@ -9259,9 +9259,9 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { CM.getWideningDecision(IG->getInsertPos(), VF) == LoopVectorizationCostModel::CM_Interleave); // For scalable vectors, the only interleave factor currently supported - // is 2 since we require the (de)interleave2 intrinsics instead of - // shufflevectors. - assert((!Result || !VF.isScalable() || IG->getFactor() == 2) && + // must be power of 2 since we require the (de)interleave2 intrinsics + // instead of shufflevectors. + assert((!Result || !VF.isScalable() || isPowerOf2_32(IG->getFactor())) && "Unsupported interleave factor for scalable vectors"); return Result; }; diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index 97be2da24fc37..4f13116382796 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -2892,10 +2892,21 @@ static Value *interleaveVectors(IRBuilderBase &Builder, ArrayRef Vals, // Scalable vectors cannot use arbitrary shufflevectors (only splats), so // must use intrinsics to interleave. if (VecTy->isScalableTy()) { -VectorType *WideVecTy = VectorType::getDoubleElementsVectorType(VecTy); -return Builder.CreateIntrinsic(WideVecTy, Intrinsic::vector_interleave2, - Vals, - /*FMFSource=*/nullptr, Name); +assert(isPowerOf2_32(Factor) && "Unsupported interleave factor for " +"scalable vectors, must be power of 2"); +SmallVector InterleavingValues(Vals); +// When interleaving, the number of values will be shrunk until we have the +// single final interleaved value. +auto *InterleaveTy = cast(InterleavingValues[0]->getType()); +for (unsigned Midpoint = Factor / 2; Midpoint > 0; Midpoint /= 2) { + InterleaveTy = VectorType::getDoubleElementsVectorType(InterleaveTy); + for (unsigned I = 0; I < Midpoint; ++I) +InterleavingValues[I] = Builder.CreateIntrinsic( +InterleaveTy, Intrinsic::vector_interleave2, +{InterleavingValues[I], InterleavingValues[Midpoint + I]}, +/*FMFSource=*/nullptr, Name); +} +return InterleavingValues[0]; } // Fixed length. Start by concatenating all vectors into a wide vector. @@ -2981,15 +2992,11 @@ void VPInterleaveRecipe::execute(VPTransformState &State) { &InterleaveFactor](Value *MaskForGaps) -> Value * { if (State.VF.isScalable()) { assert(!MaskForGaps && "Interleaved groups with gaps are not supported."); - assert(InterleaveFactor == 2 && + assert(isPowerOf2_32(InterleaveFactor) && "Unsupported deinterleave factor for scalable vectors"); auto *ResBlockInMask = State.get(BlockInMask); - SmallVector Ops = {ResBlockInMask, ResBlockInMask}; - auto *MaskTy = VectorType::get(State.Builder.getInt1Ty(), - State.VF.getKnownMinValue() * 2, true); - return S
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies (PR #127294)
Zentrik wrote: @alexey-bataev Am I correct in thinking that the `Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll` test just needs to be updated to reflect that vectorization fails. It looks like the test is there to make sure there's no crash when compiling. https://github.com/llvm/llvm-project/pull/127294 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies (PR #127294)
alexey-bataev wrote: Yes, updating should be enough https://github.com/llvm/llvm-project/pull/127294 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies (PR #127294)
nikic wrote: Closing in favor of https://github.com/llvm/llvm-project/pull/128371. https://github.com/llvm/llvm-project/pull/127294 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies: Backport Attempt 3 (PR #128371)
https://github.com/alexey-bataev approved this pull request. LG https://github.com/llvm/llvm-project/pull/128371 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies: Backport Attempt 3 (PR #128371)
https://github.com/nikic milestoned https://github.com/llvm/llvm-project/pull/128371 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies: Backport Attempt 3 (PR #128371)
https://github.com/Zentrik updated https://github.com/llvm/llvm-project/pull/128371 >From 976a97097c645a4d861e4a36c142b30c33a5e575 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 13 Feb 2025 14:19:51 -0800 Subject: [PATCH 1/2] [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies When checking for dependecies for gather nodes with users with the same last instruction, cannot rely on the index order, if there is (even potential!) cycle in the graph, which may cause order not work correctly and cause compiler crash. Fixes #127128 (cherry picked from commit ac217ee389d63124432e5e6890851a678f7a676b) --- .../Transforms/Vectorize/SLPVectorizer.cpp| 10 +++- .../X86/delayed-gather-emission.ll| 2 +- .../X86/matching-gather-nodes-phi-users.ll| 2 +- .../SLPVectorizer/X86/phi-node-with-cycle.ll | 59 +++ 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 19963e780ebd3..7b20eda550095 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -13181,8 +13181,16 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( continue; // If the user instruction is used for some reason in different // vectorized nodes - make it depend on index. +// If any vector node is PHI node, this dependency might not work +// because of cycle dependencies, so disable it. if (TEUseEI.UserTE != UseEI.UserTE && -TEUseEI.UserTE->Idx < UseEI.UserTE->Idx) +(TEUseEI.UserTE->Idx < UseEI.UserTE->Idx || + any_of( + VectorizableTree, + [](const std::unique_ptr &TE) { + return TE->State == TreeEntry::Vectorize && + TE->getOpcode() == Instruction::PHI; + }))) continue; } diff --git a/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll b/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll index 5562291dbb6be..bf3f0c4df74e4 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll @@ -31,7 +31,7 @@ define void @test() { ; CHECK-NEXT:[[TOBOOL:%.*]] = fcmp une float [[I2]], 0.00e+00 ; CHECK-NEXT:[[TMP8:%.*]] = shufflevector <2 x float> [[TMP5]], <2 x float> poison, <2 x i32> ; CHECK-NEXT:[[TMP9]] = insertelement <2 x float> [[TMP8]], float [[I2]], i32 0 -; CHECK-NEXT:[[TMP10]] = shufflevector <2 x float> [[TMP9]], <2 x float> [[TMP2]], <2 x i32> +; CHECK-NEXT:[[TMP10]] = insertelement <2 x float> [[TMP2]], float [[I2]], i32 0 ; CHECK-NEXT:br i1 [[TOBOOL]], label [[BB1]], label [[BB2]] ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll b/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll index 166c819098c8c..d649465c9ff12 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll @@ -8,7 +8,7 @@ ; YAML: Function:test ; YAML: Args: ; YAML: - String: 'Stores SLP vectorized with cost ' -; YAML: - Cost:'-6' +; YAML: - Cost:'-3' ; YAML: - String: ' and with tree size ' ; YAML: - TreeSize:'14' ; YAML: ... diff --git a/llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll new file mode 100644 index 0..22e7e6a8e6624 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll @@ -0,0 +1,59 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -mcpu=haswell < %s | FileCheck %s + +define void @test(float %0) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: float [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT:[[TMP2:%.*]] = insertelement <2 x float> , float [[TMP0]], i32 1 +; CHECK-NEXT:[[TMP3:%.*]] = fdiv <2 x float> [[TMP2]], zeroinitializer +; CHECK-NEXT:[[TMP4:%.*]] = insertelement <2 x float> , float [[TMP0]], i32 0 +; CHECK-NEXT:[[TMP5:%.*]] = fdiv <2 x float> [[TMP4]], zeroinitializer +; CHECK-NEXT:br label %[[BB6:.*]] +; CHECK: [[BB6]]: +; CHECK-NEXT:[[TMP7:%.*]] = fmul <2 x float> [[TMP5]], zeroinitializer +; CHECK-NEXT:[[TMP8:%.*]] = fsub <2 x float> zeroinitializer, [[TMP7]] +; CHECK-NEXT:br label %[[BB10:.*]] +; CHECK: [[BB9:.*]]: +; CHECK-NEXT:br label %[[BB10]] +; CHECK: [[BB10]]: +; CHECK-NEXT:[[TMP11:%.*]] = phi <2 x float> [ [[TMP8]], %[[BB
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies: Backport Attempt 3 (PR #128371)
llvmbot wrote: @llvm/pr-subscribers-vectorizers Author: None (Zentrik) Changes Backport https://github.com/llvm/llvm-project/commit/ac217ee389d63124432e5e6890851a678f7a676b This fixes https://github.com/llvm/llvm-project/pull/127294 by updating the test at `llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll` --- Full diff: https://github.com/llvm/llvm-project/pull/128371.diff 5 Files Affected: - (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+9-1) - (modified) llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll (+1-1) - (modified) llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll (+1-1) - (modified) llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll (+7-6) - (added) llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll (+59) ``diff diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 19963e780ebd3..7b20eda550095 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -13181,8 +13181,16 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( continue; // If the user instruction is used for some reason in different // vectorized nodes - make it depend on index. +// If any vector node is PHI node, this dependency might not work +// because of cycle dependencies, so disable it. if (TEUseEI.UserTE != UseEI.UserTE && -TEUseEI.UserTE->Idx < UseEI.UserTE->Idx) +(TEUseEI.UserTE->Idx < UseEI.UserTE->Idx || + any_of( + VectorizableTree, + [](const std::unique_ptr &TE) { + return TE->State == TreeEntry::Vectorize && + TE->getOpcode() == Instruction::PHI; + }))) continue; } diff --git a/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll b/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll index 5562291dbb6be..bf3f0c4df74e4 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll @@ -31,7 +31,7 @@ define void @test() { ; CHECK-NEXT:[[TOBOOL:%.*]] = fcmp une float [[I2]], 0.00e+00 ; CHECK-NEXT:[[TMP8:%.*]] = shufflevector <2 x float> [[TMP5]], <2 x float> poison, <2 x i32> ; CHECK-NEXT:[[TMP9]] = insertelement <2 x float> [[TMP8]], float [[I2]], i32 0 -; CHECK-NEXT:[[TMP10]] = shufflevector <2 x float> [[TMP9]], <2 x float> [[TMP2]], <2 x i32> +; CHECK-NEXT:[[TMP10]] = insertelement <2 x float> [[TMP2]], float [[I2]], i32 0 ; CHECK-NEXT:br i1 [[TOBOOL]], label [[BB1]], label [[BB2]] ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll b/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll index 166c819098c8c..d649465c9ff12 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll @@ -8,7 +8,7 @@ ; YAML: Function:test ; YAML: Args: ; YAML: - String: 'Stores SLP vectorized with cost ' -; YAML: - Cost:'-6' +; YAML: - Cost:'-3' ; YAML: - String: ' and with tree size ' ; YAML: - TreeSize:'14' ; YAML: ... diff --git a/llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll b/llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll index 1053e0fc10669..c4a49242a5583 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll @@ -7,16 +7,17 @@ define void @test() { ; CHECK-NEXT: [[BB:.*]]: ; CHECK-NEXT:br label %[[BB1:.*]] ; CHECK: [[BB1]]: -; CHECK-NEXT:[[TMP0:%.*]] = phi <2 x i32> [ zeroinitializer, %[[BB]] ], [ [[TMP4:%.*]], %[[BB4:.*]] ] -; CHECK-NEXT:[[TMP1:%.*]] = or <2 x i32> [[TMP0]], zeroinitializer +; CHECK-NEXT:[[PHI:%.*]] = phi i32 [ 0, %[[BB]] ], [ [[ADD6:%.*]], %[[BB4:.*]] ] +; CHECK-NEXT:[[PHI2:%.*]] = phi i32 [ 0, %[[BB]] ], [ 0, %[[BB4]] ] +; CHECK-NEXT:[[OR:%.*]] = or i32 [[PHI2]], 0 +; CHECK-NEXT:[[OR3:%.*]] = or i32 [[PHI]], 0 ; CHECK-NEXT:br i1 false, label %[[BB7:.*]], label %[[BB4]] ; CHECK: [[BB4]]: -; CHECK-NEXT:[[TMP2:%.*]] = shufflevector <2 x i32> [[TMP0]], <2 x i32> , <2 x i32> -; CHECK-NEXT:[[TMP3:%.*]] = add <2 x i32> zeroinitializer, [[TMP2]] -; CHECK-NEXT:[[TMP4]] = add <2 x i32> zeroinitializer, [[TMP2]] +; CHECK-NEXT:[[ADD6]] = add i32 [[PHI]], 0 ; CHECK-NEXT:br i1 false, label %[[BB7]], label %[[BB1]] ; CHECK: [[BB7]]: -; CHECK-NEXT:[[TMP5:%.*]] = phi <2 x i32> [ [[TMP1]], %[[BB1]] ], [ [[TMP3]], %[[BB4]] ] +; CHECK-NEXT:[[PHI8:%.*]] = phi
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies (PR #128371)
https://github.com/Zentrik created https://github.com/llvm/llvm-project/pull/128371 Backport https://github.com/llvm/llvm-project/commit/ac217ee389d63124432e5e6890851a678f7a676b This fixes https://github.com/llvm/llvm-project/pull/127294 by updating the test at `llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll` >From a426b578f8c51dc1f645a901dc6eedb33462fa22 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 13 Feb 2025 14:19:51 -0800 Subject: [PATCH 1/2] [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies When checking for dependecies for gather nodes with users with the same last instruction, cannot rely on the index order, if there is (even potential!) cycle in the graph, which may cause order not work correctly and cause compiler crash. Fixes #127128 (cherry picked from commit ac217ee389d63124432e5e6890851a678f7a676b) --- .../Transforms/Vectorize/SLPVectorizer.cpp| 10 +++- .../X86/delayed-gather-emission.ll| 2 +- .../X86/matching-gather-nodes-phi-users.ll| 2 +- .../SLPVectorizer/X86/phi-node-with-cycle.ll | 59 +++ 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 19963e780ebd3..7b20eda550095 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -13181,8 +13181,16 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( continue; // If the user instruction is used for some reason in different // vectorized nodes - make it depend on index. +// If any vector node is PHI node, this dependency might not work +// because of cycle dependencies, so disable it. if (TEUseEI.UserTE != UseEI.UserTE && -TEUseEI.UserTE->Idx < UseEI.UserTE->Idx) +(TEUseEI.UserTE->Idx < UseEI.UserTE->Idx || + any_of( + VectorizableTree, + [](const std::unique_ptr &TE) { + return TE->State == TreeEntry::Vectorize && + TE->getOpcode() == Instruction::PHI; + }))) continue; } diff --git a/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll b/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll index 5562291dbb6be..bf3f0c4df74e4 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll @@ -31,7 +31,7 @@ define void @test() { ; CHECK-NEXT:[[TOBOOL:%.*]] = fcmp une float [[I2]], 0.00e+00 ; CHECK-NEXT:[[TMP8:%.*]] = shufflevector <2 x float> [[TMP5]], <2 x float> poison, <2 x i32> ; CHECK-NEXT:[[TMP9]] = insertelement <2 x float> [[TMP8]], float [[I2]], i32 0 -; CHECK-NEXT:[[TMP10]] = shufflevector <2 x float> [[TMP9]], <2 x float> [[TMP2]], <2 x i32> +; CHECK-NEXT:[[TMP10]] = insertelement <2 x float> [[TMP2]], float [[I2]], i32 0 ; CHECK-NEXT:br i1 [[TOBOOL]], label [[BB1]], label [[BB2]] ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll b/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll index 166c819098c8c..d649465c9ff12 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll @@ -8,7 +8,7 @@ ; YAML: Function:test ; YAML: Args: ; YAML: - String: 'Stores SLP vectorized with cost ' -; YAML: - Cost:'-6' +; YAML: - Cost:'-3' ; YAML: - String: ' and with tree size ' ; YAML: - TreeSize:'14' ; YAML: ... diff --git a/llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll new file mode 100644 index 0..22e7e6a8e6624 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll @@ -0,0 +1,59 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -mcpu=haswell < %s | FileCheck %s + +define void @test(float %0) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: float [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT:[[TMP2:%.*]] = insertelement <2 x float> , float [[TMP0]], i32 1 +; CHECK-NEXT:[[TMP3:%.*]] = fdiv <2 x float> [[TMP2]], zeroinitializer +; CHECK-NEXT:[[TMP4:%.*]] = insertelement <2 x float> , float [[TMP0]], i32 0 +; CHECK-NEXT:[[TMP5:%.*]] = fdiv <2 x float> [[TMP4]], zeroinitializer +; CHECK-NEXT:br label %[[BB6:.*]] +; CHECK: [[BB6]]: +; CHECK-NEXT:[[TMP7:%.*]] = fmul <2 x float> [[TMP5]], zeroinitializer +; CHECK-NEXT:[[T
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies: Backport Attempt 3 (PR #128371)
llvmbot wrote: @llvm/pr-subscribers-llvm-transforms Author: None (Zentrik) Changes Backport https://github.com/llvm/llvm-project/commit/ac217ee389d63124432e5e6890851a678f7a676b This fixes https://github.com/llvm/llvm-project/pull/127294 by updating the test at `llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll` --- Full diff: https://github.com/llvm/llvm-project/pull/128371.diff 5 Files Affected: - (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+9-1) - (modified) llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll (+1-1) - (modified) llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll (+1-1) - (modified) llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll (+7-6) - (added) llvm/test/Transforms/SLPVectorizer/X86/phi-node-with-cycle.ll (+59) ``diff diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 19963e780ebd3..7b20eda550095 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -13181,8 +13181,16 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( continue; // If the user instruction is used for some reason in different // vectorized nodes - make it depend on index. +// If any vector node is PHI node, this dependency might not work +// because of cycle dependencies, so disable it. if (TEUseEI.UserTE != UseEI.UserTE && -TEUseEI.UserTE->Idx < UseEI.UserTE->Idx) +(TEUseEI.UserTE->Idx < UseEI.UserTE->Idx || + any_of( + VectorizableTree, + [](const std::unique_ptr &TE) { + return TE->State == TreeEntry::Vectorize && + TE->getOpcode() == Instruction::PHI; + }))) continue; } diff --git a/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll b/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll index 5562291dbb6be..bf3f0c4df74e4 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/delayed-gather-emission.ll @@ -31,7 +31,7 @@ define void @test() { ; CHECK-NEXT:[[TOBOOL:%.*]] = fcmp une float [[I2]], 0.00e+00 ; CHECK-NEXT:[[TMP8:%.*]] = shufflevector <2 x float> [[TMP5]], <2 x float> poison, <2 x i32> ; CHECK-NEXT:[[TMP9]] = insertelement <2 x float> [[TMP8]], float [[I2]], i32 0 -; CHECK-NEXT:[[TMP10]] = shufflevector <2 x float> [[TMP9]], <2 x float> [[TMP2]], <2 x i32> +; CHECK-NEXT:[[TMP10]] = insertelement <2 x float> [[TMP2]], float [[I2]], i32 0 ; CHECK-NEXT:br i1 [[TOBOOL]], label [[BB1]], label [[BB2]] ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll b/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll index 166c819098c8c..d649465c9ff12 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/matching-gather-nodes-phi-users.ll @@ -8,7 +8,7 @@ ; YAML: Function:test ; YAML: Args: ; YAML: - String: 'Stores SLP vectorized with cost ' -; YAML: - Cost:'-6' +; YAML: - Cost:'-3' ; YAML: - String: ' and with tree size ' ; YAML: - TreeSize:'14' ; YAML: ... diff --git a/llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll b/llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll index 1053e0fc10669..c4a49242a5583 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/perfect-matched-reused-bv.ll @@ -7,16 +7,17 @@ define void @test() { ; CHECK-NEXT: [[BB:.*]]: ; CHECK-NEXT:br label %[[BB1:.*]] ; CHECK: [[BB1]]: -; CHECK-NEXT:[[TMP0:%.*]] = phi <2 x i32> [ zeroinitializer, %[[BB]] ], [ [[TMP4:%.*]], %[[BB4:.*]] ] -; CHECK-NEXT:[[TMP1:%.*]] = or <2 x i32> [[TMP0]], zeroinitializer +; CHECK-NEXT:[[PHI:%.*]] = phi i32 [ 0, %[[BB]] ], [ [[ADD6:%.*]], %[[BB4:.*]] ] +; CHECK-NEXT:[[PHI2:%.*]] = phi i32 [ 0, %[[BB]] ], [ 0, %[[BB4]] ] +; CHECK-NEXT:[[OR:%.*]] = or i32 [[PHI2]], 0 +; CHECK-NEXT:[[OR3:%.*]] = or i32 [[PHI]], 0 ; CHECK-NEXT:br i1 false, label %[[BB7:.*]], label %[[BB4]] ; CHECK: [[BB4]]: -; CHECK-NEXT:[[TMP2:%.*]] = shufflevector <2 x i32> [[TMP0]], <2 x i32> , <2 x i32> -; CHECK-NEXT:[[TMP3:%.*]] = add <2 x i32> zeroinitializer, [[TMP2]] -; CHECK-NEXT:[[TMP4]] = add <2 x i32> zeroinitializer, [[TMP2]] +; CHECK-NEXT:[[ADD6]] = add i32 [[PHI]], 0 ; CHECK-NEXT:br i1 false, label %[[BB7]], label %[[BB1]] ; CHECK: [[BB7]]: -; CHECK-NEXT:[[TMP5:%.*]] = phi <2 x i32> [ [[TMP1]], %[[BB1]] ], [ [[TMP3]], %[[BB4]] ] +; CHECK-NEXT:[[PHI8:%.*]] =
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies: Backport Attempt 3 (PR #128371)
https://github.com/Zentrik edited https://github.com/llvm/llvm-project/pull/128371 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [SLP] Check for PHI nodes (potentially cycles!) when checking dependencies: Backport Attempt 3 (PR #128371)
Zentrik wrote: I suspect I don't have permissions to add this to the milestone. https://github.com/llvm/llvm-project/pull/128371 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [DAGCombiner] visitFREEZE: Early exit when N is deleted (#128161) (PR #128283)
https://github.com/RKSimon approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/128283 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] RegAllocFast: Fix verifier errors after assigning to reserved registers (PR #128281)
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/128281 >From 8d9b1ee1f1e67bd5f946a9e88e14fc7e0a34248f Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 12 Dec 2024 10:53:41 +0900 Subject: [PATCH] RegAllocFast: Fix verifier errors after assigning to reserved registers --- llvm/lib/CodeGen/RegAllocFast.cpp | 41 --- ...ut-of-registers-error-all-regs-reserved.ll | 3 +- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 14128dafbe4ee..9f92c11826cce 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -206,6 +206,7 @@ class RegAllocFastImpl { bool Error = false; ///< Could not allocate. explicit LiveReg(Register VirtReg) : VirtReg(VirtReg) {} +explicit LiveReg() {} unsigned getSparseSetIndex() const { return VirtReg.virtRegIndex(); } }; @@ -216,7 +217,7 @@ class RegAllocFastImpl { LiveRegMap LiveVirtRegs; /// Stores assigned virtual registers present in the bundle MI. - DenseMap BundleVirtRegsMap; + DenseMap BundleVirtRegsMap; DenseMap> LiveDbgValueMap; /// List of DBG_VALUE that we encountered without the vreg being assigned @@ -374,7 +375,8 @@ class RegAllocFastImpl { SmallSet &PrologLiveIns) const; void reloadAtBegin(MachineBasicBlock &MBB); - bool setPhysReg(MachineInstr &MI, MachineOperand &MO, MCPhysReg PhysReg); + bool setPhysReg(MachineInstr &MI, MachineOperand &MO, + const LiveReg &Assignment); Register traceCopies(Register VirtReg) const; Register traceCopyChain(Register Reg) const; @@ -1005,7 +1007,8 @@ void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) { MO.setSubReg(0); } MO.setReg(PhysReg); - MO.setIsRenamable(true); + if (!LRI->Error) +MO.setIsRenamable(true); } /// Variation of defineVirtReg() with special handling for livethrough regs @@ -1109,10 +1112,10 @@ bool RegAllocFastImpl::defineVirtReg(MachineInstr &MI, unsigned OpNum, LRI->Reloaded = false; } if (MI.getOpcode() == TargetOpcode::BUNDLE) { -BundleVirtRegsMap[VirtReg] = PhysReg; +BundleVirtRegsMap[VirtReg] = *LRI; } markRegUsedInInstr(PhysReg); - return setPhysReg(MI, MO, PhysReg); + return setPhysReg(MI, MO, *LRI); } /// Allocates a register for a VirtReg use. @@ -1158,10 +1161,10 @@ bool RegAllocFastImpl::useVirtReg(MachineInstr &MI, MachineOperand &MO, LRI->LastUse = &MI; if (MI.getOpcode() == TargetOpcode::BUNDLE) { -BundleVirtRegsMap[VirtReg] = LRI->PhysReg; +BundleVirtRegsMap[VirtReg] = *LRI; } markRegUsedInInstr(LRI->PhysReg); - return setPhysReg(MI, MO, LRI->PhysReg); + return setPhysReg(MI, MO, *LRI); } /// Query a physical register to use as a filler in contexts where the @@ -1215,16 +1218,27 @@ MCPhysReg RegAllocFastImpl::getErrorAssignment(const LiveReg &LR, /// Changes operand OpNum in MI the refer the PhysReg, considering subregs. /// \return true if MI's MachineOperands were re-arranged/invalidated. bool RegAllocFastImpl::setPhysReg(MachineInstr &MI, MachineOperand &MO, - MCPhysReg PhysReg) { + const LiveReg &Assignment) { + MCPhysReg PhysReg = Assignment.PhysReg; + assert(PhysReg && "assignments should always be to a valid physreg"); + + if (LLVM_UNLIKELY(Assignment.Error)) { +// Make sure we don't set renamable in error scenarios, as we may have +// assigned to a reserved register. +if (MO.isUse()) + MO.setIsUndef(true); + } + if (!MO.getSubReg()) { MO.setReg(PhysReg); -MO.setIsRenamable(true); +MO.setIsRenamable(!Assignment.Error); return false; } // Handle subregister index. - MO.setReg(PhysReg ? TRI->getSubReg(PhysReg, MO.getSubReg()) : MCRegister()); - MO.setIsRenamable(true); + MO.setReg(TRI->getSubReg(PhysReg, MO.getSubReg())); + MO.setIsRenamable(!Assignment.Error); + // Note: We leave the subreg number around a little longer in case of defs. // This is so that the register freeing logic in allocateInstruction can still // recognize this as subregister defs. The code there will clear the number. @@ -1706,7 +1720,7 @@ void RegAllocFastImpl::handleDebugValue(MachineInstr &MI) { if (LRI != LiveVirtRegs.end() && LRI->PhysReg) { // Update every use of Reg within MI. for (auto &RegMO : DbgOps) -setPhysReg(MI, *RegMO, LRI->PhysReg); +setPhysReg(MI, *RegMO, *LRI); } else { DanglingDbgValues[Reg].push_back(&MI); } @@ -1729,8 +1743,7 @@ void RegAllocFastImpl::handleBundle(MachineInstr &MI) { if (!Reg.isVirtual() || !shouldAllocateRegister(Reg)) continue; - DenseMap::iterator DI; - DI = BundleVirtRegsMap.find(Reg); + DenseMap::iterator DI = BundleVirtRegsMap.find(Reg); assert(DI != BundleVirtRegsMap
[llvm-branch-commits] [llvm] RegAllocFast: Fix verifier errors after assigning to reserved registers (PR #128281)
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/128281 >From 8d9b1ee1f1e67bd5f946a9e88e14fc7e0a34248f Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 12 Dec 2024 10:53:41 +0900 Subject: [PATCH] RegAllocFast: Fix verifier errors after assigning to reserved registers --- llvm/lib/CodeGen/RegAllocFast.cpp | 41 --- ...ut-of-registers-error-all-regs-reserved.ll | 3 +- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 14128dafbe4ee..9f92c11826cce 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -206,6 +206,7 @@ class RegAllocFastImpl { bool Error = false; ///< Could not allocate. explicit LiveReg(Register VirtReg) : VirtReg(VirtReg) {} +explicit LiveReg() {} unsigned getSparseSetIndex() const { return VirtReg.virtRegIndex(); } }; @@ -216,7 +217,7 @@ class RegAllocFastImpl { LiveRegMap LiveVirtRegs; /// Stores assigned virtual registers present in the bundle MI. - DenseMap BundleVirtRegsMap; + DenseMap BundleVirtRegsMap; DenseMap> LiveDbgValueMap; /// List of DBG_VALUE that we encountered without the vreg being assigned @@ -374,7 +375,8 @@ class RegAllocFastImpl { SmallSet &PrologLiveIns) const; void reloadAtBegin(MachineBasicBlock &MBB); - bool setPhysReg(MachineInstr &MI, MachineOperand &MO, MCPhysReg PhysReg); + bool setPhysReg(MachineInstr &MI, MachineOperand &MO, + const LiveReg &Assignment); Register traceCopies(Register VirtReg) const; Register traceCopyChain(Register Reg) const; @@ -1005,7 +1007,8 @@ void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) { MO.setSubReg(0); } MO.setReg(PhysReg); - MO.setIsRenamable(true); + if (!LRI->Error) +MO.setIsRenamable(true); } /// Variation of defineVirtReg() with special handling for livethrough regs @@ -1109,10 +1112,10 @@ bool RegAllocFastImpl::defineVirtReg(MachineInstr &MI, unsigned OpNum, LRI->Reloaded = false; } if (MI.getOpcode() == TargetOpcode::BUNDLE) { -BundleVirtRegsMap[VirtReg] = PhysReg; +BundleVirtRegsMap[VirtReg] = *LRI; } markRegUsedInInstr(PhysReg); - return setPhysReg(MI, MO, PhysReg); + return setPhysReg(MI, MO, *LRI); } /// Allocates a register for a VirtReg use. @@ -1158,10 +1161,10 @@ bool RegAllocFastImpl::useVirtReg(MachineInstr &MI, MachineOperand &MO, LRI->LastUse = &MI; if (MI.getOpcode() == TargetOpcode::BUNDLE) { -BundleVirtRegsMap[VirtReg] = LRI->PhysReg; +BundleVirtRegsMap[VirtReg] = *LRI; } markRegUsedInInstr(LRI->PhysReg); - return setPhysReg(MI, MO, LRI->PhysReg); + return setPhysReg(MI, MO, *LRI); } /// Query a physical register to use as a filler in contexts where the @@ -1215,16 +1218,27 @@ MCPhysReg RegAllocFastImpl::getErrorAssignment(const LiveReg &LR, /// Changes operand OpNum in MI the refer the PhysReg, considering subregs. /// \return true if MI's MachineOperands were re-arranged/invalidated. bool RegAllocFastImpl::setPhysReg(MachineInstr &MI, MachineOperand &MO, - MCPhysReg PhysReg) { + const LiveReg &Assignment) { + MCPhysReg PhysReg = Assignment.PhysReg; + assert(PhysReg && "assignments should always be to a valid physreg"); + + if (LLVM_UNLIKELY(Assignment.Error)) { +// Make sure we don't set renamable in error scenarios, as we may have +// assigned to a reserved register. +if (MO.isUse()) + MO.setIsUndef(true); + } + if (!MO.getSubReg()) { MO.setReg(PhysReg); -MO.setIsRenamable(true); +MO.setIsRenamable(!Assignment.Error); return false; } // Handle subregister index. - MO.setReg(PhysReg ? TRI->getSubReg(PhysReg, MO.getSubReg()) : MCRegister()); - MO.setIsRenamable(true); + MO.setReg(TRI->getSubReg(PhysReg, MO.getSubReg())); + MO.setIsRenamable(!Assignment.Error); + // Note: We leave the subreg number around a little longer in case of defs. // This is so that the register freeing logic in allocateInstruction can still // recognize this as subregister defs. The code there will clear the number. @@ -1706,7 +1720,7 @@ void RegAllocFastImpl::handleDebugValue(MachineInstr &MI) { if (LRI != LiveVirtRegs.end() && LRI->PhysReg) { // Update every use of Reg within MI. for (auto &RegMO : DbgOps) -setPhysReg(MI, *RegMO, LRI->PhysReg); +setPhysReg(MI, *RegMO, *LRI); } else { DanglingDbgValues[Reg].push_back(&MI); } @@ -1729,8 +1743,7 @@ void RegAllocFastImpl::handleBundle(MachineInstr &MI) { if (!Reg.isVirtual() || !shouldAllocateRegister(Reg)) continue; - DenseMap::iterator DI; - DI = BundleVirtRegsMap.find(Reg); + DenseMap::iterator DI = BundleVirtRegsMap.find(Reg); assert(DI != BundleVirtRegsMap
[llvm-branch-commits] [llvm] RegAllocFast: Fix verifier errors after assigning to reserved registers (PR #128281)
@@ -1005,7 +1007,8 @@ void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) { MO.setSubReg(0); } MO.setReg(PhysReg); - MO.setIsRenamable(true); + if (!LRI->Error) +MO.setIsRenamable(true); cdevadas wrote: ```suggestion MO.setIsRenamable(!LRI->Error); ``` https://github.com/llvm/llvm-project/pull/128281 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] c47780a - Revert "[analyzer] Delay the checker constructions after parsing (#127409)"
Author: Balazs Benics Date: 2025-02-22T11:42:41+01:00 New Revision: c47780aa45385a617e9beeb032896beebb2f3411 URL: https://github.com/llvm/llvm-project/commit/c47780aa45385a617e9beeb032896beebb2f3411 DIFF: https://github.com/llvm/llvm-project/commit/c47780aa45385a617e9beeb032896beebb2f3411.diff LOG: Revert "[analyzer] Delay the checker constructions after parsing (#127409)" This reverts commit f0088ee87cecfb442921251b4a70f96cf3474a15. Added: Modified: clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp Removed: diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 10dfa73cc522d..da2d16ca9b5dd 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -40,28 +40,17 @@ enum class OpenVariant { OpenAt }; -static std::optional getCreateFlagValue(const ASTContext &Ctx, - const Preprocessor &PP) { - std::optional MacroVal = tryExpandAsInteger("O_CREAT", PP); - if (MacroVal.has_value()) -return MacroVal; - - // If we failed, fall-back to known values. - if (Ctx.getTargetInfo().getTriple().getVendor() == llvm::Triple::Apple) -return {0x0200}; - return MacroVal; -} - namespace { -class UnixAPIMisuseChecker : public Checker { +class UnixAPIMisuseChecker +: public Checker> { const BugType BT_open{this, "Improper use of 'open'", categories::UnixAPI}; const BugType BT_getline{this, "Improper use of getdelim", categories::UnixAPI}; const BugType BT_pthreadOnce{this, "Improper use of 'pthread_once'", categories::UnixAPI}; const BugType BT_ArgumentNull{this, "NULL pointer", categories::UnixAPI}; - const std::optional Val_O_CREAT; + mutable std::optional Val_O_CREAT; ProgramStateRef EnsurePtrNotNull(SVal PtrVal, const Expr *PtrExpr, CheckerContext &C, @@ -74,9 +63,6 @@ class UnixAPIMisuseChecker : public Checker { const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const; public: - UnixAPIMisuseChecker(const ASTContext &Ctx, const Preprocessor &PP) - : Val_O_CREAT(getCreateFlagValue(Ctx, PP)) {} - void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr, BugReporter &BR) const; @@ -148,6 +134,20 @@ ProgramStateRef UnixAPIMisuseChecker::EnsurePtrNotNull( return PtrNotNull; } +void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU, +AnalysisManager &Mgr, +BugReporter &) const { + // The definition of O_CREAT is platform specific. + // Try to get the macro value from the preprocessor. + Val_O_CREAT = tryExpandAsInteger("O_CREAT", Mgr.getPreprocessor()); + // If we failed, fall-back to known values. + if (!Val_O_CREAT) { +if (TU->getASTContext().getTargetInfo().getTriple().getVendor() == +llvm::Triple::Apple) + Val_O_CREAT = 0x0200; + } +} + //===--===// // "open" (man 2 open) //===--===/ @@ -262,7 +262,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, return; } - if (!Val_O_CREAT.has_value()) { + if (!Val_O_CREAT) { return; } @@ -276,7 +276,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, } NonLoc oflags = V.castAs(); NonLoc ocreateFlag = C.getSValBuilder() - .makeIntVal(Val_O_CREAT.value(), oflagsEx->getType()) + .makeIntVal(*Val_O_CREAT, oflagsEx->getType()) .castAs(); SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And, oflags, ocreateFlag, @@ -621,17 +621,14 @@ void UnixAPIPortabilityChecker::checkPreStmt(const CallExpr *CE, // Registration. //===--===// -void ento::registerUnixAPIMisuseChecker(CheckerManager &Mgr) { - Mgr.registerChecker(Mgr.getASTContext(), -Mgr.getPreprocessor()); -} -bool ento::shouldRegisterUnixAPIMisuseChecker(const CheckerManager &Mgr) { - return true; -} +#define REGISTER_CHECKER(CHECKERNAME) \ + void ento::register##CHECKERNAME(CheckerManager &mgr) { \ +mgr.registerChecker(); \ + } \ + \ + bool ento::shouldRegister##
[llvm-branch-commits] [libcxx] [NFC][libc++] Guard agains operator& hijacking. (PR #128351)
https://github.com/mordante created https://github.com/llvm/llvm-project/pull/128351 This set usage of operator& instead of std::addressof seems not be easy to "abuse". Some seem easy to misuse, like basic_ostream::operator<<, trying to do that results in compilation errors since the `widen` function is not specialized for the hijacking character type. Hence there are no tests. >From 6614bf3ed9221cf47baeede6d06f2c9f2455dfe1 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sun, 16 Feb 2025 13:25:15 +0100 Subject: [PATCH] [NFC][libc++] Guard agains operator& hijacking. This set usage of operator& instead of std::addressof seems not be easy to "abuse". Some seem easy to misuse, like basic_ostream::operator<<, trying to do that results in compilation errors since the `widen` function is not specialized for the hijacking character type. Hence there are no tests. --- libcxx/include/__atomic/atomic.h | 2 +- libcxx/include/__atomic/atomic_ref.h | 2 +- libcxx/include/__charconv/traits.h| 3 +- libcxx/include/__filesystem/path.h| 3 +- libcxx/include/__functional/hash.h| 11 ++-- libcxx/include/__iterator/aliasing_iterator.h | 2 +- libcxx/include/__locale | 3 +- libcxx/include/__mdspan/layout_left.h | 2 +- libcxx/include/__mdspan/layout_right.h| 2 +- libcxx/include/__mdspan/layout_stride.h | 7 +-- libcxx/include/__mdspan/mdspan.h | 2 +- libcxx/include/__memory/shared_count.h| 5 +- libcxx/include/__ostream/basic_ostream.h | 9 ++-- libcxx/include/__split_buffer | 6 +-- .../__stop_token/intrusive_shared_ptr.h | 3 +- .../include/__string/constexpr_c_functions.h | 2 +- libcxx/include/__thread/thread.h | 3 +- libcxx/include/cwchar | 3 +- libcxx/include/fstream| 10 ++-- libcxx/include/future | 14 ++--- libcxx/include/locale | 5 +- libcxx/include/regex | 51 ++- libcxx/include/string | 4 +- 23 files changed, 83 insertions(+), 71 deletions(-) diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h index 975a479e20400..8a0996a478e2f 100644 --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -361,7 +361,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> { // https://github.com/llvm/llvm-project/issues/47978 // clang bug: __old is not updated on failure for atomic::compare_exchange_weak // Note __old = __self.load(memory_order_relaxed) will not work - std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed); + std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), std::addressof(__old), memory_order_relaxed); } # endif __new = __operation(__old, __operand); diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h index 177ea646b6cd0..b5493662c518e 100644 --- a/libcxx/include/__atomic/atomic_ref.h +++ b/libcxx/include/__atomic/atomic_ref.h @@ -119,7 +119,7 @@ struct __atomic_ref_base { // that the pointer is going to be aligned properly at runtime because that is a (checked) precondition // of atomic_ref's constructor. static constexpr bool is_always_lock_free = - __atomic_always_lock_free(sizeof(_Tp), &__get_aligner_instance::__instance); + __atomic_always_lock_free(sizeof(_Tp), std::addressof(__get_aligner_instance::__instance)); _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); } diff --git a/libcxx/include/__charconv/traits.h b/libcxx/include/__charconv/traits.h index 2cb37c8cfb023..dd1fa2354436a 100644 --- a/libcxx/include/__charconv/traits.h +++ b/libcxx/include/__charconv/traits.h @@ -15,6 +15,7 @@ #include <__charconv/tables.h> #include <__charconv/to_chars_base_10.h> #include <__config> +#include <__memory/addressof.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_unsigned.h> #include @@ -142,7 +143,7 @@ __mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) { template inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) { static_assert(is_unsigned<_Tp>::value, ""); - return __builtin_mul_overflow(__a, __b, &__r); + return __builtin_mul_overflow(__a, __b, std::addressof(__r)); } template diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index 698ae209ae1f8..a2c28bfd79bb9 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -17,6 +17,7 @@ #include <__fwd/functional.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> #includ
[llvm-branch-commits] [libcxx] [NFC][libc++] Guard agains operator& hijacking. (PR #128351)
https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/128351 >From 921a76f2275b2bde219a9f0a7a434da1f22294f9 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sun, 16 Feb 2025 13:25:15 +0100 Subject: [PATCH] [NFC][libc++] Guard agains operator& hijacking. This set usage of operator& instead of std::addressof seems not be easy to "abuse". Some seem easy to misuse, like basic_ostream::operator<<, trying to do that results in compilation errors since the `widen` function is not specialized for the hijacking character type. Hence there are no tests. --- libcxx/include/__atomic/atomic.h | 2 +- libcxx/include/__atomic/atomic_ref.h | 2 +- libcxx/include/__charconv/traits.h| 3 +- libcxx/include/__filesystem/path.h| 3 +- libcxx/include/__functional/hash.h| 11 ++-- libcxx/include/__iterator/aliasing_iterator.h | 2 +- libcxx/include/__locale | 3 +- libcxx/include/__mdspan/layout_left.h | 2 +- libcxx/include/__mdspan/layout_right.h| 2 +- libcxx/include/__mdspan/layout_stride.h | 7 +-- libcxx/include/__mdspan/mdspan.h | 2 +- libcxx/include/__memory/shared_count.h| 5 +- libcxx/include/__ostream/basic_ostream.h | 9 ++-- libcxx/include/__split_buffer | 6 +-- .../__stop_token/intrusive_shared_ptr.h | 3 +- .../include/__string/constexpr_c_functions.h | 2 +- libcxx/include/__thread/thread.h | 3 +- libcxx/include/cwchar | 3 +- libcxx/include/fstream| 10 ++-- libcxx/include/future | 14 ++--- libcxx/include/locale | 5 +- libcxx/include/regex | 51 ++- libcxx/include/string | 4 +- 23 files changed, 83 insertions(+), 71 deletions(-) diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h index 975a479e20400..8a0996a478e2f 100644 --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -361,7 +361,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> { // https://github.com/llvm/llvm-project/issues/47978 // clang bug: __old is not updated on failure for atomic::compare_exchange_weak // Note __old = __self.load(memory_order_relaxed) will not work - std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed); + std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), std::addressof(__old), memory_order_relaxed); } # endif __new = __operation(__old, __operand); diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h index 177ea646b6cd0..b5493662c518e 100644 --- a/libcxx/include/__atomic/atomic_ref.h +++ b/libcxx/include/__atomic/atomic_ref.h @@ -119,7 +119,7 @@ struct __atomic_ref_base { // that the pointer is going to be aligned properly at runtime because that is a (checked) precondition // of atomic_ref's constructor. static constexpr bool is_always_lock_free = - __atomic_always_lock_free(sizeof(_Tp), &__get_aligner_instance::__instance); + __atomic_always_lock_free(sizeof(_Tp), std::addressof(__get_aligner_instance::__instance)); _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); } diff --git a/libcxx/include/__charconv/traits.h b/libcxx/include/__charconv/traits.h index 2cb37c8cfb023..dd1fa2354436a 100644 --- a/libcxx/include/__charconv/traits.h +++ b/libcxx/include/__charconv/traits.h @@ -15,6 +15,7 @@ #include <__charconv/tables.h> #include <__charconv/to_chars_base_10.h> #include <__config> +#include <__memory/addressof.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_unsigned.h> #include @@ -142,7 +143,7 @@ __mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) { template inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) { static_assert(is_unsigned<_Tp>::value, ""); - return __builtin_mul_overflow(__a, __b, &__r); + return __builtin_mul_overflow(__a, __b, std::addressof(__r)); } template diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index 698ae209ae1f8..a2c28bfd79bb9 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -17,6 +17,7 @@ #include <__fwd/functional.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> #include <__type_traits/decay.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_pointer.h> @@ -584,7 +585,7 @@ class _LIBCPP_EXPORTED_FROM_ABI path { template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) { -_PathCVT<_ECharT>::__append_source(__pn_,
[llvm-branch-commits] [libcxx] [NFC][libc++] Guard agains operator& hijacking. (PR #128351)
https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/128351 >From 05c33c80b15e9f1cd27206f31ff69add583f72af Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sun, 16 Feb 2025 13:25:15 +0100 Subject: [PATCH] [NFC][libc++] Guard agains operator& hijacking. This set usage of operator& instead of std::addressof seems not be easy to "abuse". Some seem easy to misuse, like basic_ostream::operator<<, trying to do that results in compilation errors since the `widen` function is not specialized for the hijacking character type. Hence there are no tests. --- libcxx/include/__atomic/atomic.h | 2 +- libcxx/include/__atomic/atomic_ref.h | 2 +- libcxx/include/__charconv/traits.h| 3 +- libcxx/include/__filesystem/path.h| 3 +- libcxx/include/__functional/hash.h| 11 ++-- libcxx/include/__iterator/aliasing_iterator.h | 3 +- libcxx/include/__locale | 3 +- libcxx/include/__mdspan/layout_left.h | 3 +- libcxx/include/__mdspan/layout_right.h| 3 +- libcxx/include/__mdspan/layout_stride.h | 10 ++-- libcxx/include/__mdspan/mdspan.h | 3 +- libcxx/include/__memory/shared_count.h| 5 +- libcxx/include/__ostream/basic_ostream.h | 9 ++-- libcxx/include/__split_buffer | 6 +-- .../__stop_token/intrusive_shared_ptr.h | 3 +- .../include/__string/constexpr_c_functions.h | 2 +- libcxx/include/__thread/thread.h | 3 +- libcxx/include/cwchar | 3 +- libcxx/include/fstream| 10 ++-- libcxx/include/future | 10 ++-- libcxx/include/locale | 5 +- libcxx/include/regex | 51 ++- libcxx/include/string | 4 +- 23 files changed, 87 insertions(+), 70 deletions(-) diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h index 975a479e20400..8a0996a478e2f 100644 --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -361,7 +361,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> { // https://github.com/llvm/llvm-project/issues/47978 // clang bug: __old is not updated on failure for atomic::compare_exchange_weak // Note __old = __self.load(memory_order_relaxed) will not work - std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed); + std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), std::addressof(__old), memory_order_relaxed); } # endif __new = __operation(__old, __operand); diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h index 177ea646b6cd0..b5493662c518e 100644 --- a/libcxx/include/__atomic/atomic_ref.h +++ b/libcxx/include/__atomic/atomic_ref.h @@ -119,7 +119,7 @@ struct __atomic_ref_base { // that the pointer is going to be aligned properly at runtime because that is a (checked) precondition // of atomic_ref's constructor. static constexpr bool is_always_lock_free = - __atomic_always_lock_free(sizeof(_Tp), &__get_aligner_instance::__instance); + __atomic_always_lock_free(sizeof(_Tp), std::addressof(__get_aligner_instance::__instance)); _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); } diff --git a/libcxx/include/__charconv/traits.h b/libcxx/include/__charconv/traits.h index 2cb37c8cfb023..dd1fa2354436a 100644 --- a/libcxx/include/__charconv/traits.h +++ b/libcxx/include/__charconv/traits.h @@ -15,6 +15,7 @@ #include <__charconv/tables.h> #include <__charconv/to_chars_base_10.h> #include <__config> +#include <__memory/addressof.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_unsigned.h> #include @@ -142,7 +143,7 @@ __mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) { template inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) { static_assert(is_unsigned<_Tp>::value, ""); - return __builtin_mul_overflow(__a, __b, &__r); + return __builtin_mul_overflow(__a, __b, std::addressof(__r)); } template diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index 698ae209ae1f8..a2c28bfd79bb9 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -17,6 +17,7 @@ #include <__fwd/functional.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> #include <__type_traits/decay.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_pointer.h> @@ -584,7 +585,7 @@ class _LIBCPP_EXPORTED_FROM_ABI path { template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) { -_PathCVT<_ECharT>::__append_source(__pn_,
[llvm-branch-commits] [llvm] [AMDGPU][Attributor] Rework update of `AAAMDWavesPerEU` (PR #123995)
jplehr wrote: Out of curiosity: I believe this is case three, why would we not want to use the user-provided values? https://github.com/llvm/llvm-project/pull/123995 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [libcxx] [libc++] Clang-tidy operator& hijacker. (PR #128366)
https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/128366 >From ab09f9dfbc3ee01af586b8a5285ac72b4f35e2f9 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sun, 16 Feb 2025 12:07:44 +0100 Subject: [PATCH] [libc++] Clang-tidy operator& hijacker. Guards against introducing new places where operator& depends on a template type. --- .../tools/clang_tidy_checks/CMakeLists.txt| 1 + .../tools/clang_tidy_checks/libcpp_module.cpp | 3 ++ .../robust_against_operator_ampersand.cpp | 47 +++ .../robust_against_operator_ampersand.hpp | 24 ++ 4 files changed, 75 insertions(+) create mode 100644 libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp create mode 100644 libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp diff --git a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt index 0f8f0e8864d0f..e8e62c3f4ba40 100644 --- a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt +++ b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt @@ -96,6 +96,7 @@ set(SOURCES proper_version_checks.cpp qualify_declval.cpp robust_against_adl.cpp +robust_against_operator_ampersand.cpp uglify_attributes.cpp libcpp_module.cpp diff --git a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp index bc7c8ce7ec443..a52e25f2cf08f 100644 --- a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp +++ b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp @@ -17,6 +17,7 @@ #include "proper_version_checks.hpp" #include "qualify_declval.hpp" #include "robust_against_adl.hpp" +#include "robust_against_operator_ampersand.hpp" #include "uglify_attributes.hpp" namespace { @@ -30,6 +31,8 @@ class LibcxxTestModule : public clang::tidy::ClangTidyModule { check_factories.registerCheck("libcpp-nodebug-on-aliases"); check_factories.registerCheck("libcpp-cpp-version-check"); check_factories.registerCheck("libcpp-robust-against-adl"); +check_factories.registerCheck( +"libcpp-robust-against-operator-ampersand"); check_factories.registerCheck("libcpp-uglify-attributes"); check_factories.registerCheck("libcpp-qualify-declval"); } diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp new file mode 100644 index 0..3d3e7d516be9a --- /dev/null +++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp @@ -0,0 +1,47 @@ +//===--===// +// +// 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-tidy/ClangTidyCheck.h" +#include "clang-tidy/ClangTidyModuleRegistry.h" +#include "clang/Tooling/FixIt.h" + +#include "robust_against_operator_ampersand.hpp" + +// This clang-tidy check ensures that we don't use operator& on dependant +// types. If the type is user supplied it may call the type's operator&. +// Instead use std::addressof. + +namespace libcpp { +robust_against_operator_ampersand::robust_against_operator_ampersand( +llvm::StringRef name, clang::tidy::ClangTidyContext* context) +: clang::tidy::ClangTidyCheck(name, context), disabled_(!context->getLangOpts().CPlusPlus11) {} + +void robust_against_operator_ampersand::registerMatchers(clang::ast_matchers::MatchFinder* finder) { + if (disabled_) +return; + + using namespace clang::ast_matchers; + finder->addMatcher( + cxxOperatorCallExpr(allOf(hasOperatorName("&"), argumentCountIs(1), isTypeDependent()), + unless(hasUnaryOperand(dependentScopeDeclRefExpr( + .bind("match"), + this); +} + +void robust_against_operator_ampersand::check(const clang::ast_matchers::MatchFinder::MatchResult& result) { + if (const auto* call = result.Nodes.getNodeAs< clang::CXXOperatorCallExpr >("match"); call != nullptr) { +diag(call->getBeginLoc(), "Guard against user provided operator& for dependent types.") +<< clang::FixItHint::CreateReplacement( + call->getSourceRange(), + (llvm::Twine( +"std::addressof(" + clang::tooling::fixit::getText(*call->getArg(0), *result.Context) + ")")) + .str()); + } +} + +} // namespace libcpp diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp new file mode 100644 index 0..e7010de02685c --- /dev/null +++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampers
[llvm-branch-commits] [libcxx] [libc++] Clang-tidy operator& hijacker. (PR #128366)
llvmbot wrote: @llvm/pr-subscribers-libcxx Author: Mark de Wever (mordante) Changes Guards against introducing new places where operator& depends on a template type. --- Full diff: https://github.com/llvm/llvm-project/pull/128366.diff 4 Files Affected: - (modified) libcxx/test/tools/clang_tidy_checks/CMakeLists.txt (+1) - (modified) libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp (+3) - (added) libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp (+44) - (added) libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp (+18) ``diff diff --git a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt index 0f8f0e8864d0f..e8e62c3f4ba40 100644 --- a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt +++ b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt @@ -96,6 +96,7 @@ set(SOURCES proper_version_checks.cpp qualify_declval.cpp robust_against_adl.cpp +robust_against_operator_ampersand.cpp uglify_attributes.cpp libcpp_module.cpp diff --git a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp index bc7c8ce7ec443..a52e25f2cf08f 100644 --- a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp +++ b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp @@ -17,6 +17,7 @@ #include "proper_version_checks.hpp" #include "qualify_declval.hpp" #include "robust_against_adl.hpp" +#include "robust_against_operator_ampersand.hpp" #include "uglify_attributes.hpp" namespace { @@ -30,6 +31,8 @@ class LibcxxTestModule : public clang::tidy::ClangTidyModule { check_factories.registerCheck("libcpp-nodebug-on-aliases"); check_factories.registerCheck("libcpp-cpp-version-check"); check_factories.registerCheck("libcpp-robust-against-adl"); +check_factories.registerCheck( +"libcpp-robust-against-operator-ampersand"); check_factories.registerCheck("libcpp-uglify-attributes"); check_factories.registerCheck("libcpp-qualify-declval"); } diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp new file mode 100644 index 0..8361e0c3eee88 --- /dev/null +++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp @@ -0,0 +1,44 @@ +//===--===// +// +// 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-tidy/ClangTidyCheck.h" +#include "clang-tidy/ClangTidyModuleRegistry.h" +#include "clang/Tooling/FixIt.h" + +#include "robust_against_operator_ampersand.hpp" + +// This clang-tidy check ensures that we don't use operator& on dependant +// types. If the type is user supplied it may call the type's operator&. +// Instead use std::addressof. + +namespace libcpp { +robust_against_operator_ampersand::robust_against_operator_ampersand( +llvm::StringRef name, clang::tidy::ClangTidyContext* context) +: clang::tidy::ClangTidyCheck(name, context) {} + +void robust_against_operator_ampersand::registerMatchers(clang::ast_matchers::MatchFinder* finder) { + using namespace clang::ast_matchers; + finder->addMatcher( + cxxOperatorCallExpr(allOf(hasOperatorName("&"), argumentCountIs(1), isTypeDependent()), + unless(hasUnaryOperand(dependentScopeDeclRefExpr( + .bind("match"), + this); +} + +void robust_against_operator_ampersand::check(const clang::ast_matchers::MatchFinder::MatchResult& result) { + if (const auto* call = result.Nodes.getNodeAs< clang::CXXOperatorCallExpr >("match"); call != nullptr) { +diag(call->getBeginLoc(), "Guard against user provided operator& for dependent types.") +<< clang::FixItHint::CreateReplacement( + call->getSourceRange(), + (llvm::Twine( +"std::addressof(" + clang::tooling::fixit::getText(*call->getArg(0), *result.Context) + ")")) + .str()); + } +} + +} // namespace libcpp diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp new file mode 100644 index 0..5cdc0baca5c23 --- /dev/null +++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp @@ -0,0 +1,18 @@ +//===--===// +// +// 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 LLV
[llvm-branch-commits] [libcxx] [libc++] Clang-tidy operator& hijacker. (PR #128366)
https://github.com/mordante created https://github.com/llvm/llvm-project/pull/128366 Guards against introducing new places where operator& depends on a template type. >From 5a96aadb54b757812dc48f07e753477164d8062a Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sun, 16 Feb 2025 12:07:44 +0100 Subject: [PATCH] [libc++] Clang-tidy operator& hijacker. Guards against introducing new places where operator& depends on a template type. --- .../tools/clang_tidy_checks/CMakeLists.txt| 1 + .../tools/clang_tidy_checks/libcpp_module.cpp | 3 ++ .../robust_against_operator_ampersand.cpp | 44 +++ .../robust_against_operator_ampersand.hpp | 18 4 files changed, 66 insertions(+) create mode 100644 libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp create mode 100644 libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp diff --git a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt index 0f8f0e8864d0f..e8e62c3f4ba40 100644 --- a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt +++ b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt @@ -96,6 +96,7 @@ set(SOURCES proper_version_checks.cpp qualify_declval.cpp robust_against_adl.cpp +robust_against_operator_ampersand.cpp uglify_attributes.cpp libcpp_module.cpp diff --git a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp index bc7c8ce7ec443..a52e25f2cf08f 100644 --- a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp +++ b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp @@ -17,6 +17,7 @@ #include "proper_version_checks.hpp" #include "qualify_declval.hpp" #include "robust_against_adl.hpp" +#include "robust_against_operator_ampersand.hpp" #include "uglify_attributes.hpp" namespace { @@ -30,6 +31,8 @@ class LibcxxTestModule : public clang::tidy::ClangTidyModule { check_factories.registerCheck("libcpp-nodebug-on-aliases"); check_factories.registerCheck("libcpp-cpp-version-check"); check_factories.registerCheck("libcpp-robust-against-adl"); +check_factories.registerCheck( +"libcpp-robust-against-operator-ampersand"); check_factories.registerCheck("libcpp-uglify-attributes"); check_factories.registerCheck("libcpp-qualify-declval"); } diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp new file mode 100644 index 0..8361e0c3eee88 --- /dev/null +++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp @@ -0,0 +1,44 @@ +//===--===// +// +// 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-tidy/ClangTidyCheck.h" +#include "clang-tidy/ClangTidyModuleRegistry.h" +#include "clang/Tooling/FixIt.h" + +#include "robust_against_operator_ampersand.hpp" + +// This clang-tidy check ensures that we don't use operator& on dependant +// types. If the type is user supplied it may call the type's operator&. +// Instead use std::addressof. + +namespace libcpp { +robust_against_operator_ampersand::robust_against_operator_ampersand( +llvm::StringRef name, clang::tidy::ClangTidyContext* context) +: clang::tidy::ClangTidyCheck(name, context) {} + +void robust_against_operator_ampersand::registerMatchers(clang::ast_matchers::MatchFinder* finder) { + using namespace clang::ast_matchers; + finder->addMatcher( + cxxOperatorCallExpr(allOf(hasOperatorName("&"), argumentCountIs(1), isTypeDependent()), + unless(hasUnaryOperand(dependentScopeDeclRefExpr( + .bind("match"), + this); +} + +void robust_against_operator_ampersand::check(const clang::ast_matchers::MatchFinder::MatchResult& result) { + if (const auto* call = result.Nodes.getNodeAs< clang::CXXOperatorCallExpr >("match"); call != nullptr) { +diag(call->getBeginLoc(), "Guard against user provided operator& for dependent types.") +<< clang::FixItHint::CreateReplacement( + call->getSourceRange(), + (llvm::Twine( +"std::addressof(" + clang::tooling::fixit::getText(*call->getArg(0), *result.Context) + ")")) + .str()); + } +} + +} // namespace libcpp diff --git a/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.hpp new file mode 100644 index 0..5cdc0baca5c23 --- /dev/null +++ b/libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampers
[llvm-branch-commits] [libcxx] [NFC][libc++] Guard agains operator& hijacking. (PR #128351)
llvmbot wrote: @llvm/pr-subscribers-libcxx Author: Mark de Wever (mordante) Changes This set usage of operator& instead of std::addressof seems not be easy to "abuse". Some seem easy to misuse, like basic_ostream::operator<<, trying to do that results in compilation errors since the `widen` function is not specialized for the hijacking character type. Hence there are no tests. --- Patch is 34.49 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/128351.diff 23 Files Affected: - (modified) libcxx/include/__atomic/atomic.h (+1-1) - (modified) libcxx/include/__atomic/atomic_ref.h (+1-1) - (modified) libcxx/include/__charconv/traits.h (+2-1) - (modified) libcxx/include/__filesystem/path.h (+2-1) - (modified) libcxx/include/__functional/hash.h (+6-5) - (modified) libcxx/include/__iterator/aliasing_iterator.h (+1-1) - (modified) libcxx/include/__locale (+2-1) - (modified) libcxx/include/__mdspan/layout_left.h (+1-1) - (modified) libcxx/include/__mdspan/layout_right.h (+1-1) - (modified) libcxx/include/__mdspan/layout_stride.h (+4-3) - (modified) libcxx/include/__mdspan/mdspan.h (+1-1) - (modified) libcxx/include/__memory/shared_count.h (+3-2) - (modified) libcxx/include/__ostream/basic_ostream.h (+5-4) - (modified) libcxx/include/__split_buffer (+3-3) - (modified) libcxx/include/__stop_token/intrusive_shared_ptr.h (+2-1) - (modified) libcxx/include/__string/constexpr_c_functions.h (+1-1) - (modified) libcxx/include/__thread/thread.h (+2-1) - (modified) libcxx/include/cwchar (+2-1) - (modified) libcxx/include/fstream (+5-5) - (modified) libcxx/include/future (+7-7) - (modified) libcxx/include/locale (+3-2) - (modified) libcxx/include/regex (+26-25) - (modified) libcxx/include/string (+2-2) ``diff diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h index 975a479e20400..8a0996a478e2f 100644 --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -361,7 +361,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> { // https://github.com/llvm/llvm-project/issues/47978 // clang bug: __old is not updated on failure for atomic::compare_exchange_weak // Note __old = __self.load(memory_order_relaxed) will not work - std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed); + std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), std::addressof(__old), memory_order_relaxed); } # endif __new = __operation(__old, __operand); diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h index 177ea646b6cd0..b5493662c518e 100644 --- a/libcxx/include/__atomic/atomic_ref.h +++ b/libcxx/include/__atomic/atomic_ref.h @@ -119,7 +119,7 @@ struct __atomic_ref_base { // that the pointer is going to be aligned properly at runtime because that is a (checked) precondition // of atomic_ref's constructor. static constexpr bool is_always_lock_free = - __atomic_always_lock_free(sizeof(_Tp), &__get_aligner_instance::__instance); + __atomic_always_lock_free(sizeof(_Tp), std::addressof(__get_aligner_instance::__instance)); _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); } diff --git a/libcxx/include/__charconv/traits.h b/libcxx/include/__charconv/traits.h index 2cb37c8cfb023..dd1fa2354436a 100644 --- a/libcxx/include/__charconv/traits.h +++ b/libcxx/include/__charconv/traits.h @@ -15,6 +15,7 @@ #include <__charconv/tables.h> #include <__charconv/to_chars_base_10.h> #include <__config> +#include <__memory/addressof.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_unsigned.h> #include @@ -142,7 +143,7 @@ __mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) { template inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) { static_assert(is_unsigned<_Tp>::value, ""); - return __builtin_mul_overflow(__a, __b, &__r); + return __builtin_mul_overflow(__a, __b, std::addressof(__r)); } template diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index 698ae209ae1f8..a2c28bfd79bb9 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -17,6 +17,7 @@ #include <__fwd/functional.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> #include <__type_traits/decay.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_pointer.h> @@ -584,7 +585,7 @@ class _LIBCPP_EXPORTED_FROM_ABI path { template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) { -_PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(&__x, 1)); +_PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(std::add
[llvm-branch-commits] [libcxx] [NFC][libc++] Guard agains operator& hijacking. (PR #128351)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 0e79268c4ac3b91dd5742bc04d8d5658bf587b0e 6614bf3ed9221cf47baeede6d06f2c9f2455dfe1 --extensions ,h -- libcxx/include/__atomic/atomic.h libcxx/include/__atomic/atomic_ref.h libcxx/include/__charconv/traits.h libcxx/include/__filesystem/path.h libcxx/include/__functional/hash.h libcxx/include/__iterator/aliasing_iterator.h libcxx/include/__locale libcxx/include/__mdspan/layout_left.h libcxx/include/__mdspan/layout_right.h libcxx/include/__mdspan/layout_stride.h libcxx/include/__mdspan/mdspan.h libcxx/include/__memory/shared_count.h libcxx/include/__ostream/basic_ostream.h libcxx/include/__split_buffer libcxx/include/__stop_token/intrusive_shared_ptr.h libcxx/include/__string/constexpr_c_functions.h libcxx/include/__thread/thread.h libcxx/include/cwchar libcxx/include/fstream libcxx/include/future libcxx/include/locale libcxx/include/regex libcxx/include/string `` View the diff from clang-format here. ``diff diff --git a/libcxx/include/regex b/libcxx/include/regex index 617431efca..c04cbc316d 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -2177,7 +2177,8 @@ void __bracket_expression<_CharT, _Traits>::__exec(__state& __s) const { } } if (!__equivalences_.empty()) { -string_type __s2 = __traits_.transform_primary(std::addressof(__ch2.first), std::addressof(__ch2.first) + 2); +string_type __s2 = +__traits_.transform_primary(std::addressof(__ch2.first), std::addressof(__ch2.first) + 2); for (size_t __i = 0; __i < __equivalences_.size(); ++__i) { if (__s2 == __equivalences_[__i]) { __found = true; @@ -2225,7 +2226,8 @@ void __bracket_expression<_CharT, _Traits>::__exec(__state& __s) const { } } if (!__ranges_.empty()) { - string_type __s2 = __collate_ ? __traits_.transform(std::addressof(__ch), std::addressof(__ch) + 1) : string_type(1, __ch); + string_type __s2 = + __collate_ ? __traits_.transform(std::addressof(__ch), std::addressof(__ch) + 1) : string_type(1, __ch); for (size_t __i = 0; __i < __ranges_.size(); ++__i) { if (__ranges_[__i].first <= __s2 && __s2 <= __ranges_[__i].second) { __found = true; @@ -5678,7 +5680,8 @@ template bool regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>::operator==(const regex_token_iterator& __x) const { if (__result_ == nullptr && __x.__result_ == nullptr) return true; - if (__result_ == std::addressof(__suffix_) && __x.__result_ == std::addressof(__x.__suffix_) && __suffix_ == __x.__suffix_) + if (__result_ == std::addressof(__suffix_) && __x.__result_ == std::addressof(__x.__suffix_) && + __suffix_ == __x.__suffix_) return true; if (__result_ == nullptr || __x.__result_ == nullptr) return false; `` https://github.com/llvm/llvm-project/pull/128351 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [libcxx] [NFC][libc++] Guard against operator& hijacking. (PR #128351)
https://github.com/mordante edited https://github.com/llvm/llvm-project/pull/128351 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AMDGPU][Attributor] Rework update of `AAAMDWavesPerEU` (PR #123995)
arsenm wrote: > Out of curiosity: I believe this is case three, why would we not want to use > the user-provided values? A library use does not have the usage context. It may have specified a bounds to avoid negatively impacting occupancy of some unknown calling kernel. If we know the bounds of the concrete calling kernels, the function should specialize for its bound https://github.com/llvm/llvm-project/pull/123995 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [flang][draft] update fir.coordinate_of to carry the fields (PR #127231)
https://github.com/clementval approved this pull request. https://github.com/llvm/llvm-project/pull/127231 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] RegAllocFast: Fix verifier errors after assigning to reserved registers (PR #128281)
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/128281 >From d93b45487feba452868706b31e6e59e0bb1a5d19 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 12 Dec 2024 10:53:41 +0900 Subject: [PATCH] RegAllocFast: Fix verifier errors after assigning to reserved registers --- llvm/lib/CodeGen/RegAllocFast.cpp | 41 --- ...ut-of-registers-error-all-regs-reserved.ll | 3 +- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 14128dafbe4ee..9f92c11826cce 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -206,6 +206,7 @@ class RegAllocFastImpl { bool Error = false; ///< Could not allocate. explicit LiveReg(Register VirtReg) : VirtReg(VirtReg) {} +explicit LiveReg() {} unsigned getSparseSetIndex() const { return VirtReg.virtRegIndex(); } }; @@ -216,7 +217,7 @@ class RegAllocFastImpl { LiveRegMap LiveVirtRegs; /// Stores assigned virtual registers present in the bundle MI. - DenseMap BundleVirtRegsMap; + DenseMap BundleVirtRegsMap; DenseMap> LiveDbgValueMap; /// List of DBG_VALUE that we encountered without the vreg being assigned @@ -374,7 +375,8 @@ class RegAllocFastImpl { SmallSet &PrologLiveIns) const; void reloadAtBegin(MachineBasicBlock &MBB); - bool setPhysReg(MachineInstr &MI, MachineOperand &MO, MCPhysReg PhysReg); + bool setPhysReg(MachineInstr &MI, MachineOperand &MO, + const LiveReg &Assignment); Register traceCopies(Register VirtReg) const; Register traceCopyChain(Register Reg) const; @@ -1005,7 +1007,8 @@ void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) { MO.setSubReg(0); } MO.setReg(PhysReg); - MO.setIsRenamable(true); + if (!LRI->Error) +MO.setIsRenamable(true); } /// Variation of defineVirtReg() with special handling for livethrough regs @@ -1109,10 +1112,10 @@ bool RegAllocFastImpl::defineVirtReg(MachineInstr &MI, unsigned OpNum, LRI->Reloaded = false; } if (MI.getOpcode() == TargetOpcode::BUNDLE) { -BundleVirtRegsMap[VirtReg] = PhysReg; +BundleVirtRegsMap[VirtReg] = *LRI; } markRegUsedInInstr(PhysReg); - return setPhysReg(MI, MO, PhysReg); + return setPhysReg(MI, MO, *LRI); } /// Allocates a register for a VirtReg use. @@ -1158,10 +1161,10 @@ bool RegAllocFastImpl::useVirtReg(MachineInstr &MI, MachineOperand &MO, LRI->LastUse = &MI; if (MI.getOpcode() == TargetOpcode::BUNDLE) { -BundleVirtRegsMap[VirtReg] = LRI->PhysReg; +BundleVirtRegsMap[VirtReg] = *LRI; } markRegUsedInInstr(LRI->PhysReg); - return setPhysReg(MI, MO, LRI->PhysReg); + return setPhysReg(MI, MO, *LRI); } /// Query a physical register to use as a filler in contexts where the @@ -1215,16 +1218,27 @@ MCPhysReg RegAllocFastImpl::getErrorAssignment(const LiveReg &LR, /// Changes operand OpNum in MI the refer the PhysReg, considering subregs. /// \return true if MI's MachineOperands were re-arranged/invalidated. bool RegAllocFastImpl::setPhysReg(MachineInstr &MI, MachineOperand &MO, - MCPhysReg PhysReg) { + const LiveReg &Assignment) { + MCPhysReg PhysReg = Assignment.PhysReg; + assert(PhysReg && "assignments should always be to a valid physreg"); + + if (LLVM_UNLIKELY(Assignment.Error)) { +// Make sure we don't set renamable in error scenarios, as we may have +// assigned to a reserved register. +if (MO.isUse()) + MO.setIsUndef(true); + } + if (!MO.getSubReg()) { MO.setReg(PhysReg); -MO.setIsRenamable(true); +MO.setIsRenamable(!Assignment.Error); return false; } // Handle subregister index. - MO.setReg(PhysReg ? TRI->getSubReg(PhysReg, MO.getSubReg()) : MCRegister()); - MO.setIsRenamable(true); + MO.setReg(TRI->getSubReg(PhysReg, MO.getSubReg())); + MO.setIsRenamable(!Assignment.Error); + // Note: We leave the subreg number around a little longer in case of defs. // This is so that the register freeing logic in allocateInstruction can still // recognize this as subregister defs. The code there will clear the number. @@ -1706,7 +1720,7 @@ void RegAllocFastImpl::handleDebugValue(MachineInstr &MI) { if (LRI != LiveVirtRegs.end() && LRI->PhysReg) { // Update every use of Reg within MI. for (auto &RegMO : DbgOps) -setPhysReg(MI, *RegMO, LRI->PhysReg); +setPhysReg(MI, *RegMO, *LRI); } else { DanglingDbgValues[Reg].push_back(&MI); } @@ -1729,8 +1743,7 @@ void RegAllocFastImpl::handleBundle(MachineInstr &MI) { if (!Reg.isVirtual() || !shouldAllocateRegister(Reg)) continue; - DenseMap::iterator DI; - DI = BundleVirtRegsMap.find(Reg); + DenseMap::iterator DI = BundleVirtRegsMap.find(Reg); assert(DI != BundleVirtRegsMap