Skip to content

Commit ae73bc8

Browse files
committed
Reapply [InstCombine] Support gep nuw in icmp folds (#118472)
The profile runtime test failure this caused has been addressed in: #118782 ----- Unsigned icmp of gep nuw folds to unsigned icmp of offsets. Unsigned icmp of gep nusw nuw folds to unsigned samesign icmp of offsets. Proofs: https://alive2.llvm.org/ce/z/VEwQY8
1 parent 1885886 commit ae73bc8

File tree

2 files changed

+102
-9
lines changed

2 files changed

+102
-9
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

+27-9
Original file line numberDiff line numberDiff line change
@@ -689,13 +689,32 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
689689
if (!isa<GetElementPtrInst>(RHS))
690690
RHS = RHS->stripPointerCasts();
691691

692+
auto CanFold = [Cond](GEPNoWrapFlags NW) {
693+
if (ICmpInst::isEquality(Cond))
694+
return true;
695+
696+
// Unsigned predicates can be folded if the GEPs have *any* nowrap flags.
697+
assert(ICmpInst::isUnsigned(Cond));
698+
return NW != GEPNoWrapFlags::none();
699+
};
700+
701+
auto NewICmp = [Cond](GEPNoWrapFlags NW, Value *Op1, Value *Op2) {
702+
if (!NW.hasNoUnsignedWrap()) {
703+
// Convert signed to unsigned comparison.
704+
return new ICmpInst(ICmpInst::getSignedPredicate(Cond), Op1, Op2);
705+
}
706+
707+
auto *I = new ICmpInst(Cond, Op1, Op2);
708+
I->setSameSign(NW.hasNoUnsignedSignedWrap());
709+
return I;
710+
};
711+
692712
Value *PtrBase = GEPLHS->getOperand(0);
693-
if (PtrBase == RHS &&
694-
(GEPLHS->hasNoUnsignedSignedWrap() || ICmpInst::isEquality(Cond))) {
713+
if (PtrBase == RHS && CanFold(GEPLHS->getNoWrapFlags())) {
695714
// ((gep Ptr, OFFSET) cmp Ptr) ---> (OFFSET cmp 0).
696715
Value *Offset = EmitGEPOffset(GEPLHS);
697-
return new ICmpInst(ICmpInst::getSignedPredicate(Cond), Offset,
698-
Constant::getNullValue(Offset->getType()));
716+
return NewICmp(GEPLHS->getNoWrapFlags(), Offset,
717+
Constant::getNullValue(Offset->getType()));
699718
}
700719

701720
if (GEPLHS->isInBounds() && ICmpInst::isEquality(Cond) &&
@@ -813,19 +832,18 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
813832
return replaceInstUsesWith(I, // No comparison is needed here.
814833
ConstantInt::get(I.getType(), ICmpInst::isTrueWhenEqual(Cond)));
815834

816-
else if (NumDifferences == 1 && NW.hasNoUnsignedSignedWrap()) {
835+
else if (NumDifferences == 1 && CanFold(NW)) {
817836
Value *LHSV = GEPLHS->getOperand(DiffOperand);
818837
Value *RHSV = GEPRHS->getOperand(DiffOperand);
819-
// Make sure we do a signed comparison here.
820-
return new ICmpInst(ICmpInst::getSignedPredicate(Cond), LHSV, RHSV);
838+
return NewICmp(NW, LHSV, RHSV);
821839
}
822840
}
823841

824-
if (NW.hasNoUnsignedSignedWrap() || CmpInst::isEquality(Cond)) {
842+
if (CanFold(NW)) {
825843
// ((gep Ptr, OFFSET1) cmp (gep Ptr, OFFSET2) ---> (OFFSET1 cmp OFFSET2)
826844
Value *L = EmitGEPOffset(GEPLHS, /*RewriteGEP=*/true);
827845
Value *R = EmitGEPOffset(GEPRHS, /*RewriteGEP=*/true);
828-
return new ICmpInst(ICmpInst::getSignedPredicate(Cond), L, R);
846+
return NewICmp(NW, L, R);
829847
}
830848
}
831849

llvm/test/Transforms/InstCombine/icmp-gep.ll

+75
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,44 @@ define i1 @ult_base_nusw(ptr %x, i64 %y) {
143143
ret i1 %r
144144
}
145145

146+
define i1 @ugt_base_nuw(ptr %x, i64 %y) {
147+
; CHECK-LABEL: @ugt_base_nuw(
148+
; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0
149+
; CHECK-NEXT: ret i1 [[R]]
150+
;
151+
%g = getelementptr nuw i8, ptr %x, i64 %y
152+
%r = icmp ugt ptr %g, %x
153+
ret i1 %r
154+
}
155+
156+
define i1 @ugt_base_nusw_nuw(ptr %x, i64 %y) {
157+
; CHECK-LABEL: @ugt_base_nusw_nuw(
158+
; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0
159+
; CHECK-NEXT: ret i1 [[R]]
160+
;
161+
%g = getelementptr nusw nuw i8, ptr %x, i64 %y
162+
%r = icmp ugt ptr %g, %x
163+
ret i1 %r
164+
}
165+
166+
define i1 @uge_base_nuw(ptr %x, i64 %y) {
167+
; CHECK-LABEL: @uge_base_nuw(
168+
; CHECK-NEXT: ret i1 true
169+
;
170+
%g = getelementptr nuw i8, ptr %x, i64 %y
171+
%r = icmp uge ptr %g, %x
172+
ret i1 %r
173+
}
174+
175+
define i1 @uge_base_nusw_nuw(ptr %x, i64 %y) {
176+
; CHECK-LABEL: @uge_base_nusw_nuw(
177+
; CHECK-NEXT: ret i1 true
178+
;
179+
%g = getelementptr nusw nuw i8, ptr %x, i64 %y
180+
%r = icmp uge ptr %g, %x
181+
ret i1 %r
182+
}
183+
146184
define i1 @ugt_base_inbounds_commute(i64 %y) {
147185
; CHECK-LABEL: @ugt_base_inbounds_commute(
148186
; CHECK-NEXT: [[X:%.*]] = call ptr @getptr()
@@ -319,6 +357,43 @@ define i1 @test60_nusw_inbounds(ptr %foo, i64 %i, i64 %j) {
319357
ret i1 %cmp
320358
}
321359

360+
define i1 @test60_nuw(ptr %foo, i64 %i, i64 %j) {
361+
; CHECK-LABEL: @test60_nuw(
362+
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[I:%.*]], 2
363+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[GEP1_IDX]], [[J:%.*]]
364+
; CHECK-NEXT: ret i1 [[CMP]]
365+
;
366+
%gep1 = getelementptr nuw i32, ptr %foo, i64 %i
367+
%gep2 = getelementptr nuw i8, ptr %foo, i64 %j
368+
%cmp = icmp ult ptr %gep1, %gep2
369+
ret i1 %cmp
370+
}
371+
372+
define i1 @test60_nusw_nuw(ptr %foo, i64 %i, i64 %j) {
373+
; CHECK-LABEL: @test60_nusw_nuw(
374+
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw nsw i64 [[I:%.*]], 2
375+
; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i64 [[GEP1_IDX]], [[J:%.*]]
376+
; CHECK-NEXT: ret i1 [[CMP]]
377+
;
378+
%gep1 = getelementptr nusw nuw i32, ptr %foo, i64 %i
379+
%gep2 = getelementptr nusw nuw i8, ptr %foo, i64 %j
380+
%cmp = icmp ult ptr %gep1, %gep2
381+
ret i1 %cmp
382+
}
383+
384+
define i1 @test60_nusw_nuw_mix(ptr %foo, i64 %i, i64 %j) {
385+
; CHECK-LABEL: @test60_nusw_nuw_mix(
386+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[FOO:%.*]], i64 [[I:%.*]]
387+
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nusw i8, ptr [[FOO]], i64 [[J:%.*]]
388+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]]
389+
; CHECK-NEXT: ret i1 [[CMP]]
390+
;
391+
%gep1 = getelementptr nuw i32, ptr %foo, i64 %i
392+
%gep2 = getelementptr nusw i8, ptr %foo, i64 %j
393+
%cmp = icmp ult ptr %gep1, %gep2
394+
ret i1 %cmp
395+
}
396+
322397
define i1 @test_gep_ult_no_inbounds(ptr %foo, i64 %i, i64 %j) {
323398
; CHECK-LABEL: @test_gep_ult_no_inbounds(
324399
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[FOO:%.*]], i64 [[I:%.*]]

0 commit comments

Comments
 (0)