Skip to content

Commit b400dde

Browse files
committed
[InstSimplify] Use dominate condtion to simplify instructions
Fix #56795 Reviewed By: spatel Differential Revision: https://reviews.llvm.org/D138542
1 parent 5c1e148 commit b400dde

File tree

3 files changed

+64
-25
lines changed

3 files changed

+64
-25
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,42 @@ static Constant *computePointerDifference(const DataLayout &DL, Value *LHS,
741741
return Res;
742742
}
743743

744+
/// Test if there is a dominating equivalence condition for the
745+
/// two operands. If there is, try to reduce the binary operation
746+
/// between the two operands.
747+
/// Example: Op0 - Op1 --> 0 when Op0 == Op1
748+
static Value *simplifyByDomEq(unsigned Opcode, Value *Op0, Value *Op1,
749+
const SimplifyQuery &Q, unsigned MaxRecurse) {
750+
// Recursive run it can not get any benefit
751+
if (MaxRecurse != RecursionLimit)
752+
return nullptr;
753+
754+
Optional<bool> Imp =
755+
isImpliedByDomCondition(CmpInst::ICMP_EQ, Op0, Op1, Q.CxtI, Q.DL);
756+
if (Imp && *Imp) {
757+
Type *Ty = Op0->getType();
758+
switch (Opcode) {
759+
case Instruction::Sub:
760+
case Instruction::Xor:
761+
case Instruction::URem:
762+
case Instruction::SRem:
763+
return Constant::getNullValue(Ty);
764+
765+
case Instruction::SDiv:
766+
case Instruction::UDiv:
767+
return ConstantInt::get(Ty, 1);
768+
769+
case Instruction::And:
770+
case Instruction::Or:
771+
// Could be either one - choose Op1 since that's more likely a constant.
772+
return Op1;
773+
default:
774+
break;
775+
}
776+
}
777+
return nullptr;
778+
}
779+
744780
/// Given operands for a Sub, see if we can fold the result.
745781
/// If not, this returns null.
746782
static Value *simplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
@@ -872,6 +908,9 @@ static Value *simplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
872908
// "A-B" and "A-C" thus gains nothing, but costs compile time. Similarly
873909
// for threading over phi nodes.
874910

911+
if (Value *V = simplifyByDomEq(Instruction::Sub, Op0, Op1, Q, MaxRecurse))
912+
return V;
913+
875914
return nullptr;
876915
}
877916

@@ -947,7 +986,8 @@ Value *llvm::simplifyMulInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
947986
/// Check for common or similar folds of integer division or integer remainder.
948987
/// This applies to all 4 opcodes (sdiv/udiv/srem/urem).
949988
static Value *simplifyDivRem(Instruction::BinaryOps Opcode, Value *Op0,
950-
Value *Op1, const SimplifyQuery &Q) {
989+
Value *Op1, const SimplifyQuery &Q,
990+
unsigned MaxRecurse) {
951991
bool IsDiv = (Opcode == Instruction::SDiv || Opcode == Instruction::UDiv);
952992
bool IsSigned = (Opcode == Instruction::SDiv || Opcode == Instruction::SRem);
953993

@@ -1022,6 +1062,9 @@ static Value *simplifyDivRem(Instruction::BinaryOps Opcode, Value *Op0,
10221062
}
10231063
}
10241064

1065+
if (Value *V = simplifyByDomEq(Opcode, Op0, Op1, Q, MaxRecurse))
1066+
return V;
1067+
10251068
return nullptr;
10261069
}
10271070

@@ -1103,7 +1146,7 @@ static Value *simplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
11031146
if (Constant *C = foldOrCommuteConstant(Opcode, Op0, Op1, Q))
11041147
return C;
11051148

1106-
if (Value *V = simplifyDivRem(Opcode, Op0, Op1, Q))
1149+
if (Value *V = simplifyDivRem(Opcode, Op0, Op1, Q, MaxRecurse))
11071150
return V;
11081151

11091152
bool IsSigned = Opcode == Instruction::SDiv;
@@ -1147,7 +1190,7 @@ static Value *simplifyRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
11471190
if (Constant *C = foldOrCommuteConstant(Opcode, Op0, Op1, Q))
11481191
return C;
11491192

1150-
if (Value *V = simplifyDivRem(Opcode, Op0, Op1, Q))
1193+
if (Value *V = simplifyDivRem(Opcode, Op0, Op1, Q, MaxRecurse))
11511194
return V;
11521195

11531196
// (X % Y) % Y -> X % Y
@@ -2191,6 +2234,9 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
21912234
}
21922235
}
21932236

2237+
if (Value *V = simplifyByDomEq(Instruction::And, Op0, Op1, Q, MaxRecurse))
2238+
return V;
2239+
21942240
return nullptr;
21952241
}
21962242

@@ -2450,6 +2496,9 @@ static Value *simplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
24502496
}
24512497
}
24522498

2499+
if (Value *V = simplifyByDomEq(Instruction::Or, Op0, Op1, Q, MaxRecurse))
2500+
return V;
2501+
24532502
return nullptr;
24542503
}
24552504

@@ -2525,6 +2574,9 @@ static Value *simplifyXorInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
25252574
// "A^B" and "A^C" thus gains nothing, but costs compile time. Similarly
25262575
// for threading over phi nodes.
25272576

2577+
if (Value *V = simplifyByDomEq(Instruction::Xor, Op0, Op1, Q, MaxRecurse))
2578+
return V;
2579+
25282580
return nullptr;
25292581
}
25302582

llvm/test/Transforms/InstCombine/usub-overflow-known-by-implied-cond.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ define i32 @test5(i32 %a, i32 %b) {
123123
; CHECK: bb1:
124124
; CHECK-NEXT: br i1 false, label [[BB3]], label [[BB2:%.*]]
125125
; CHECK: bb2:
126-
; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i32 [[A]], [[B]]
127-
; CHECK-NEXT: ret i32 [[SUB1]]
126+
; CHECK-NEXT: ret i32 0
128127
; CHECK: bb3:
129128
; CHECK-NEXT: ret i32 0
130129
;

llvm/test/Transforms/InstSimplify/domcondition.ll

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ define i32 @xor_domcondition(i32 %x, i32 %y) {
77
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
88
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
99
; CHECK: cond.true:
10-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
1110
; CHECK-NEXT: br label [[COND_END]]
1211
; CHECK: cond.end:
13-
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[XOR]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
14-
; CHECK-NEXT: ret i32 [[COND]]
12+
; CHECK-NEXT: ret i32 0
1513
;
1614
entry:
1715
%cmp = icmp eq i32 %x, %y
@@ -32,11 +30,9 @@ define i32 @sub_domcondition(i32 %x, i32 %y) {
3230
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
3331
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
3432
; CHECK: cond.true:
35-
; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]
3633
; CHECK-NEXT: br label [[COND_END]]
3734
; CHECK: cond.end:
38-
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[SUB]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
39-
; CHECK-NEXT: ret i32 [[COND]]
35+
; CHECK-NEXT: ret i32 0
4036
;
4137
entry:
4238
%cmp = icmp eq i32 %x, %y
@@ -57,10 +53,9 @@ define i32 @udiv_domcondition(i32 %x, i32 %y) {
5753
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
5854
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
5955
; CHECK: cond.true:
60-
; CHECK-NEXT: [[UDIV:%.*]] = udiv i32 [[X]], [[Y]]
6156
; CHECK-NEXT: br label [[COND_END]]
6257
; CHECK: cond.end:
63-
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[UDIV]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
58+
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 1, [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
6459
; CHECK-NEXT: ret i32 [[COND]]
6560
;
6661
entry:
@@ -82,10 +77,9 @@ define i32 @sdiv_domcondition(i32 %x, i32 %y) {
8277
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
8378
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
8479
; CHECK: cond.true:
85-
; CHECK-NEXT: [[SDIV:%.*]] = sdiv i32 [[X]], [[Y]]
8680
; CHECK-NEXT: br label [[COND_END]]
8781
; CHECK: cond.end:
88-
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[SDIV]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
82+
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 1, [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
8983
; CHECK-NEXT: ret i32 [[COND]]
9084
;
9185
entry:
@@ -107,11 +101,9 @@ define i32 @urem_domcondition(i32 %x, i32 %y) {
107101
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
108102
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
109103
; CHECK: cond.true:
110-
; CHECK-NEXT: [[UREM:%.*]] = urem i32 [[X]], [[Y]]
111104
; CHECK-NEXT: br label [[COND_END]]
112105
; CHECK: cond.end:
113-
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[UREM]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
114-
; CHECK-NEXT: ret i32 [[COND]]
106+
; CHECK-NEXT: ret i32 0
115107
;
116108
entry:
117109
%cmp = icmp eq i32 %x, %y
@@ -132,11 +124,9 @@ define i32 @srem_domcondition(i32 %x, i32 %y) {
132124
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
133125
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
134126
; CHECK: cond.true:
135-
; CHECK-NEXT: [[SREM:%.*]] = srem i32 [[X]], [[Y]]
136127
; CHECK-NEXT: br label [[COND_END]]
137128
; CHECK: cond.end:
138-
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[SREM]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
139-
; CHECK-NEXT: ret i32 [[COND]]
129+
; CHECK-NEXT: ret i32 0
140130
;
141131
entry:
142132
%cmp = icmp eq i32 %x, %y
@@ -158,10 +148,9 @@ define i32 @and_domcondition(i32 %x, i32 %y) {
158148
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
159149
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
160150
; CHECK: cond.true:
161-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
162151
; CHECK-NEXT: br label [[COND_END]]
163152
; CHECK: cond.end:
164-
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[AND]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
153+
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[Y]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
165154
; CHECK-NEXT: ret i32 [[COND]]
166155
;
167156
entry:
@@ -184,10 +173,9 @@ define i32 @or_domcondition(i32 %x, i32 %y) {
184173
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
185174
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
186175
; CHECK: cond.true:
187-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
188176
; CHECK-NEXT: br label [[COND_END]]
189177
; CHECK: cond.end:
190-
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[OR]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
178+
; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[Y]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
191179
; CHECK-NEXT: ret i32 [[COND]]
192180
;
193181
entry:

0 commit comments

Comments
 (0)