Skip to content

Commit 0008af8

Browse files
authored
[SROA] Allow as zext<i1> index when unfolding GEP select (#146929)
A zero-extension from an i1 is equivalent to a select with constant 0 and 1 values. Add this case when rewriting gep(select) -> select(gep) to expose more opportunities for SROA.
1 parent a4f31cc commit 0008af8

File tree

2 files changed

+65
-7
lines changed

2 files changed

+65
-7
lines changed

llvm/lib/Transforms/Scalar/SROA.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4070,18 +4070,27 @@ class AggLoadStoreRewriter : public InstVisitor<AggLoadStoreRewriter, bool> {
40704070
// => select cond, gep(ptr1, idx), gep(ptr2, idx)
40714071
// and gep ptr, (select cond, idx1, idx2)
40724072
// => select cond, gep(ptr, idx1), gep(ptr, idx2)
4073+
// We also allow for i1 zext indices, which are equivalent to selects.
40734074
bool unfoldGEPSelect(GetElementPtrInst &GEPI) {
40744075
// Check whether the GEP has exactly one select operand and all indices
40754076
// will become constant after the transform.
4076-
SelectInst *Sel = dyn_cast<SelectInst>(GEPI.getPointerOperand());
4077+
Instruction *Sel = dyn_cast<SelectInst>(GEPI.getPointerOperand());
40774078
for (Value *Op : GEPI.indices()) {
40784079
if (auto *SI = dyn_cast<SelectInst>(Op)) {
40794080
if (Sel)
40804081
return false;
40814082

40824083
Sel = SI;
4083-
if (!isa<ConstantInt>(Sel->getTrueValue()) ||
4084-
!isa<ConstantInt>(Sel->getFalseValue()))
4084+
if (!isa<ConstantInt>(SI->getTrueValue()) ||
4085+
!isa<ConstantInt>(SI->getFalseValue()))
4086+
return false;
4087+
continue;
4088+
}
4089+
if (auto *ZI = dyn_cast<ZExtInst>(Op)) {
4090+
if (Sel)
4091+
return false;
4092+
Sel = ZI;
4093+
if (!ZI->getSrcTy()->isIntegerTy(1))
40854094
return false;
40864095
continue;
40874096
}
@@ -4107,8 +4116,16 @@ class AggLoadStoreRewriter : public InstVisitor<AggLoadStoreRewriter, bool> {
41074116
return NewOps;
41084117
};
41094118

4110-
Value *True = Sel->getTrueValue();
4111-
Value *False = Sel->getFalseValue();
4119+
Value *Cond, *True, *False;
4120+
if (auto *SI = dyn_cast<SelectInst>(Sel)) {
4121+
Cond = SI->getCondition();
4122+
True = SI->getTrueValue();
4123+
False = SI->getFalseValue();
4124+
} else {
4125+
Cond = Sel->getOperand(0);
4126+
True = ConstantInt::get(Sel->getType(), 1);
4127+
False = ConstantInt::get(Sel->getType(), 0);
4128+
}
41124129
SmallVector<Value *> TrueOps = GetNewOps(True);
41134130
SmallVector<Value *> FalseOps = GetNewOps(False);
41144131

@@ -4123,8 +4140,8 @@ class AggLoadStoreRewriter : public InstVisitor<AggLoadStoreRewriter, bool> {
41234140
IRB.CreateGEP(Ty, FalseOps[0], ArrayRef(FalseOps).drop_front(),
41244141
False->getName() + ".sroa.gep", NW);
41254142

4126-
Value *NSel = IRB.CreateSelect(Sel->getCondition(), NTrue, NFalse,
4127-
Sel->getName() + ".sroa.sel");
4143+
Value *NSel =
4144+
IRB.CreateSelect(Cond, NTrue, NFalse, Sel->getName() + ".sroa.sel");
41284145
Visited.erase(&GEPI);
41294146
GEPI.replaceAllUsesWith(NSel);
41304147
GEPI.eraseFromParent();

llvm/test/Transforms/SROA/select-gep.ll

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,47 @@ define i32 @test_select_idx_mem2reg(i1 %c) {
201201
ret i32 %res
202202
}
203203

204+
; Test gep with a select-like zext index unfolding on an alloca that is
205+
; splittable and promotable.
206+
define i64 @test_select_like_zext_idx_mem2reg(i1 %c) {
207+
; CHECK-LABEL: @test_select_like_zext_idx_mem2reg(
208+
; CHECK-NEXT: [[IDX:%.*]] = zext i1 [[C:%.*]] to i64
209+
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C]], i64 2, i64 1
210+
; CHECK-NEXT: ret i64 [[RES]]
211+
;
212+
%alloca = alloca [2 x i64], align 8
213+
store i64 1, ptr %alloca
214+
%gep1 = getelementptr inbounds i64, ptr %alloca, i64 1
215+
store i64 2, ptr %gep1
216+
%idx = zext i1 %c to i64
217+
%gep2 = getelementptr inbounds i64, ptr %alloca, i64 %idx
218+
%res = load i64, ptr %gep2
219+
ret i64 %res
220+
}
221+
222+
; Test gep with a zext index that is not equivalent to a select. No unfolding
223+
; or promotion should take place.
224+
define i64 @test_zext_unlike_select_idx_mem2reg(i8 %c) {
225+
; CHECK-LABEL: @test_zext_unlike_select_idx_mem2reg(
226+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [2 x i64], align 8
227+
; CHECK-NEXT: store i64 1, ptr [[ALLOCA]], align 4
228+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 1
229+
; CHECK-NEXT: store i64 2, ptr [[GEP1]], align 4
230+
; CHECK-NEXT: [[IDX:%.*]] = zext i8 [[C:%.*]] to i64
231+
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 [[IDX]]
232+
; CHECK-NEXT: [[RES:%.*]] = load i64, ptr [[GEP2]], align 4
233+
; CHECK-NEXT: ret i64 [[RES]]
234+
;
235+
%alloca = alloca [2 x i64], align 8
236+
store i64 1, ptr %alloca
237+
%gep1 = getelementptr inbounds i64, ptr %alloca, i64 1
238+
store i64 2, ptr %gep1
239+
%idx = zext i8 %c to i64
240+
%gep2 = getelementptr inbounds i64, ptr %alloca, i64 %idx
241+
%res = load i64, ptr %gep2
242+
ret i64 %res
243+
}
244+
204245
; Test gep of index select unfolding on an alloca that escaped, and as such
205246
; is not splittable or promotable.
206247
; FIXME: Ideally, no transform would take place in this case.

0 commit comments

Comments
 (0)