Skip to content

Commit cf5562b

Browse files
committed
[InstCombine] Simplify (X / C0) * C1 + (X % C0) * C2 to (X / C0) * (C1 - C2 * C0) + X * C2
1 parent 5e565bb commit cf5562b

File tree

3 files changed

+44
-22
lines changed

3 files changed

+44
-22
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,8 @@ static bool MulWillOverflow(APInt &C0, APInt &C1, bool IsSigned) {
11321132

11331133
// Simplifies X % C0 + (( X / C0 ) % C1) * C0 to X % (C0 * C1), where (C0 * C1)
11341134
// does not overflow.
1135+
// Simplifies (X / C0) * C1 + (X % C0) * C2 to
1136+
// (X / C0) * (C1 - C2 * C0) + X * C2
11351137
Value *InstCombinerImpl::SimplifyAddWithRemainder(BinaryOperator &I) {
11361138
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
11371139
Value *X, *MulOpV;
@@ -1159,6 +1161,33 @@ Value *InstCombinerImpl::SimplifyAddWithRemainder(BinaryOperator &I) {
11591161
}
11601162
}
11611163

1164+
// Match I = (X / C0) * C1 + (X % C0) * C2
1165+
Value *Div, *Rem;
1166+
APInt C1, C2;
1167+
if (!LHS->hasOneUse() || !MatchMul(LHS, Div, C1))
1168+
Div = LHS, C1 = APInt(I.getType()->getScalarSizeInBits(), 1);
1169+
if (!RHS->hasOneUse() || !MatchMul(RHS, Rem, C2))
1170+
Rem = RHS, C2 = APInt(I.getType()->getScalarSizeInBits(), 1);
1171+
if (match(Div, m_IRem(m_Value(), m_Value()))) {
1172+
std::swap(Div, Rem);
1173+
std::swap(C1, C2);
1174+
}
1175+
Value *DivOpV;
1176+
APInt DivOpC;
1177+
if (MatchRem(Rem, X, C0, IsSigned) &&
1178+
MatchDiv(Div, DivOpV, DivOpC, IsSigned) && X == DivOpV && C0 == DivOpC) {
1179+
if (!isGuaranteedNotToBeUndef(X, &AC, &I, &DT))
1180+
return nullptr;
1181+
APInt NewC = C1 - C2 * C0;
1182+
if (!NewC.isZero() && !Rem->hasOneUse())
1183+
return nullptr;
1184+
Value *MulXC2 = Builder.CreateMul(X, ConstantInt::get(X->getType(), C2));
1185+
if (NewC.isZero())
1186+
return MulXC2;
1187+
return Builder.CreateAdd(
1188+
Builder.CreateMul(Div, ConstantInt::get(X->getType(), NewC)), MulXC2);
1189+
}
1190+
11621191
return nullptr;
11631192
}
11641193

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3910,6 +3910,10 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
39103910

39113911
if (Instruction *Res = foldBitwiseLogicWithIntrinsics(I, Builder))
39123912
return Res;
3913+
3914+
if (cast<PossiblyDisjointInst>(I).isDisjoint())
3915+
if (Value *V = SimplifyAddWithRemainder(I))
3916+
return replaceInstUsesWith(I, V);
39133917

39143918
return nullptr;
39153919
}

llvm/test/Transforms/InstCombine/add4.ll

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,8 @@ define i32 @fold_add_udiv_urem(i32 noundef %val) {
135135
; CHECK-LABEL: @fold_add_udiv_urem(
136136
; CHECK-NEXT: entry:
137137
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10
138-
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4
139-
; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], 10
140-
; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[SHL]], [[REM]]
138+
; CHECK-NEXT: [[TMP0:%.*]] = mul nuw i32 [[DIV]], 6
139+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]]
141140
; CHECK-NEXT: ret i32 [[ADD]]
142141
;
143142
entry:
@@ -151,9 +150,8 @@ define i32 @fold_add_sdiv_srem(i32 noundef %val) {
151150
; CHECK-LABEL: @fold_add_sdiv_srem(
152151
; CHECK-NEXT: entry:
153152
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[VAL:%.*]], 10
154-
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4
155-
; CHECK-NEXT: [[REM:%.*]] = srem i32 [[VAL]], 10
156-
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], [[REM]]
153+
; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i32 [[DIV]], 6
154+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]]
157155
; CHECK-NEXT: ret i32 [[ADD]]
158156
;
159157
entry:
@@ -166,11 +164,7 @@ entry:
166164
define i32 @fold_add_udiv_urem_to_mul(i32 noundef %val) {
167165
; CHECK-LABEL: @fold_add_udiv_urem_to_mul(
168166
; CHECK-NEXT: entry:
169-
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 7
170-
; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[DIV]], 21
171-
; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], 7
172-
; CHECK-NEXT: [[MUL2:%.*]] = mul nuw nsw i32 [[REM]], 3
173-
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[MUL1]], [[MUL2]]
167+
; CHECK-NEXT: [[ADD:%.*]] = mul i32 [[VAL:%.*]], 3
174168
; CHECK-NEXT: ret i32 [[ADD]]
175169
;
176170
entry:
@@ -184,12 +178,9 @@ entry:
184178
define i32 @fold_add_udiv_urem_to_mul_multiuse(i32 noundef %val) {
185179
; CHECK-LABEL: @fold_add_udiv_urem_to_mul_multiuse(
186180
; CHECK-NEXT: entry:
187-
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 7
188-
; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[DIV]], 21
189-
; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], 7
181+
; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL:%.*]], 7
190182
; CHECK-NEXT: call void @use(i32 [[REM]])
191-
; CHECK-NEXT: [[MUL2:%.*]] = mul nuw nsw i32 [[REM]], 3
192-
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[MUL1]], [[MUL2]]
183+
; CHECK-NEXT: [[ADD:%.*]] = mul i32 [[VAL]], 3
193184
; CHECK-NEXT: ret i32 [[ADD]]
194185
;
195186
entry:
@@ -205,9 +196,8 @@ define i32 @fold_add_udiv_urem_commuted(i32 noundef %val) {
205196
; CHECK-LABEL: @fold_add_udiv_urem_commuted(
206197
; CHECK-NEXT: entry:
207198
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10
208-
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4
209-
; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], 10
210-
; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[REM]], [[SHL]]
199+
; CHECK-NEXT: [[TMP0:%.*]] = mul nuw i32 [[DIV]], 6
200+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]]
211201
; CHECK-NEXT: ret i32 [[ADD]]
212202
;
213203
entry:
@@ -221,9 +211,8 @@ define i32 @fold_add_udiv_urem_or_disjoint(i32 noundef %val) {
221211
; CHECK-LABEL: @fold_add_udiv_urem_or_disjoint(
222212
; CHECK-NEXT: entry:
223213
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[VAL:%.*]], 10
224-
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[DIV]], 4
225-
; CHECK-NEXT: [[REM:%.*]] = urem i32 [[VAL]], 10
226-
; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[SHL]], [[REM]]
214+
; CHECK-NEXT: [[TMP0:%.*]] = mul nuw i32 [[DIV]], 6
215+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[VAL]]
227216
; CHECK-NEXT: ret i32 [[ADD]]
228217
;
229218
entry:

0 commit comments

Comments
 (0)