[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