[PATCH] D154010: [InstCombine] Canonicalize `getelementptr` patterns to `@llvm.ptrmask`

Noah Goldstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 28 14:18:10 PDT 2023


goldstein.w.n created this revision.
goldstein.w.n added reviewers: nikic, RKSimon.
Herald added subscribers: StephenFan, hiraditya, arichardson.
Herald added a project: All.
goldstein.w.n requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

`@llvm.ptrmask` is documented as being equivilent to:
`(getelementptr i8 Ptr, (sub (and (ptrtoint Ptr), Mask), (ptrtoint Ptr)))`

See: https://llvm.org/docs/LangRef.html#llvm-ptrmask-intrinsic

Complex: `(getelementptr i8 Ptr, (sub (and (ptrtoint Ptr), Mask), (ptrtoint Ptr)))`
is also equivilent to:
Simple: `(getelementptr i8 null, (and (ptrtoint Ptr), Mask))`

so add fold from complex -> simple -> `@llvm.ptrmask`

Proofs: https://alive2.llvm.org/ce/z/S6yEwr

Alive2 doesn't support `@llvm.ptrmask` so assuming that the documented
form MUST be equivilent, then the simple/complex forms verify.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154010

Files:
  llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
  llvm/test/Transforms/InstCombine/to-ptrmask.ll


Index: llvm/test/Transforms/InstCombine/to-ptrmask.ll
===================================================================
--- llvm/test/Transforms/InstCombine/to-ptrmask.ll
+++ llvm/test/Transforms/InstCombine/to-ptrmask.ll
@@ -94,8 +94,7 @@
 ; CHECK-SAME: (ptr [[P:%.*]], i64 [[M:%.*]]) {
 ; CHECK-NEXT:    [[PI:%.*]] = ptrtoint ptr [[P]] to i64
 ; CHECK-NEXT:    [[PI_M:%.*]] = xor i64 [[PI]], [[M]]
-; CHECK-NEXT:    [[PI_OFF:%.*]] = sub i64 [[PI_M]], [[PI]]
-; CHECK-NEXT:    [[PM:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[PI_OFF]]
+; CHECK-NEXT:    [[PM:%.*]] = getelementptr i8, ptr null, i64 [[PI_M]]
 ; CHECK-NEXT:    ret ptr [[PM]]
 ;
   %pi = ptrtoint ptr %p to i64
@@ -108,10 +107,7 @@
 define ptr @GEP_inttoptr_complex_pattern(ptr %p, i64 %m) {
 ; CHECK-LABEL: define ptr @GEP_inttoptr_complex_pattern
 ; CHECK-SAME: (ptr [[P:%.*]], i64 [[M:%.*]]) {
-; CHECK-NEXT:    [[PI:%.*]] = ptrtoint ptr [[P]] to i64
-; CHECK-NEXT:    [[PI_M:%.*]] = and i64 [[PI]], [[M]]
-; CHECK-NEXT:    [[PI_OFF:%.*]] = sub i64 [[PI_M]], [[PI]]
-; CHECK-NEXT:    [[PM:%.*]] = getelementptr i8, ptr [[P]], i64 [[PI_OFF]]
+; CHECK-NEXT:    [[PM:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 [[M]])
 ; CHECK-NEXT:    ret ptr [[PM]]
 ;
   %pi = ptrtoint ptr %p to i64
@@ -144,7 +140,7 @@
 ; CHECK-NEXT:    [[PI_M:%.*]] = and i64 [[PI]], [[M]]
 ; CHECK-NEXT:    [[PI_OFF:%.*]] = sub i64 [[PI_M]], [[PI]]
 ; CHECK-NEXT:    call void @use.i64(i64 [[PI_OFF]])
-; CHECK-NEXT:    [[PM:%.*]] = getelementptr i8, ptr [[P]], i64 [[PI_OFF]]
+; CHECK-NEXT:    [[PM:%.*]] = getelementptr i8, ptr null, i64 [[PI_M]]
 ; CHECK-NEXT:    ret ptr [[PM]]
 ;
   %pi = ptrtoint ptr %p to i64
@@ -176,9 +172,7 @@
 define ptr @GEP_inttoptr_simple_pattern(ptr %p, i64 %m) {
 ; CHECK-LABEL: define ptr @GEP_inttoptr_simple_pattern
 ; CHECK-SAME: (ptr [[P:%.*]], i64 [[M:%.*]]) {
-; CHECK-NEXT:    [[PI:%.*]] = ptrtoint ptr [[P]] to i64
-; CHECK-NEXT:    [[PI_M:%.*]] = and i64 [[PI]], [[M]]
-; CHECK-NEXT:    [[PM:%.*]] = getelementptr i8, ptr null, i64 [[PI_M]]
+; CHECK-NEXT:    [[PM:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 [[M]])
 ; CHECK-NEXT:    ret ptr [[PM]]
 ;
   %pi = ptrtoint ptr %p to i64
Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2224,6 +2224,37 @@
   if (Instruction *R = foldSelectGEP(GEP, Builder))
     return R;
 
+  // The definition of llvm.ptrmask(Ptr, Mask) is:
+  // (getelementptr i8, Ptr, (sub (and (ptrtoint Ptr), Mask), (ptrtoint Ptr)))
+  // or
+  // (getelementptr i8, null, (and (ptrtoint Ptr), Mask))
+  //
+  // llvm.ptrmask is preferable as it doesn't require transitioning from ptr ->
+  // int (and is generally easier to analyze).
+  // Don't do this for for vector of pointers, as llvm.ptrmask has weird
+  // definition for vectors.
+  if (GEPEltType->isIntegerTy(8) && GEP.getNumIndices() == 1) {
+    Value *Ptr, *Index;
+    // (getelementptr i8, Ptr, (sub Index, (ptrtoint Ptr)))
+    //     ->  (getelementptr i8, null, Index)
+    if (match(GEP.idx_begin()->get(),
+              m_Sub(m_Value(Index),
+                    m_PtrToInt(m_Specific(GEP.getPointerOperand())))))
+      return replaceInstUsesWith(
+          GEP, Builder.CreateGEP(
+                   GEP.getSourceElementType(),
+                   Constant::getNullValue(GEP.getPointerOperand()->getType()),
+                   Index));
+    Value *Mask;
+    // (getelementptr i8, null, (and (ptrtoint Ptr), Mask))
+    //      -> llvm.ptrmask(Ptr, Mask)
+    if (!GEPType->isVectorTy() && match(GEP.getPointerOperand(), m_Zero()) &&
+        match(GEP.idx_begin()->get(),
+              m_OneUse(m_c_And(m_PtrToInt(m_Value(Ptr)), m_Value(Mask)))))
+      return replaceInstUsesWith(
+          GEP, Builder.CreateIntrinsic(Ptr->getType(), Intrinsic::ptrmask,
+                                       {Ptr, Mask}));
+  }
   return nullptr;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D154010.535532.patch
Type: text/x-patch
Size: 4059 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230628/e13960dd/attachment.bin>


More information about the llvm-commits mailing list