Skip to content

Commit 5cb20ef

Browse files
committed
[InstCombine] Make indexed compare fold opaque ptr compatible
Rather than relying on pointer type equality (which, for a change, is silently incorrect with opaque pointers) check that the GEP source element types match.
1 parent 4c8174f commit 5cb20ef

File tree

2 files changed

+66
-14
lines changed

2 files changed

+66
-14
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ static Value *evaluateGEPOffsetExpression(User *GEP, InstCombinerImpl &IC,
502502
/// Returns true if we can rewrite Start as a GEP with pointer Base
503503
/// and some integer offset. The nodes that need to be re-written
504504
/// for this transformation will be added to Explored.
505-
static bool canRewriteGEPAsOffset(Value *Start, Value *Base,
505+
static bool canRewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
506506
const DataLayout &DL,
507507
SetVector<Value *> &Explored) {
508508
SmallVector<Value *, 16> WorkList(1, Start);
@@ -550,7 +550,7 @@ static bool canRewriteGEPAsOffset(Value *Start, Value *Base,
550550
// the original pointer type. We could handle more cases in the
551551
// future.
552552
if (GEP->getNumIndices() != 1 || !GEP->isInBounds() ||
553-
GEP->getType() != Start->getType())
553+
GEP->getSourceElementType() != ElemTy)
554554
return false;
555555

556556
if (Explored.count(GEP->getOperand(0)) == 0)
@@ -626,7 +626,7 @@ static void setInsertionPoint(IRBuilder<> &Builder, Value *V,
626626

627627
/// Returns a re-written value of Start as an indexed GEP using Base as a
628628
/// pointer.
629-
static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
629+
static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
630630
const DataLayout &DL,
631631
SetVector<Value *> &Explored) {
632632
// Perform all the substitutions. This is a bit tricky because we can
@@ -728,8 +728,7 @@ static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
728728
Start->getName() + "to.ptr");
729729

730730
Value *GEP = Builder.CreateInBoundsGEP(
731-
Start->getType()->getPointerElementType(), NewBase,
732-
makeArrayRef(NewInsts[Val]), Val->getName() + ".ptr");
731+
ElemTy, NewBase, makeArrayRef(NewInsts[Val]), Val->getName() + ".ptr");
733732

734733
if (!Val->getType()->isPointerTy()) {
735734
Value *Cast = Builder.CreatePointerCast(GEP, Val->getType(),
@@ -746,7 +745,7 @@ static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
746745
/// the input Value as a constant indexed GEP. Returns a pair containing
747746
/// the GEPs Pointer and Index.
748747
static std::pair<Value *, Value *>
749-
getAsConstantIndexedAddress(Value *V, const DataLayout &DL) {
748+
getAsConstantIndexedAddress(Type *ElemTy, Value *V, const DataLayout &DL) {
750749
Type *IndexType = IntegerType::get(V->getContext(),
751750
DL.getIndexTypeSizeInBits(V->getType()));
752751

@@ -758,7 +757,7 @@ getAsConstantIndexedAddress(Value *V, const DataLayout &DL) {
758757
if (!GEP->isInBounds())
759758
break;
760759
if (GEP->hasAllConstantIndices() && GEP->getNumIndices() == 1 &&
761-
GEP->getType() == V->getType()) {
760+
GEP->getSourceElementType() == ElemTy) {
762761
V = GEP->getOperand(0);
763762
Constant *GEPIndex = static_cast<Constant *>(GEP->getOperand(1));
764763
Index = ConstantExpr::getAdd(
@@ -797,17 +796,14 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
797796
if (!GEPLHS->hasAllConstantIndices())
798797
return nullptr;
799798

800-
// Make sure the pointers have the same type.
801-
if (GEPLHS->getType() != RHS->getType())
802-
return nullptr;
803-
799+
Type *ElemTy = GEPLHS->getSourceElementType();
804800
Value *PtrBase, *Index;
805-
std::tie(PtrBase, Index) = getAsConstantIndexedAddress(GEPLHS, DL);
801+
std::tie(PtrBase, Index) = getAsConstantIndexedAddress(ElemTy, GEPLHS, DL);
806802

807803
// The set of nodes that will take part in this transformation.
808804
SetVector<Value *> Nodes;
809805

810-
if (!canRewriteGEPAsOffset(RHS, PtrBase, DL, Nodes))
806+
if (!canRewriteGEPAsOffset(ElemTy, RHS, PtrBase, DL, Nodes))
811807
return nullptr;
812808

813809
// We know we can re-write this as
@@ -816,7 +812,7 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
816812
// can't have overflow on either side. We can therefore re-write
817813
// this as:
818814
// OFFSET1 cmp OFFSET2
819-
Value *NewRHS = rewriteGEPAsOffset(RHS, PtrBase, DL, Nodes);
815+
Value *NewRHS = rewriteGEPAsOffset(ElemTy, RHS, PtrBase, DL, Nodes);
820816

821817
// RewriteGEPAsOffset has replaced RHS and all of its uses with a re-written
822818
// GEP having PtrBase as the pointer base, and has returned in NewRHS the

llvm/test/Transforms/InstCombine/indexed-gep-compares.ll

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,63 @@ bb:
2929

3030
bb2:
3131
ret i32* %RHS
32+
}
33+
34+
define ptr @test1_opaque_ptr(ptr %A, i32 %Offset) {
35+
; CHECK-LABEL: @test1_opaque_ptr(
36+
; CHECK-NEXT: entry:
37+
; CHECK-NEXT: br label [[BB:%.*]]
38+
; CHECK: bb:
39+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
40+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
41+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
42+
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
43+
; CHECK: bb2:
44+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[RHS_IDX]]
45+
; CHECK-NEXT: ret ptr [[RHS_PTR]]
46+
;
47+
entry:
48+
%tmp = getelementptr inbounds i32, ptr %A, i32 %Offset
49+
br label %bb
50+
51+
bb:
52+
%RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
53+
%LHS = getelementptr inbounds i32, ptr %A, i32 100
54+
%RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
55+
%cond = icmp ult ptr %LHS, %RHS
56+
br i1 %cond, label %bb2, label %bb
3257

58+
bb2:
59+
ret ptr %RHS
60+
}
61+
62+
define ptr @test_opaque_ptr_different_types(ptr %A, i32 %Offset) {
63+
; CHECK-LABEL: @test_opaque_ptr_different_types(
64+
; CHECK-NEXT: entry:
65+
; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[OFFSET:%.*]]
66+
; CHECK-NEXT: br label [[BB:%.*]]
67+
; CHECK: bb:
68+
; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
69+
; CHECK-NEXT: [[LHS:%.*]] = getelementptr inbounds i64, ptr [[A]], i32 100
70+
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds i32, ptr [[RHS]], i32 1
71+
; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
72+
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
73+
; CHECK: bb2:
74+
; CHECK-NEXT: ret ptr [[RHS]]
75+
;
76+
entry:
77+
%tmp = getelementptr inbounds i32, ptr %A, i32 %Offset
78+
br label %bb
79+
80+
bb:
81+
%RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
82+
%LHS = getelementptr inbounds i64, ptr %A, i32 100
83+
%RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
84+
%cond = icmp ult ptr %LHS, %RHS
85+
br i1 %cond, label %bb2, label %bb
86+
87+
bb2:
88+
ret ptr %RHS
3389
}
3490

3591
define i32 *@test2(i32 %A, i32 %Offset) {

0 commit comments

Comments
 (0)