Skip to content

Commit 8da2fa8

Browse files
committed
[InstCombine] fold sdiv with hidden common factor
(X * Y) s/ (X << Z) --> Y s/ (1 << Z) https://alive2.llvm.org/ce/z/yRSddG issue #58137
1 parent 241893f commit 8da2fa8

File tree

3 files changed

+34
-17
lines changed

3 files changed

+34
-17
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -970,12 +970,17 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
970970
auto *OBO0 = cast<OverflowingBinaryOperator>(Op0);
971971
auto *OBO1 = cast<OverflowingBinaryOperator>(Op1);
972972
bool HasNUW = OBO0->hasNoUnsignedWrap() && OBO1->hasNoUnsignedWrap();
973+
bool HasNSW = OBO0->hasNoSignedWrap() && OBO1->hasNoSignedWrap();
973974

974975
// (X * Y) u/ (X << Z) --> Y u>> Z
975976
if (!IsSigned && HasNUW)
976977
return BinaryOperator::CreateLShr(Y, Z);
977978

978-
// TODO: Handle signed division.
979+
// (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
980+
if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
981+
Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
982+
return BinaryOperator::CreateSDiv(Y, Shl);
983+
}
979984
}
980985

981986
return nullptr;

llvm/test/Transforms/InstCombine/div-shift.ll

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,12 @@ define <2 x i32> @t16(<2 x i32> %x, <2 x i32> %y) {
295295
ret <2 x i32> %r
296296
}
297297

298+
; (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
299+
298300
define i5 @sdiv_mul_shl_nsw(i5 %x, i5 %y, i5 %z) {
299301
; CHECK-LABEL: @sdiv_mul_shl_nsw(
300-
; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[X:%.*]], [[Y:%.*]]
301-
; CHECK-NEXT: [[M2:%.*]] = shl nsw i5 [[X]], [[Z:%.*]]
302-
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[M1]], [[M2]]
302+
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i5 1, [[Z:%.*]]
303+
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[Y:%.*]], [[TMP1]]
303304
; CHECK-NEXT: ret i5 [[D]]
304305
;
305306
%m1 = mul nsw i5 %x, %y
@@ -308,11 +309,12 @@ define i5 @sdiv_mul_shl_nsw(i5 %x, i5 %y, i5 %z) {
308309
ret i5 %d
309310
}
310311

312+
; (Y * Z) s/ (X << Z) --> Y s/ (1 << Z)
313+
311314
define i5 @sdiv_mul_shl_nsw_commute1(i5 %x, i5 %y, i5 %z) {
312315
; CHECK-LABEL: @sdiv_mul_shl_nsw_commute1(
313-
; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[Y:%.*]], [[X:%.*]]
314-
; CHECK-NEXT: [[M2:%.*]] = shl nsw i5 [[X]], [[Z:%.*]]
315-
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[M1]], [[M2]]
316+
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i5 1, [[Z:%.*]]
317+
; CHECK-NEXT: [[D:%.*]] = sdiv i5 [[Y:%.*]], [[TMP1]]
316318
; CHECK-NEXT: ret i5 [[D]]
317319
;
318320
%m1 = mul nsw i5 %y, %x
@@ -321,6 +323,8 @@ define i5 @sdiv_mul_shl_nsw_commute1(i5 %x, i5 %y, i5 %z) {
321323
ret i5 %d
322324
}
323325

326+
; negative test - shl is not commutative
327+
324328
define i5 @sdiv_mul_shl_nsw_commute2(i5 %x, i5 %y, i5 %z) {
325329
; CHECK-LABEL: @sdiv_mul_shl_nsw_commute2(
326330
; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[Y:%.*]], [[X:%.*]]
@@ -334,12 +338,14 @@ define i5 @sdiv_mul_shl_nsw_commute2(i5 %x, i5 %y, i5 %z) {
334338
ret i5 %d
335339
}
336340

341+
; extra use is ok
342+
337343
define i8 @sdiv_mul_shl_nsw_use1(i8 %x, i8 %y, i8 %z) {
338344
; CHECK-LABEL: @sdiv_mul_shl_nsw_use1(
339345
; CHECK-NEXT: [[M1:%.*]] = mul nsw i8 [[X:%.*]], [[Y:%.*]]
340346
; CHECK-NEXT: call void @use(i8 [[M1]])
341-
; CHECK-NEXT: [[M2:%.*]] = shl nsw i8 [[X]], [[Z:%.*]]
342-
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[M1]], [[M2]]
347+
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i8 1, [[Z:%.*]]
348+
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[Y]], [[TMP1]]
343349
; CHECK-NEXT: ret i8 [[D]]
344350
;
345351
%m1 = mul nsw i8 %x, %y
@@ -349,12 +355,14 @@ define i8 @sdiv_mul_shl_nsw_use1(i8 %x, i8 %y, i8 %z) {
349355
ret i8 %d
350356
}
351357

358+
; extra use is ok
359+
352360
define i8 @sdiv_mul_shl_nsw_use2(i8 %x, i8 %y, i8 %z) {
353361
; CHECK-LABEL: @sdiv_mul_shl_nsw_use2(
354-
; CHECK-NEXT: [[M1:%.*]] = mul nsw i8 [[X:%.*]], [[Y:%.*]]
355-
; CHECK-NEXT: [[M2:%.*]] = shl nsw i8 [[X]], [[Z:%.*]]
362+
; CHECK-NEXT: [[M2:%.*]] = shl nsw i8 [[X:%.*]], [[Z:%.*]]
356363
; CHECK-NEXT: call void @use(i8 [[M2]])
357-
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[M1]], [[M2]]
364+
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i8 1, [[Z]]
365+
; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[Y:%.*]], [[TMP1]]
358366
; CHECK-NEXT: ret i8 [[D]]
359367
;
360368
%m1 = mul nsw i8 %x, %y
@@ -364,6 +372,8 @@ define i8 @sdiv_mul_shl_nsw_use2(i8 %x, i8 %y, i8 %z) {
364372
ret i8 %d
365373
}
366374

375+
; negative test - both operands can't have extra uses
376+
367377
define i8 @sdiv_mul_shl_nsw_use3(i8 %x, i8 %y, i8 %z) {
368378
; CHECK-LABEL: @sdiv_mul_shl_nsw_use3(
369379
; CHECK-NEXT: [[M1:%.*]] = mul nsw i8 [[X:%.*]], [[Y:%.*]]
@@ -381,6 +391,8 @@ define i8 @sdiv_mul_shl_nsw_use3(i8 %x, i8 %y, i8 %z) {
381391
ret i8 %d
382392
}
383393

394+
; negative test - shl must be divisor
395+
384396
define i5 @sdiv_shl_mul_nsw(i5 %x, i5 %y, i5 %z) {
385397
; CHECK-LABEL: @sdiv_shl_mul_nsw(
386398
; CHECK-NEXT: [[M1:%.*]] = shl nsw i5 [[Z:%.*]], [[X:%.*]]
@@ -394,6 +406,8 @@ define i5 @sdiv_shl_mul_nsw(i5 %x, i5 %y, i5 %z) {
394406
ret i5 %d
395407
}
396408

409+
; negative test - wrong no-wrap
410+
397411
define i5 @sdiv_mul_shl_missing_nsw1(i5 %x, i5 %y, i5 %z) {
398412
; CHECK-LABEL: @sdiv_mul_shl_missing_nsw1(
399413
; CHECK-NEXT: [[M1:%.*]] = mul nsw i5 [[X:%.*]], [[Y:%.*]]
@@ -407,6 +421,8 @@ define i5 @sdiv_mul_shl_missing_nsw1(i5 %x, i5 %y, i5 %z) {
407421
ret i5 %d
408422
}
409423

424+
; negative test - wrong no-wrap
425+
410426
define i5 @sdiv_mul_shl_missing_nsw2(i5 %x, i5 %y, i5 %z) {
411427
; CHECK-LABEL: @sdiv_mul_shl_missing_nsw2(
412428
; CHECK-NEXT: [[M1:%.*]] = mul nuw i5 [[X:%.*]], [[Y:%.*]]

llvm/test/Transforms/PhaseOrdering/reassociate-instcombine.ll

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,7 @@ define i32 @not_reassociate_or_or_not(i32 %a, i32 %b, i32 %c, i32 %d) {
3939

4040
define i32 @PR58137(i32 %a, i32 %b) {
4141
; CHECK-LABEL: @PR58137(
42-
; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[A:%.*]], 1
43-
; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[MUL]], [[B:%.*]]
44-
; CHECK-NEXT: [[MUL2:%.*]] = shl nsw i32 [[A]], 1
45-
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[MUL1]], [[MUL2]]
46-
; CHECK-NEXT: ret i32 [[DIV]]
42+
; CHECK-NEXT: ret i32 [[B:%.*]]
4743
;
4844
%mul = mul nsw i32 2, %b
4945
%mul1 = mul nsw i32 %mul, %a

0 commit comments

Comments
 (0)