[llvm] 7d850a0 - [InstCombine] Make indexed compare fold opaque ptr compatible
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 28 02:47:29 PST 2021
Author: Nikita Popov
Date: 2021-12-28T11:47:20+01:00
New Revision: 7d850a0c4d26591fadb26d82a8ffac530c217e9c
URL: https://github.com/llvm/llvm-project/commit/7d850a0c4d26591fadb26d82a8ffac530c217e9c
DIFF: https://github.com/llvm/llvm-project/commit/7d850a0c4d26591fadb26d82a8ffac530c217e9c.diff
LOG: [InstCombine] Make indexed compare fold opaque ptr compatible
We need to make sure that the GEP source element types match.
A caveat here is that the used GEP source element type can be
arbitrary if no offset is stripped from the original GEP -- the
transform is somewhat inconsistent in that it always starts from
a GEP, but might not actually look through it if it has multiple
indices.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/indexed-gep-compares.ll
llvm/test/Transforms/InstCombine/opaque-ptr.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 62a43b00773a..59e131bd3b6a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -503,7 +503,7 @@ static Value *evaluateGEPOffsetExpression(User *GEP, InstCombinerImpl &IC,
/// Returns true if we can rewrite Start as a GEP with pointer Base
/// and some integer offset. The nodes that need to be re-written
/// for this transformation will be added to Explored.
-static bool canRewriteGEPAsOffset(Value *Start, Value *Base,
+static bool canRewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
const DataLayout &DL,
SetVector<Value *> &Explored) {
SmallVector<Value *, 16> WorkList(1, Start);
@@ -551,7 +551,7 @@ static bool canRewriteGEPAsOffset(Value *Start, Value *Base,
// the original pointer type. We could handle more cases in the
// future.
if (GEP->getNumIndices() != 1 || !GEP->isInBounds() ||
- GEP->getType() != Start->getType())
+ GEP->getSourceElementType() != ElemTy)
return false;
if (!Explored.contains(GEP->getOperand(0)))
@@ -627,7 +627,7 @@ static void setInsertionPoint(IRBuilder<> &Builder, Value *V,
/// Returns a re-written value of Start as an indexed GEP using Base as a
/// pointer.
-static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
+static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
const DataLayout &DL,
SetVector<Value *> &Explored) {
// Perform all the substitutions. This is a bit tricky because we can
@@ -714,6 +714,8 @@ static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
}
}
+ PointerType *PtrTy =
+ ElemTy->getPointerTo(Start->getType()->getPointerAddressSpace());
for (Value *Val : Explored) {
if (Val == Base)
continue;
@@ -722,22 +724,14 @@ static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
// a GEP or a GEP + ptrtoint.
setInsertionPoint(Builder, Val, false);
- // If required, create an inttoptr instruction for Base.
- Value *NewBase = Base;
- if (!Base->getType()->isPointerTy())
- NewBase = Builder.CreateBitOrPointerCast(Base, Start->getType(),
- Start->getName() + "to.ptr");
-
- Value *GEP = Builder.CreateInBoundsGEP(
- Start->getType()->getPointerElementType(), NewBase,
- makeArrayRef(NewInsts[Val]), Val->getName() + ".ptr");
-
- if (!Val->getType()->isPointerTy()) {
- Value *Cast = Builder.CreatePointerCast(GEP, Val->getType(),
- Val->getName() + ".conv");
- GEP = Cast;
- }
- Val->replaceAllUsesWith(GEP);
+ // Cast base to the expected type.
+ Value *NewVal = Builder.CreateBitOrPointerCast(
+ Base, PtrTy, Start->getName() + "to.ptr");
+ NewVal = Builder.CreateInBoundsGEP(
+ ElemTy, NewVal, makeArrayRef(NewInsts[Val]), Val->getName() + ".ptr");
+ NewVal = Builder.CreateBitOrPointerCast(
+ NewVal, Val->getType(), Val->getName() + ".conv");
+ Val->replaceAllUsesWith(NewVal);
}
return NewInsts[Start];
@@ -747,7 +741,7 @@ static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
/// the input Value as a constant indexed GEP. Returns a pair containing
/// the GEPs Pointer and Index.
static std::pair<Value *, Value *>
-getAsConstantIndexedAddress(Value *V, const DataLayout &DL) {
+getAsConstantIndexedAddress(Type *ElemTy, Value *V, const DataLayout &DL) {
Type *IndexType = IntegerType::get(V->getContext(),
DL.getIndexTypeSizeInBits(V->getType()));
@@ -759,7 +753,7 @@ getAsConstantIndexedAddress(Value *V, const DataLayout &DL) {
if (!GEP->isInBounds())
break;
if (GEP->hasAllConstantIndices() && GEP->getNumIndices() == 1 &&
- GEP->getType() == V->getType()) {
+ GEP->getSourceElementType() == ElemTy) {
V = GEP->getOperand(0);
Constant *GEPIndex = static_cast<Constant *>(GEP->getOperand(1));
Index = ConstantExpr::getAdd(
@@ -798,17 +792,14 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
if (!GEPLHS->hasAllConstantIndices())
return nullptr;
- // Make sure the pointers have the same type.
- if (GEPLHS->getType() != RHS->getType())
- return nullptr;
-
+ Type *ElemTy = GEPLHS->getSourceElementType();
Value *PtrBase, *Index;
- std::tie(PtrBase, Index) = getAsConstantIndexedAddress(GEPLHS, DL);
+ std::tie(PtrBase, Index) = getAsConstantIndexedAddress(ElemTy, GEPLHS, DL);
// The set of nodes that will take part in this transformation.
SetVector<Value *> Nodes;
- if (!canRewriteGEPAsOffset(RHS, PtrBase, DL, Nodes))
+ if (!canRewriteGEPAsOffset(ElemTy, RHS, PtrBase, DL, Nodes))
return nullptr;
// We know we can re-write this as
@@ -817,7 +808,7 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
// can't have overflow on either side. We can therefore re-write
// this as:
// OFFSET1 cmp OFFSET2
- Value *NewRHS = rewriteGEPAsOffset(RHS, PtrBase, DL, Nodes);
+ Value *NewRHS = rewriteGEPAsOffset(ElemTy, RHS, PtrBase, DL, Nodes);
// RewriteGEPAsOffset has replaced RHS and all of its uses with a re-written
// GEP having PtrBase as the pointer base, and has returned in NewRHS the
diff --git a/llvm/test/Transforms/InstCombine/indexed-gep-compares.ll b/llvm/test/Transforms/InstCombine/indexed-gep-compares.ll
index b8180603f11f..c00fd5be06e4 100644
--- a/llvm/test/Transforms/InstCombine/indexed-gep-compares.ll
+++ b/llvm/test/Transforms/InstCombine/indexed-gep-compares.ll
@@ -300,3 +300,28 @@ entry:
%cmp = icmp eq i32** %gepi32, %cast
ret i1 %cmp
}
+
+define void @test_zero_offset_cycle({ i64, i64 }* %arg) {
+; CHECK-LABEL: @test_zero_offset_cycle(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: br i1 true, label [[LOOP]], label [[LOOP_CONT:%.*]]
+; CHECK: loop.cont:
+; CHECK-NEXT: br label [[LOOP]]
+;
+entry:
+ %gep = getelementptr inbounds { i64, i64 }, { i64, i64 }* %arg, i32 0, i32 1
+ %gep.int = ptrtoint i64* %gep to i32
+ br label %loop
+
+loop:
+ %phi = phi i32 [ %gep.int, %entry ], [ %gep.int2, %loop.cont ], [ %phi, %loop ]
+ %phi.ptr = inttoptr i32 %phi to i64*
+ %cmp = icmp eq i64* %gep, %phi.ptr
+ br i1 %cmp, label %loop, label %loop.cont
+
+loop.cont:
+ %gep.int2 = ptrtoint i64* %gep to i32
+ br label %loop
+}
diff --git a/llvm/test/Transforms/InstCombine/opaque-ptr.ll b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
index 4ebf68f918e1..035b50588f54 100644
--- a/llvm/test/Transforms/InstCombine/opaque-ptr.ll
+++ b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
@@ -206,3 +206,60 @@ define i1 @compare_geps_same_indices_
diff erent_types(ptr %a, ptr %b, i64 %idx) {
%c = icmp eq ptr %a2, %b2
ret i1 %c
}
+
+define ptr @indexed_compare(ptr %A, i64 %offset) {
+; CHECK-LABEL: @indexed_compare(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[BB:%.*]]
+; CHECK: bb:
+; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i64 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[RHS_ADD]] = add nsw i64 [[RHS_IDX]], 1
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[RHS_IDX]], 100
+; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
+; CHECK: bb2:
+; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[RHS_IDX]]
+; CHECK-NEXT: ret ptr [[RHS_PTR]]
+;
+entry:
+ %tmp = getelementptr inbounds i32, ptr %A, i64 %offset
+ br label %bb
+
+bb:
+ %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
+ %LHS = getelementptr inbounds i32, ptr %A, i32 100
+ %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
+ %cond = icmp ult ptr %LHS, %RHS
+ br i1 %cond, label %bb2, label %bb
+
+bb2:
+ ret ptr %RHS
+}
+
+define ptr @indexed_compare_
diff erent_types(ptr %A, i64 %offset) {
+; CHECK-LABEL: @indexed_compare_
diff erent_types(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[OFFSET:%.*]]
+; CHECK-NEXT: br label [[BB:%.*]]
+; CHECK: bb:
+; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[LHS:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 100
+; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds i32, ptr [[RHS]], i64 1
+; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
+; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
+; CHECK: bb2:
+; CHECK-NEXT: ret ptr [[RHS]]
+;
+entry:
+ %tmp = getelementptr inbounds i32, ptr %A, i64 %offset
+ br label %bb
+
+bb:
+ %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
+ %LHS = getelementptr inbounds i64, ptr %A, i32 100
+ %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
+ %cond = icmp ult ptr %LHS, %RHS
+ br i1 %cond, label %bb2, label %bb
+
+bb2:
+ ret ptr %RHS
+}
More information about the llvm-commits
mailing list