Skip to content

Commit 2eb7a82

Browse files
authored
[InstCombine] Relax the one-use constraints for icmp pred (binop X, Z), (binop Y, Z) (#76384)
This patch relaxes the one-use constraints for `icmp pred (binop X, Z), (binop Y, Z)`. It will enable more optimizations with pointer arithmetic. One example in `boost::match_results::set_size`: ``` declare void @use(i64) define i1 @src(ptr %a1, ptr %a2, ptr %add.ptr.i66, i64 %sub.ptr.rhs.cast.i) { %sub.ptr.lhs.cast.i = ptrtoint ptr %a1 to i64 %sub.ptr.rhs.cast.i = ptrtoint ptr %a2 to i64 %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i %sub.ptr.div.i = sdiv exact i64 %sub.ptr.sub.i, 24 call void @use(i64 %sub.ptr.div.i) %sub.ptr.lhs.cast.i.i = ptrtoint ptr %add.ptr.i66 to i64 %sub.ptr.sub.i.i = sub i64 %sub.ptr.lhs.cast.i.i, %sub.ptr.rhs.cast.i %sub.ptr.div.i.i = sdiv exact i64 %sub.ptr.sub.i.i, 24 %cmp.i.not.i.i = icmp eq i64 %sub.ptr.div.i.i, %sub.ptr.div.i ret i1 %cmp.i.not.i.i } define i1 @tgt(ptr %a1, ptr %a2, ptr %add.ptr.i66, i64 %sub.ptr.rhs.cast.i) { %sub.ptr.lhs.cast.i = ptrtoint ptr %a1 to i64 %sub.ptr.rhs.cast.i = ptrtoint ptr %a2 to i64 %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i %sub.ptr.div.i = sdiv exact i64 %sub.ptr.sub.i, 24 call void @use(i64 %sub.ptr.div.i) %cmp.i.not.i.i = icmp eq i64 %sub.ptr.sub.i.i, %sub.ptr.sub.i ret i1 %cmp.i.not.i.i } ```
1 parent fd1c156 commit 2eb7a82

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4920,8 +4920,9 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
49204920
}
49214921
}
49224922

4923-
if (BO0 && BO1 && BO0->getOpcode() == BO1->getOpcode() && BO0->hasOneUse() &&
4924-
BO1->hasOneUse() && BO0->getOperand(1) == BO1->getOperand(1)) {
4923+
if (BO0 && BO1 && BO0->getOpcode() == BO1->getOpcode() &&
4924+
(BO0->hasOneUse() || BO1->hasOneUse()) &&
4925+
BO0->getOperand(1) == BO1->getOperand(1)) {
49254926
switch (BO0->getOpcode()) {
49264927
default:
49274928
break;

llvm/test/Transforms/InstCombine/icmp.ll

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,51 @@ define i1 @test46(i32 %X, i32 %Y, i32 %Z) {
815815
ret i1 %C
816816
}
817817

818+
define i1 @test46_multiuse1(i32 %X, i32 %Y, i32 %Z) {
819+
; CHECK-LABEL: @test46_multiuse1(
820+
; CHECK-NEXT: [[A:%.*]] = ashr exact i32 [[X:%.*]], [[Z:%.*]]
821+
; CHECK-NEXT: call void @use_i32(i32 [[A]])
822+
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[X]], [[Y:%.*]]
823+
; CHECK-NEXT: ret i1 [[C]]
824+
;
825+
%A = ashr exact i32 %X, %Z
826+
call void @use_i32(i32 %A)
827+
%B = ashr exact i32 %Y, %Z
828+
%C = icmp ult i32 %A, %B
829+
ret i1 %C
830+
}
831+
832+
define i1 @test46_multiuse2(i32 %X, i32 %Y, i32 %Z) {
833+
; CHECK-LABEL: @test46_multiuse2(
834+
; CHECK-NEXT: [[B:%.*]] = ashr exact i32 [[Y:%.*]], [[Z:%.*]]
835+
; CHECK-NEXT: call void @use_i32(i32 [[B]])
836+
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[X:%.*]], [[Y]]
837+
; CHECK-NEXT: ret i1 [[C]]
838+
;
839+
%A = ashr exact i32 %X, %Z
840+
%B = ashr exact i32 %Y, %Z
841+
call void @use_i32(i32 %B)
842+
%C = icmp ult i32 %A, %B
843+
ret i1 %C
844+
}
845+
846+
define i1 @test46_multiuse3(i32 %X, i32 %Y, i32 %Z) {
847+
; CHECK-LABEL: @test46_multiuse3(
848+
; CHECK-NEXT: [[A:%.*]] = ashr exact i32 [[X:%.*]], [[Z:%.*]]
849+
; CHECK-NEXT: call void @use_i32(i32 [[A]])
850+
; CHECK-NEXT: [[B:%.*]] = ashr exact i32 [[Y:%.*]], [[Z]]
851+
; CHECK-NEXT: call void @use_i32(i32 [[B]])
852+
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A]], [[B]]
853+
; CHECK-NEXT: ret i1 [[C]]
854+
;
855+
%A = ashr exact i32 %X, %Z
856+
call void @use_i32(i32 %A)
857+
%B = ashr exact i32 %Y, %Z
858+
call void @use_i32(i32 %B)
859+
%C = icmp ult i32 %A, %B
860+
ret i1 %C
861+
}
862+
818863
; PR9343 #5
819864
define i1 @test47(i32 %X, i32 %Y, i32 %Z) {
820865
; CHECK-LABEL: @test47(

0 commit comments

Comments
 (0)