Skip to content

Commit e7bf750

Browse files
authored
[InstCombine] Pass disjoint in or combine (#138800)
Proof: https://alive2.llvm.org/ce/z/wtTm5V https://alive2.llvm.org/ce/z/WC7Ai2 --------- Signed-off-by: feng.feng <feng.feng@iluvatar.com>
1 parent fc8484f commit e7bf750

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3894,12 +3894,23 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
38943894
// be simplified by a later pass either, so we try swapping the inner/outer
38953895
// ORs in the hopes that we'll be able to simplify it this way.
38963896
// (X|C) | V --> (X|V) | C
3897+
// Pass the disjoint flag in the following two patterns:
3898+
// 1. or-disjoint (or-disjoint X, C), V -->
3899+
// or-disjoint (or-disjoint X, V), C
3900+
//
3901+
// 2. or-disjoint (or X, C), V -->
3902+
// or (or-disjoint X, V), C
38973903
ConstantInt *CI;
38983904
if (Op0->hasOneUse() && !match(Op1, m_ConstantInt()) &&
38993905
match(Op0, m_Or(m_Value(A), m_ConstantInt(CI)))) {
3906+
bool IsDisjointOuter = cast<PossiblyDisjointInst>(I).isDisjoint();
3907+
bool IsDisjointInner = cast<PossiblyDisjointInst>(Op0)->isDisjoint();
39003908
Value *Inner = Builder.CreateOr(A, Op1);
3909+
cast<PossiblyDisjointInst>(Inner)->setIsDisjoint(IsDisjointOuter);
39013910
Inner->takeName(Op0);
3902-
return BinaryOperator::CreateOr(Inner, CI);
3911+
return IsDisjointOuter && IsDisjointInner
3912+
? BinaryOperator::CreateDisjointOr(Inner, CI)
3913+
: BinaryOperator::CreateOr(Inner, CI);
39033914
}
39043915

39053916
// Change (or (bool?A:B),(bool?C:D)) --> (bool?(or A,C):(or B,D))
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3+
4+
; (X | C) | Y --> (X | Y) | C
5+
6+
define i32 @test1(i32 %x, i32 %y) {
7+
; CHECK-LABEL: @test1(
8+
; CHECK-NEXT: [[INNER:%.*]] = or disjoint i32 [[X:%.*]], [[Y:%.*]]
9+
; CHECK-NEXT: [[OUTER:%.*]] = or disjoint i32 [[INNER]], 5
10+
; CHECK-NEXT: ret i32 [[OUTER]]
11+
;
12+
%inner = or disjoint i32 %x, 5
13+
%outer = or disjoint i32 %inner, %y
14+
ret i32 %outer
15+
}
16+
17+
define i32 @test2(i32 %x, i32 %y) {
18+
; CHECK-LABEL: @test2(
19+
; CHECK-NEXT: [[INNER:%.*]] = or disjoint i32 [[X:%.*]], [[Y:%.*]]
20+
; CHECK-NEXT: [[OUTER:%.*]] = or i32 [[INNER]], 5
21+
; CHECK-NEXT: ret i32 [[OUTER]]
22+
;
23+
%inner = or i32 %x, 5
24+
%outer = or disjoint i32 %inner, %y
25+
ret i32 %outer
26+
}
27+
28+
define i32 @test3(i32 %x, i32 %y) {
29+
; CHECK-LABEL: @test3(
30+
; CHECK-NEXT: [[INNER:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
31+
; CHECK-NEXT: [[OUTER:%.*]] = or i32 [[INNER]], 5
32+
; CHECK-NEXT: ret i32 [[OUTER]]
33+
;
34+
%inner = or disjoint i32 %x, 5
35+
%outer = or i32 %inner, %y
36+
ret i32 %outer
37+
}
38+
39+
define i32 @test4(i32 %x, i32 %y) {
40+
; CHECK-LABEL: @test4(
41+
; CHECK-NEXT: [[INNER:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
42+
; CHECK-NEXT: [[OUTER:%.*]] = or i32 [[INNER]], 5
43+
; CHECK-NEXT: ret i32 [[OUTER]]
44+
;
45+
%inner = or i32 %x, 5
46+
%outer = or i32 %inner, %y
47+
ret i32 %outer
48+
}

0 commit comments

Comments
 (0)