Skip to content

Commit c350a1e

Browse files
authored
[InstCombine] Simplifiy sdiv -X, X into X == INT_MIN ? 1 : -1 (#71768)
Alive2: https://alive2.llvm.org/ce/z/dHddwH Fixes #69574
1 parent 097ba53 commit c350a1e

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,13 @@ Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) {
15441544
}
15451545
}
15461546

1547+
// -X / X --> X == INT_MIN ? 1 : -1
1548+
if (isKnownNegation(Op0, Op1)) {
1549+
APInt MinVal = APInt::getSignedMinValue(Ty->getScalarSizeInBits());
1550+
Value *Cond = Builder.CreateICmpEQ(Op0, ConstantInt::get(Ty, MinVal));
1551+
return SelectInst::Create(Cond, ConstantInt::get(Ty, 1),
1552+
ConstantInt::getAllOnesValue(Ty));
1553+
}
15471554
return nullptr;
15481555
}
15491556

llvm/test/Transforms/InstCombine/div.ll

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,88 @@ define <2 x i8> @sdiv_sdiv_mul_nsw(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
14321432
ret <2 x i8> %r
14331433
}
14341434

1435+
define i32 @sdiv_sub1(i32 %arg) {
1436+
; CHECK-LABEL: @sdiv_sub1(
1437+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG:%.*]], -2147483648
1438+
; CHECK-NEXT: [[DIV:%.*]] = select i1 [[TMP1]], i32 1, i32 -1
1439+
; CHECK-NEXT: ret i32 [[DIV]]
1440+
;
1441+
%neg = sub i32 0, %arg
1442+
%div = sdiv i32 %neg, %arg
1443+
ret i32 %div
1444+
}
1445+
1446+
define i32 @sdiv_sub2(i32 %arg) {
1447+
; CHECK-LABEL: @sdiv_sub2(
1448+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG:%.*]], -2147483648
1449+
; CHECK-NEXT: [[DIV:%.*]] = select i1 [[TMP1]], i32 1, i32 -1
1450+
; CHECK-NEXT: ret i32 [[DIV]]
1451+
;
1452+
%neg = sub i32 0, %arg
1453+
%div = sdiv i32 %arg, %neg
1454+
ret i32 %div
1455+
}
1456+
1457+
define i32 @sub_sdiv_multiuse(i32 %arg) {
1458+
; CHECK-LABEL: @sub_sdiv_multiuse(
1459+
; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[ARG:%.*]]
1460+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG]], -2147483648
1461+
; CHECK-NEXT: [[DIV:%.*]] = select i1 [[TMP1]], i32 1, i32 -1
1462+
; CHECK-NEXT: call void @use(i32 [[NEG]])
1463+
; CHECK-NEXT: ret i32 [[DIV]]
1464+
;
1465+
%neg = sub i32 0, %arg
1466+
%div = sdiv i32 %arg, %neg
1467+
call void @use(i32 %neg)
1468+
ret i32 %div
1469+
}
1470+
1471+
define i32 @sdiv_sub_sub(i32 %x ,i32 %y) {
1472+
; CHECK-LABEL: @sdiv_sub_sub(
1473+
; CHECK-NEXT: [[S:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
1474+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[S]], -2147483648
1475+
; CHECK-NEXT: [[D:%.*]] = select i1 [[TMP1]], i32 1, i32 -1
1476+
; CHECK-NEXT: ret i32 [[D]]
1477+
;
1478+
%s = sub i32 %x, %y
1479+
%u = sub i32 %y, %x
1480+
%d = sdiv i32 %s, %u
1481+
ret i32 %d
1482+
}
1483+
1484+
define i32 @sdiv_mul_sub(i32 %x, i32 %y) {
1485+
; CHECK-LABEL: @sdiv_mul_sub(
1486+
; CHECK-NEXT: [[M:%.*]] = mul i32 [[Y:%.*]], [[X:%.*]]
1487+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[M]], -2147483648
1488+
; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 1, i32 -1
1489+
; CHECK-NEXT: ret i32 [[R]]
1490+
;
1491+
%m = mul i32 %y, %x
1492+
%d = sub i32 0, %m
1493+
%r = sdiv i32 %d, %m
1494+
ret i32 %r
1495+
}
1496+
1497+
define i32 @sdiv_mul_sub_nsw(i32 %x, i32 %y) {
1498+
; CHECK-LABEL: @sdiv_mul_sub_nsw(
1499+
; CHECK-NEXT: ret i32 -1
1500+
;
1501+
%m = mul i32 %y, %x
1502+
%n = sub nsw i32 0, %m
1503+
%d = sdiv i32 %m, %n
1504+
ret i32 %d
1505+
}
1506+
1507+
define i32 @sdiv_mul_nsw_sub_nsw(i32 %x, i32 %y) {
1508+
; CHECK-LABEL: @sdiv_mul_nsw_sub_nsw(
1509+
; CHECK-NEXT: ret i32 -1
1510+
;
1511+
%m = mul nsw i32 %y, %x
1512+
%n = sub nsw i32 0, %m
1513+
%d = sdiv i32 %m, %n
1514+
ret i32 %d
1515+
}
1516+
14351517
; exact propagates
14361518

14371519
define i8 @sdiv_sdiv_mul_nsw_exact_exact(i8 %x, i8 %y, i8 %z) {

0 commit comments

Comments
 (0)