From cbf36e236ea917e5635f3de0c22a3c4ac62837be Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 11 Sep 2025 10:00:47 +0100 Subject: [PATCH 1/3] [VPlan/PatternMatch] Fix m_GetElementPtr (NFC) The m_GetElementPtr matcher is incorrect and incomplete. Fix it to match all possible GEPs to avoid misleading users. It currently just has one use, and the change is non-functional for that use. --- llvm/lib/Transforms/Vectorize/VPlan.h | 3 +++ .../Transforms/Vectorize/VPlanPatternMatch.h | 26 +++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 53291a931530f..db0f6dea254e8 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1799,6 +1799,9 @@ class LLVM_ABI_FOR_TEST VPWidenGEPRecipe : public VPRecipeWithIRFlags { VP_CLASSOF_IMPL(VPDef::VPWidenGEPSC) + /// This recipe generates a GEP instruction. + unsigned getOpcode() const { return Instruction::GetElementPtr; } + /// Generate the gep nodes. void execute(VPTransformState &State) override; diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h index 109156c1469c5..14ade616b9831 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h +++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h @@ -252,10 +252,10 @@ struct Recipe_match { static bool matchRecipeAndOpcode(const VPRecipeBase *R) { auto *DefR = dyn_cast(R); // Check for recipes that do not have opcodes. - if constexpr (std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value) + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) return DefR; else return DefR && DefR->getOpcode() == Opcode; @@ -524,15 +524,25 @@ m_SpecificCmp(CmpPredicate MatchPred, const Op0_t &Op0, const Op1_t &Op1) { } template -using GEPLikeRecipe_match = +using GEPLikeRecipe_match = match_combine_or< Recipe_match, Instruction::GetElementPtr, - /*Commutative*/ false, VPWidenRecipe, VPReplicateRecipe, - VPWidenGEPRecipe, VPInstruction>; + /*Commutative*/ false, VPReplicateRecipe, VPWidenGEPRecipe, + VPVectorPointerRecipe>, + match_combine_or< + VPInstruction_match, + VPInstruction_match>>; template inline GEPLikeRecipe_match m_GetElementPtr(const Op0_t &Op0, const Op1_t &Op1) { - return GEPLikeRecipe_match(Op0, Op1); + return m_CombineOr( + Recipe_match, Instruction::GetElementPtr, + /*Commutative*/ false, VPReplicateRecipe, VPWidenGEPRecipe, + VPVectorPointerRecipe>(Op0, Op1), + m_CombineOr( + VPInstruction_match(Op0, Op1), + VPInstruction_match(Op0, + Op1))); } template From 440600d80ce84280ea1e1fd88fd6433d70992e5b Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 11 Sep 2025 10:17:39 +0100 Subject: [PATCH 2/3] [VPlan/PatternMatch] Strip VectorPointerRecipe --- llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h index 14ade616b9831..b3735786585cf 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h +++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h @@ -254,8 +254,7 @@ struct Recipe_match { // Check for recipes that do not have opcodes. if constexpr (std::is_same_v || std::is_same_v || - std::is_same_v || - std::is_same_v) + std::is_same_v) return DefR; else return DefR && DefR->getOpcode() == Opcode; @@ -526,8 +525,7 @@ m_SpecificCmp(CmpPredicate MatchPred, const Op0_t &Op0, const Op1_t &Op1) { template using GEPLikeRecipe_match = match_combine_or< Recipe_match, Instruction::GetElementPtr, - /*Commutative*/ false, VPReplicateRecipe, VPWidenGEPRecipe, - VPVectorPointerRecipe>, + /*Commutative*/ false, VPReplicateRecipe, VPWidenGEPRecipe>, match_combine_or< VPInstruction_match, VPInstruction_match>>; @@ -537,8 +535,8 @@ inline GEPLikeRecipe_match m_GetElementPtr(const Op0_t &Op0, const Op1_t &Op1) { return m_CombineOr( Recipe_match, Instruction::GetElementPtr, - /*Commutative*/ false, VPReplicateRecipe, VPWidenGEPRecipe, - VPVectorPointerRecipe>(Op0, Op1), + /*Commutative*/ false, VPReplicateRecipe, VPWidenGEPRecipe>( + Op0, Op1), m_CombineOr( VPInstruction_match(Op0, Op1), VPInstruction_match(Op0, From e8a9716fb9514b6945f1b6728cb6d6d8f5b0bd91 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Mon, 15 Sep 2025 11:24:16 +0100 Subject: [PATCH 3/3] [VPlan] Add unit-test --- .../Vectorize/VPlanPatternMatchTest.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/llvm/unittests/Transforms/Vectorize/VPlanPatternMatchTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanPatternMatchTest.cpp index e38b4fad80b0e..582094bed3ef7 100644 --- a/llvm/unittests/Transforms/Vectorize/VPlanPatternMatchTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanPatternMatchTest.cpp @@ -51,5 +51,29 @@ TEST_F(VPPatternMatchTest, ScalarIVSteps) { m_SpecificInt(2), m_Specific(VF)))); } +TEST_F(VPPatternMatchTest, GetElementPtr) { + VPlan &Plan = getPlan(); + VPBasicBlock *VPBB = Plan.createVPBasicBlock("entry"); + VPBuilder Builder(VPBB); + + IntegerType *I64Ty = IntegerType::get(C, 64); + VPValue *One = Plan.getOrAddLiveIn(ConstantInt::get(I64Ty, 1)); + VPValue *Two = Plan.getOrAddLiveIn(ConstantInt::get(I64Ty, 2)); + VPValue *Ptr = + Plan.getOrAddLiveIn(Constant::getNullValue(PointerType::get(C, 0))); + + VPInstruction *PtrAdd = Builder.createPtrAdd(Ptr, One); + VPInstruction *WidePtrAdd = Builder.createWidePtrAdd(Ptr, Two); + + using namespace VPlanPatternMatch; + ASSERT_TRUE( + match(PtrAdd, m_GetElementPtr(m_Specific(Ptr), m_SpecificInt(1)))); + ASSERT_FALSE( + match(PtrAdd, m_GetElementPtr(m_Specific(Ptr), m_SpecificInt(2)))); + ASSERT_TRUE( + match(WidePtrAdd, m_GetElementPtr(m_Specific(Ptr), m_SpecificInt(2)))); + ASSERT_FALSE( + match(WidePtrAdd, m_GetElementPtr(m_Specific(Ptr), m_SpecificInt(1)))); +} } // namespace } // namespace llvm