Skip to content

Commit cc6fe76

Browse files
committed
[InstCombine] Add support for GEPs in simplifyNonNullOperand
1 parent a202d77 commit cc6fe76

File tree

8 files changed

+40
-23
lines changed

8 files changed

+40
-23
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3997,7 +3997,9 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) {
39973997
// Simplify the nonnull operand if the parameter is known to be nonnull.
39983998
// Otherwise, try to infer nonnull for it.
39993999
if (Call.paramHasNonNullAttr(ArgNo, /*AllowUndefOrPoison=*/true)) {
4000-
if (Value *Res = simplifyNonNullOperand(V)) {
4000+
if (Value *Res = simplifyNonNullOperand(
4001+
V, /*HasDereferenceable=*/Call.getParamDereferenceableBytes(
4002+
ArgNo) > 0)) {
40014003
replaceOperand(Call, ArgNo, Res);
40024004
Changed = true;
40034005
}

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,10 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
457457

458458
/// Simplify \p V given that it is known to be non-null.
459459
/// Returns the simplified value if possible, otherwise returns nullptr.
460-
Value *simplifyNonNullOperand(Value *V);
460+
/// If \p HasDereferenceable is true, the simplification will not perform
461+
/// same object checks.
462+
Value *simplifyNonNullOperand(Value *V, bool HasDereferenceable,
463+
unsigned Depth = 0);
461464

462465
public:
463466
/// Create and insert the idiom we use to indicate a block is unreachable

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -982,8 +982,9 @@ static bool canSimplifyNullLoadOrGEP(LoadInst &LI, Value *Op) {
982982
return false;
983983
}
984984

985-
/// TODO: Recursively simplify nonnull value to handle one-use inbounds GEPs.
986-
Value *InstCombinerImpl::simplifyNonNullOperand(Value *V) {
985+
Value *InstCombinerImpl::simplifyNonNullOperand(Value *V,
986+
bool HasDereferenceable,
987+
unsigned Depth) {
987988
if (auto *Sel = dyn_cast<SelectInst>(V)) {
988989
if (isa<ConstantPointerNull>(Sel->getOperand(1)))
989990
return Sel->getOperand(2);
@@ -992,6 +993,23 @@ Value *InstCombinerImpl::simplifyNonNullOperand(Value *V) {
992993
return Sel->getOperand(1);
993994
}
994995

996+
if (!V->hasOneUse())
997+
return nullptr;
998+
999+
if (Depth == 1)
1000+
return nullptr;
1001+
1002+
if (auto *GEP = dyn_cast<GetElementPtrInst>(V)) {
1003+
if (HasDereferenceable || GEP->isInBounds()) {
1004+
if (auto *Res = simplifyNonNullOperand(GEP->getPointerOperand(),
1005+
HasDereferenceable, Depth + 1)) {
1006+
replaceOperand(*GEP, 0, Res);
1007+
addToWorklist(GEP);
1008+
return nullptr;
1009+
}
1010+
}
1011+
}
1012+
9951013
return nullptr;
9961014
}
9971015

@@ -1076,7 +1094,7 @@ Instruction *InstCombinerImpl::visitLoadInst(LoadInst &LI) {
10761094
}
10771095

10781096
if (!NullPointerIsDefined(LI.getFunction(), LI.getPointerAddressSpace()))
1079-
if (Value *V = simplifyNonNullOperand(Op))
1097+
if (Value *V = simplifyNonNullOperand(Op, /*HasDereferenceable=*/true))
10801098
return replaceOperand(LI, 0, V);
10811099

10821100
return nullptr;
@@ -1444,7 +1462,7 @@ Instruction *InstCombinerImpl::visitStoreInst(StoreInst &SI) {
14441462
return eraseInstFromFunction(SI);
14451463

14461464
if (!NullPointerIsDefined(SI.getFunction(), SI.getPointerAddressSpace()))
1447-
if (Value *V = simplifyNonNullOperand(Ptr))
1465+
if (Value *V = simplifyNonNullOperand(Ptr, /*HasDereferenceable=*/true))
14481466
return replaceOperand(SI, 1, V);
14491467

14501468
return nullptr;

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3596,7 +3596,9 @@ Instruction *InstCombinerImpl::visitReturnInst(ReturnInst &RI) {
35963596
if (F->hasRetAttribute(Attribute::NonNull) ||
35973597
(F->getAttributes().getRetDereferenceableBytes() > 0 &&
35983598
!NullPointerIsDefined(F, RetTy->getPointerAddressSpace()))) {
3599-
if (Value *V = simplifyNonNullOperand(RetVal))
3599+
if (Value *V = simplifyNonNullOperand(
3600+
RetVal, /*HasDereferenceable=*/F->getAttributes()
3601+
.getRetDereferenceableBytes() > 0))
36003602
return replaceOperand(RI, 0, V);
36013603
}
36023604
}

llvm/test/Transforms/InstCombine/load.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,7 @@ define i4 @test_vector_load_i4_non_byte_sized() {
442442

443443
define i32 @load_select_with_null_gep(i1 %cond, ptr %p, i64 %off) {
444444
; CHECK-LABEL: @load_select_with_null_gep(
445-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], ptr [[P:%.*]], ptr null
446-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[SEL]], i64 [[OFF:%.*]]
445+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[SEL:%.*]], i64 [[OFF:%.*]]
447446
; CHECK-NEXT: [[RES:%.*]] = load i32, ptr [[GEP]], align 4
448447
; CHECK-NEXT: ret i32 [[RES]]
449448
;

llvm/test/Transforms/InstCombine/nonnull-select.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,7 @@ define void @all_nonnull_call_gep_multiuse(i1 %cond, ptr %p, i64 %off) {
131131

132132
define void @nonnull_call_gep_inbounds(i1 %cond, ptr %p, i64 %off) {
133133
; CHECK-LABEL: @nonnull_call_gep_inbounds(
134-
; CHECK-NEXT: [[PTR:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[P:%.*]]
135-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[OFF:%.*]]
134+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[OFF:%.*]]
136135
; CHECK-NEXT: call void @f(ptr nonnull [[GEP]])
137136
; CHECK-NEXT: ret void
138137
;
@@ -144,8 +143,7 @@ define void @nonnull_call_gep_inbounds(i1 %cond, ptr %p, i64 %off) {
144143

145144
define void @nonnull_dereferenceable_call_gep(i1 %cond, ptr %p, i64 %off) {
146145
; CHECK-LABEL: @nonnull_dereferenceable_call_gep(
147-
; CHECK-NEXT: [[PTR:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[P:%.*]]
148-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[OFF:%.*]]
146+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i64 [[OFF:%.*]]
149147
; CHECK-NEXT: call void @f(ptr dereferenceable(1) [[GEP]])
150148
; CHECK-NEXT: ret void
151149
;
@@ -168,8 +166,7 @@ define nonnull ptr @nonnull_ret_gep(i1 %cond, ptr %p, i64 %off) {
168166

169167
define nonnull ptr @nonnull_ret_gep_inbounds(i1 %cond, ptr %p, i64 %off) {
170168
; CHECK-LABEL: @nonnull_ret_gep_inbounds(
171-
; CHECK-NEXT: [[PTR:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[P:%.*]]
172-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[OFF:%.*]]
169+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[OFF:%.*]]
173170
; CHECK-NEXT: ret ptr [[GEP]]
174171
;
175172
%ptr = select i1 %cond, ptr null, ptr %p
@@ -179,8 +176,7 @@ define nonnull ptr @nonnull_ret_gep_inbounds(i1 %cond, ptr %p, i64 %off) {
179176

180177
define dereferenceable(1) ptr @nonnull_dereferenceable_ret_gep(i1 %cond, ptr %p, i64 %off) {
181178
; CHECK-LABEL: @nonnull_dereferenceable_ret_gep(
182-
; CHECK-NEXT: [[PTR:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[P:%.*]]
183-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[OFF:%.*]]
179+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i64 [[OFF:%.*]]
184180
; CHECK-NEXT: ret ptr [[GEP]]
185181
;
186182
%ptr = select i1 %cond, ptr null, ptr %p

llvm/test/Transforms/InstCombine/store.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,8 +389,7 @@ define void @store_select_with_unknown(i1 %cond, ptr %p, ptr %p2) {
389389

390390
define void @store_select_with_null_gep(i1 %cond, ptr %p, i64 %off) {
391391
; CHECK-LABEL: @store_select_with_null_gep(
392-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], ptr [[P:%.*]], ptr null
393-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[SEL]], i64 [[OFF:%.*]]
392+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[SEL:%.*]], i64 [[OFF:%.*]]
394393
; CHECK-NEXT: store i32 0, ptr [[GEP]], align 4
395394
; CHECK-NEXT: ret void
396395
;

llvm/test/Transforms/PhaseOrdering/memset-combine.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
define void @merge_memset(ptr %p, i1 %cond) {
77
; CHECK-LABEL: define void @merge_memset(
88
; CHECK-SAME: ptr [[P:%.*]], i1 [[COND:%.*]]) {
9-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], ptr null, ptr [[P]]
10-
; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(4096) [[P]], i8 0, i64 4096, i1 false)
11-
; CHECK-NEXT: [[OFF:%.*]] = getelementptr inbounds nuw i8, ptr [[SEL]], i64 4096
12-
; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(768) [[OFF]], i8 0, i64 768, i1 false)
9+
; CHECK-NEXT: [[OFF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 4096
10+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[P]], i8 0, i64 4864, i1 false)
1311
; CHECK-NEXT: ret void
1412
;
1513
%sel = select i1 %cond, ptr null, ptr %p

0 commit comments

Comments
 (0)