Skip to content

Commit

Permalink
[InstCombine] Relax the one-use constraints for `icmp pred (binop X, …
Browse files Browse the repository at this point in the history
…Z), (binop Y, Z)` (llvm#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
}
```
  • Loading branch information
dtcxzyw authored and justinfargnoli committed Jan 28, 2024
1 parent 07de3c1 commit 6f34bf2
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 2 deletions.
5 changes: 3 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Expand Up @@ -4920,8 +4920,9 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
}
}

if (BO0 && BO1 && BO0->getOpcode() == BO1->getOpcode() && BO0->hasOneUse() &&
BO1->hasOneUse() && BO0->getOperand(1) == BO1->getOperand(1)) {
if (BO0 && BO1 && BO0->getOpcode() == BO1->getOpcode() &&
(BO0->hasOneUse() || BO1->hasOneUse()) &&
BO0->getOperand(1) == BO1->getOperand(1)) {
switch (BO0->getOpcode()) {
default:
break;
Expand Down
45 changes: 45 additions & 0 deletions llvm/test/Transforms/InstCombine/icmp.ll
Expand Up @@ -815,6 +815,51 @@ define i1 @test46(i32 %X, i32 %Y, i32 %Z) {
ret i1 %C
}

define i1 @test46_multiuse1(i32 %X, i32 %Y, i32 %Z) {
; CHECK-LABEL: @test46_multiuse1(
; CHECK-NEXT: [[A:%.*]] = ashr exact i32 [[X:%.*]], [[Z:%.*]]
; CHECK-NEXT: call void @use_i32(i32 [[A]])
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[X]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[C]]
;
%A = ashr exact i32 %X, %Z
call void @use_i32(i32 %A)
%B = ashr exact i32 %Y, %Z
%C = icmp ult i32 %A, %B
ret i1 %C
}

define i1 @test46_multiuse2(i32 %X, i32 %Y, i32 %Z) {
; CHECK-LABEL: @test46_multiuse2(
; CHECK-NEXT: [[B:%.*]] = ashr exact i32 [[Y:%.*]], [[Z:%.*]]
; CHECK-NEXT: call void @use_i32(i32 [[B]])
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[X:%.*]], [[Y]]
; CHECK-NEXT: ret i1 [[C]]
;
%A = ashr exact i32 %X, %Z
%B = ashr exact i32 %Y, %Z
call void @use_i32(i32 %B)
%C = icmp ult i32 %A, %B
ret i1 %C
}

define i1 @test46_multiuse3(i32 %X, i32 %Y, i32 %Z) {
; CHECK-LABEL: @test46_multiuse3(
; CHECK-NEXT: [[A:%.*]] = ashr exact i32 [[X:%.*]], [[Z:%.*]]
; CHECK-NEXT: call void @use_i32(i32 [[A]])
; CHECK-NEXT: [[B:%.*]] = ashr exact i32 [[Y:%.*]], [[Z]]
; CHECK-NEXT: call void @use_i32(i32 [[B]])
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A]], [[B]]
; CHECK-NEXT: ret i1 [[C]]
;
%A = ashr exact i32 %X, %Z
call void @use_i32(i32 %A)
%B = ashr exact i32 %Y, %Z
call void @use_i32(i32 %B)
%C = icmp ult i32 %A, %B
ret i1 %C
}

; PR9343 #5
define i1 @test47(i32 %X, i32 %Y, i32 %Z) {
; CHECK-LABEL: @test47(
Expand Down

0 comments on commit 6f34bf2

Please sign in to comment.