[llvm-branch-commits] [llvm] [IR] Account for byte width in m_PtrAdd (PR #106540)

Sergei Barannikov via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Feb 22 10:46:25 PST 2026


https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/106540

>From 9618de643a6c7f4bce3c3b23d08d0303acef4f4a Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Thu, 29 Aug 2024 00:54:20 +0300
Subject: [PATCH] [IR] Account for byte width in m_PtrAdd

The method has few uses yet, so just pass DL argument to it. The change
follows m_PtrToIntSameSize, and I don't see a better way of delivering
the byte width to the method.
---
 llvm/include/llvm/IR/PatternMatch.h           | 13 ++++++----
 llvm/lib/Analysis/InstructionSimplify.cpp     |  2 +-
 .../InstCombineSimplifyDemanded.cpp           |  7 +++---
 .../InstCombine/InstructionCombining.cpp      |  2 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp     |  5 ++--
 llvm/unittests/IR/PatternMatch.cpp            | 25 ++++++++++++++-----
 6 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index ee99d627dde5d..d22306e44e1be 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -2050,15 +2050,17 @@ struct m_SplatOrPoisonMask {
 };
 
 template <typename PointerOpTy, typename OffsetOpTy> struct PtrAdd_match {
+  const DataLayout &DL;
   PointerOpTy PointerOp;
   OffsetOpTy OffsetOp;
 
-  PtrAdd_match(const PointerOpTy &PointerOp, const OffsetOpTy &OffsetOp)
-      : PointerOp(PointerOp), OffsetOp(OffsetOp) {}
+  PtrAdd_match(const DataLayout &DL, const PointerOpTy &PointerOp,
+               const OffsetOpTy &OffsetOp)
+      : DL(DL), PointerOp(PointerOp), OffsetOp(OffsetOp) {}
 
   template <typename OpTy> bool match(OpTy *V) const {
     auto *GEP = dyn_cast<GEPOperator>(V);
-    return GEP && GEP->getSourceElementType()->isIntegerTy(8) &&
+    return GEP && GEP->getSourceElementType()->isIntegerTy(DL.getByteWidth()) &&
            PointerOp.match(GEP->getPointerOperand()) &&
            OffsetOp.match(GEP->idx_begin()->get());
   }
@@ -2100,8 +2102,9 @@ inline auto m_GEP(const OperandTypes &...Ops) {
 /// Matches GEP with i8 source element type
 template <typename PointerOpTy, typename OffsetOpTy>
 inline PtrAdd_match<PointerOpTy, OffsetOpTy>
-m_PtrAdd(const PointerOpTy &PointerOp, const OffsetOpTy &OffsetOp) {
-  return PtrAdd_match<PointerOpTy, OffsetOpTy>(PointerOp, OffsetOp);
+m_PtrAdd(const DataLayout &DL, const PointerOpTy &PointerOp,
+         const OffsetOpTy &OffsetOp) {
+  return PtrAdd_match<PointerOpTy, OffsetOpTy>(DL, PointerOp, OffsetOp);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 3d5ee74c0e2e8..1a3c7b5b786ec 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -5620,7 +5620,7 @@ static Value *simplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty,
   Value *Ptr, *X;
   if ((CastOpc == Instruction::PtrToInt || CastOpc == Instruction::PtrToAddr) &&
       match(Op,
-            m_PtrAdd(m_Value(Ptr),
+            m_PtrAdd(Q.DL, m_Value(Ptr),
                      m_Sub(m_Value(X), m_PtrToIntOrAddr(m_Deferred(Ptr))))) &&
       X->getType() == Ty && Ty == Q.DL.getIndexType(Ptr->getType()))
     return X;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index bcc6e56059270..751629f25b934 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1071,9 +1071,10 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
         Value *InnerPtr;
         uint64_t GEPIndex;
         uint64_t PtrMaskImmediate;
-        if (match(I, m_Intrinsic<Intrinsic::ptrmask>(
-                         m_PtrAdd(m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
-                         m_ConstantInt(PtrMaskImmediate)))) {
+        if (match(I,
+                  m_Intrinsic<Intrinsic::ptrmask>(
+                      m_PtrAdd(DL, m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
+                      m_ConstantInt(PtrMaskImmediate)))) {
 
           LHSKnown = computeKnownBits(InnerPtr, I, Depth + 1);
           if (!LHSKnown.isZero()) {
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index c4beacdd12684..1513d8e6c5538 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2794,7 +2794,7 @@ static Instruction *canonicalizeGEPOfConstGEPI8(GetElementPtrInst &GEP,
   auto &DL = IC.getDataLayout();
   Value *Base;
   const APInt *C1;
-  if (!match(Src, m_PtrAdd(m_Value(Base), m_APInt(C1))))
+  if (!match(Src, m_PtrAdd(DL, m_Value(Base), m_APInt(C1))))
     return nullptr;
   Value *VarIndex;
   const APInt *C2;
diff --git a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
index c298daff30108..5b2b3b37f1a09 100644
--- a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
+++ b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
@@ -979,8 +979,9 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
   // offset from each is accumulated.
   Value *NewBase;
   const APInt *BaseOffset;
-  bool ExtractBase = match(GEP->getPointerOperand(),
-                           m_PtrAdd(m_Value(NewBase), m_APInt(BaseOffset)));
+  bool ExtractBase =
+      match(GEP->getPointerOperand(),
+            m_PtrAdd(*DL, m_Value(NewBase), m_APInt(BaseOffset)));
 
   unsigned IdxWidth = DL->getIndexTypeSizeInBits(GEP->getType());
   APInt BaseByteOffset =
diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp
index feb3973b47202..306ffce763ede 100644
--- a/llvm/unittests/IR/PatternMatch.cpp
+++ b/llvm/unittests/IR/PatternMatch.cpp
@@ -2599,26 +2599,39 @@ TEST_F(PatternMatchTest, ConstExpr) {
   EXPECT_TRUE(match(V, m_ConstantExpr()));
 }
 
-TEST_F(PatternMatchTest, PtrAdd) {
+// PatternMatchTest parametrized by byte width.
+class PatternMatchByteParamTest
+    : public PatternMatchTest,
+      public ::testing::WithParamInterface<unsigned> {
+public:
+  PatternMatchByteParamTest() {
+    M->setDataLayout("b:" + std::to_string(GetParam()));
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(ByteWidths, PatternMatchByteParamTest,
+                         ::testing::Values(8, 16, 32));
+
+TEST_P(PatternMatchByteParamTest, PtrAdd) {
+  const DataLayout &DL = M->getDataLayout();
   Type *PtrTy = PointerType::getUnqual(Ctx);
   Type *IdxTy = Type::getInt64Ty(Ctx);
   Constant *Null = Constant::getNullValue(PtrTy);
   Constant *Offset = ConstantInt::get(IdxTy, 42);
   Value *PtrAdd = IRB.CreatePtrAdd(Null, Offset);
   Value *OtherGEP = IRB.CreateGEP(IdxTy, Null, Offset);
-  Value *PtrAddConst =
-      ConstantExpr::getPtrAdd(M->getDataLayout(), Null, Offset);
+  Value *PtrAddConst = ConstantExpr::getPtrAdd(DL, Null, Offset);
 
   Value *A, *B;
-  EXPECT_TRUE(match(PtrAdd, m_PtrAdd(m_Value(A), m_Value(B))));
+  EXPECT_TRUE(match(PtrAdd, m_PtrAdd(DL, m_Value(A), m_Value(B))));
   EXPECT_EQ(A, Null);
   EXPECT_EQ(B, Offset);
 
-  EXPECT_TRUE(match(PtrAddConst, m_PtrAdd(m_Value(A), m_Value(B))));
+  EXPECT_TRUE(match(PtrAddConst, m_PtrAdd(DL, m_Value(A), m_Value(B))));
   EXPECT_EQ(A, Null);
   EXPECT_EQ(B, Offset);
 
-  EXPECT_FALSE(match(OtherGEP, m_PtrAdd(m_Value(A), m_Value(B))));
+  EXPECT_FALSE(match(OtherGEP, m_PtrAdd(DL, m_Value(A), m_Value(B))));
 }
 
 TEST_F(PatternMatchTest, ShiftOrSelf) {



More information about the llvm-branch-commits mailing list