Skip to content

Commit 9646a71

Browse files
davemgreenkrishna2803
authored andcommitted
[InstCombine] Make foldCmpLoadFromIndexedGlobal more resilient to non-array geps. (llvm#150639)
My understanding is that gep [n x i8] and gep i8 can be treated equivalently - the array type conveys no extra information and could be removed. This goes through foldCmpLoadFromIndexedGlobal and tries to make it work for non-array gep types, so long as the index type still matches the array being loaded.
1 parent e1291d8 commit 9646a71

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,16 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
113113
LoadInst *LI, GetElementPtrInst *GEP, GlobalVariable *GV, CmpInst &ICI,
114114
ConstantInt *AndCst) {
115115
if (LI->isVolatile() || LI->getType() != GEP->getResultElementType() ||
116-
GV->getValueType() != GEP->getSourceElementType() || !GV->isConstant() ||
116+
!GV->getValueType()->isArrayTy() || !GV->isConstant() ||
117117
!GV->hasDefinitiveInitializer())
118118
return nullptr;
119119

120+
Type *GEPSrcEltTy = GEP->getSourceElementType();
121+
if (GEPSrcEltTy->isArrayTy())
122+
GEPSrcEltTy = GEPSrcEltTy->getArrayElementType();
123+
if (GV->getValueType()->getArrayElementType() != GEPSrcEltTy)
124+
return nullptr;
125+
120126
Constant *Init = GV->getInitializer();
121127
if (!isa<ConstantArray>(Init) && !isa<ConstantDataArray>(Init))
122128
return nullptr;
@@ -127,12 +133,19 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
127133
return nullptr;
128134

129135
// There are many forms of this optimization we can handle, for now, just do
130-
// the simple index into a single-dimensional array.
136+
// the simple index into a single-dimensional array or elements of equal size.
131137
//
132-
// Require: GEP GV, 0, i {{, constant indices}}
133-
if (GEP->getNumOperands() < 3 || !isa<ConstantInt>(GEP->getOperand(1)) ||
134-
!cast<ConstantInt>(GEP->getOperand(1))->isZero() ||
135-
isa<Constant>(GEP->getOperand(2)))
138+
// Require: GEP [n x i8] GV, 0, Idx {{, constant indices}}
139+
// Or: GEP i8 GV, Idx
140+
141+
unsigned GEPIdxOp = 1;
142+
if (GEP->getSourceElementType()->isArrayTy()) {
143+
GEPIdxOp = 2;
144+
if (!match(GEP->getOperand(1), m_ZeroInt()))
145+
return nullptr;
146+
}
147+
if (GEP->getNumOperands() < GEPIdxOp + 1 ||
148+
isa<Constant>(GEP->getOperand(GEPIdxOp)))
136149
return nullptr;
137150

138151
// Check that indices after the variable are constants and in-range for the
@@ -141,7 +154,7 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
141154
SmallVector<unsigned, 4> LaterIndices;
142155

143156
Type *EltTy = Init->getType()->getArrayElementType();
144-
for (unsigned i = 3, e = GEP->getNumOperands(); i != e; ++i) {
157+
for (unsigned i = GEPIdxOp + 1, e = GEP->getNumOperands(); i != e; ++i) {
145158
ConstantInt *Idx = dyn_cast<ConstantInt>(GEP->getOperand(i));
146159
if (!Idx)
147160
return nullptr; // Variable index.
@@ -163,7 +176,7 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
163176
LaterIndices.push_back(IdxVal);
164177
}
165178

166-
Value *Idx = GEP->getOperand(2);
179+
Value *Idx = GEP->getOperand(GEPIdxOp);
167180
// If the index type is non-canonical, wait for it to be canonicalized.
168181
if (Idx->getType() != DL.getIndexType(GEP->getType()))
169182
return nullptr;

llvm/test/Transforms/InstCombine/load-cmp.ll

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ define i1 @test1_noinbounds_as1(i32 %x) {
6868
%q = load i16, ptr addrspace(1) %p
6969
%r = icmp eq i16 %q, 0
7070
ret i1 %r
71-
7271
}
7372

7473
define i1 @test1_noinbounds_as2(i64 %x) {
@@ -81,7 +80,17 @@ define i1 @test1_noinbounds_as2(i64 %x) {
8180
%q = load i16, ptr addrspace(2) %p
8281
%r = icmp eq i16 %q, 0
8382
ret i1 %r
83+
}
8484

85+
define i1 @test1_noarrayty(i32 %X) {
86+
; CHECK-LABEL: @test1_noarrayty(
87+
; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X:%.*]], 9
88+
; CHECK-NEXT: ret i1 [[R]]
89+
;
90+
%P = getelementptr inbounds i16, ptr @G16, i32 %X
91+
%Q = load i16, ptr %P
92+
%R = icmp eq i16 %Q, 0
93+
ret i1 %R
8594
}
8695

8796
define i1 @test2(i32 %X) {
@@ -104,7 +113,17 @@ define i1 @test3(i32 %X) {
104113
%Q = load double, ptr %P
105114
%R = fcmp oeq double %Q, 1.0
106115
ret i1 %R
116+
}
107117

118+
define i1 @test3_noarrayty(i32 %X) {
119+
; CHECK-LABEL: @test3_noarrayty(
120+
; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X:%.*]], 1
121+
; CHECK-NEXT: ret i1 [[R]]
122+
;
123+
%P = getelementptr inbounds double, ptr @GD, i32 %X
124+
%Q = load double, ptr %P
125+
%R = fcmp oeq double %Q, 1.0
126+
ret i1 %R
108127
}
109128

110129
define i1 @test4(i32 %X) {
@@ -325,6 +344,17 @@ define i1 @test10_struct_arr_noinbounds_i64(i64 %x) {
325344
ret i1 %r
326345
}
327346

347+
define i1 @test10_struct_arr_noarrayty(i32 %x) {
348+
; CHECK-LABEL: @test10_struct_arr_noarrayty(
349+
; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X:%.*]], 1
350+
; CHECK-NEXT: ret i1 [[R]]
351+
;
352+
%p = getelementptr inbounds %Foo, ptr @GStructArr, i32 %x, i32 2
353+
%q = load i32, ptr %p
354+
%r = icmp eq i32 %q, 9
355+
ret i1 %r
356+
}
357+
328358
@table = internal constant [2 x ptr] [ptr @g, ptr getelementptr (i8, ptr @g, i64 4)], align 16
329359
@g = external global [2 x i32]
330360

0 commit comments

Comments
 (0)