Skip to content

Commit 69339fc

Browse files
committed
[SelectionDAG] Add more cases for UDIV and SDIV
Ported from ValueTracking.
1 parent aea7403 commit 69339fc

File tree

2 files changed

+134
-3
lines changed

2 files changed

+134
-3
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5857,14 +5857,31 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
58575857
return true;
58585858
break;
58595859
}
5860-
case ISD::UDIV:
5861-
case ISD::SDIV:
5860+
case ISD::UDIV: {
58625861
// div exact can only produce a zero if the dividend is zero.
5863-
// TODO: For udiv this is also true if Op1 u<= Op0
58645862
if (Op->getFlags().hasExact())
58655863
return isKnownNeverZero(Op.getOperand(0), Depth + 1);
5864+
5865+
// If Op0 >= Op1, then the result is at least 1, and therefore not 0.
5866+
KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
5867+
KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
5868+
if (Op0.isStrictlyPositive() && Op1.isStrictlyPositive() &&
5869+
KnownBits::uge(Op0, Op1).value_or(false))
5870+
return true;
58665871
break;
5872+
}
5873+
case ISD::SDIV: {
5874+
// div exact can only produce a zero if the dividend is zero.
5875+
if (Op->getFlags().hasExact())
5876+
return isKnownNeverZero(Op.getOperand(0), Depth + 1);
58675877

5878+
KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
5879+
KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
5880+
if (Op0.isStrictlyPositive() && Op1.isStrictlyPositive() &&
5881+
KnownBits::uge(Op0, Op1).value_or(false))
5882+
return true;
5883+
break;
5884+
}
58685885
case ISD::ADD:
58695886
if (Op->getFlags().hasNoUnsignedWrap())
58705887
if (isKnownNeverZero(Op.getOperand(1), Depth + 1) ||

llvm/test/Analysis/ValueTracking/known-non-zero.ll

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,3 +1547,117 @@ define i1 @vec_reverse_non_zero_demanded_fail(<4 x i8> %xx) {
15471547
}
15481548

15491549
declare i32 @llvm.experimental.get.vector.length.i32(i32, i32, i1)
1550+
1551+
define i1 @sdiv_by_1_never_zero(i8 %x) {
1552+
; CHECK-LABEL: @sdiv_by_1_never_zero(
1553+
; CHECK-NEXT: ret i1 true
1554+
;
1555+
%nonzero = or i8 %x, 1 ; Make sure x is non-zero
1556+
%div = sdiv i8 %nonzero, 1
1557+
%cmp = icmp ne i8 %div, 0
1558+
ret i1 %cmp
1559+
}
1560+
1561+
define i1 @sdiv_by_neg1_never_zero(i8 %x) {
1562+
; CHECK-LABEL: @sdiv_by_neg1_never_zero(
1563+
; CHECK-NEXT: ret i1 true
1564+
;
1565+
%nonzero = or i8 %x, 1 ; Make sure x is non-zero
1566+
%div = sdiv i8 %nonzero, -1
1567+
%cmp = icmp ne i8 %div, 0
1568+
ret i1 %cmp
1569+
}
1570+
1571+
define i1 @udiv_by_1_never_zero(i8 %x) {
1572+
; CHECK-LABEL: @udiv_by_1_never_zero(
1573+
; CHECK-NEXT: ret i1 true
1574+
;
1575+
%nonzero = or i8 %x, 1 ; Make sure x is non-zero
1576+
%div = udiv i8 %nonzero, 1
1577+
%cmp = icmp ne i8 %div, 0
1578+
ret i1 %cmp
1579+
}
1580+
1581+
define i1 @sdiv_odd_by_pow2_never_zero(i8 %x) {
1582+
; CHECK-LABEL: @sdiv_odd_by_pow2_never_zero(
1583+
; CHECK-NEXT: ret i1 true
1584+
;
1585+
%odd = or i8 %x, 1 ; Make sure x is odd
1586+
%div = sdiv i8 %odd, 4
1587+
%cmp = icmp ne i8 %div, 0
1588+
ret i1 %cmp
1589+
}
1590+
1591+
define i1 @udiv_odd_by_pow2_never_zero(i8 %x) {
1592+
; CHECK-LABEL: @udiv_odd_by_pow2_never_zero(
1593+
; CHECK-NEXT: ret i1 true
1594+
;
1595+
%odd = or i8 %x, 1 ; Make sure x is odd
1596+
%div = udiv i8 %odd, 4
1597+
%cmp = icmp ne i8 %div, 0
1598+
ret i1 %cmp
1599+
}
1600+
1601+
1602+
define i1 @sdiv_odd_by_neg_pow2_never_zero(i8 %x) {
1603+
; CHECK-LABEL: @sdiv_odd_by_neg_pow2_never_zero(
1604+
; CHECK-NEXT: ret i1 true
1605+
;
1606+
%odd = or i8 %x, 1 ; Make sure x is odd
1607+
%div = sdiv i8 %odd, -4
1608+
%cmp = icmp ne i8 %div, 0
1609+
ret i1 %cmp
1610+
}
1611+
1612+
define i1 @udiv_dividend_ge_divisor_never_zero(i8 %x, i8 %y) {
1613+
; CHECK-LABEL: @udiv_dividend_ge_divisor_never_zero(
1614+
; CHECK-NEXT: [[NUM:%.*]] = or i8 [[X:%.*]], 16
1615+
; CHECK-NEXT: [[DENUM:%.*]] = and i8 [[Y:%.*]], 15
1616+
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[NUM]], [[DENUM]]
1617+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[DIV]], 0
1618+
; CHECK-NEXT: ret i1 [[CMP]]
1619+
;
1620+
%num = or i8 %x, 16 ; Ensure dividend is at least 16
1621+
%denum = and i8 %y, 15 ; Ensure divisor is at most 15
1622+
%div = udiv i8 %num, %denum
1623+
%cmp = icmp ne i8 %div, 0
1624+
ret i1 %cmp
1625+
}
1626+
1627+
define i1 @sdiv_abs_dividend_ge_abs_divisor_never_zero(i8 %x, i8 %y) {
1628+
; CHECK-LABEL: @sdiv_abs_dividend_ge_abs_divisor_never_zero(
1629+
; CHECK-NEXT: [[XX:%.*]] = or i8 [[X:%.*]], -64
1630+
; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 63
1631+
; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[XX]], [[YY]]
1632+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[DIV]], 0
1633+
; CHECK-NEXT: ret i1 [[CMP]]
1634+
;
1635+
%xx = or i8 %x, 192 ; Ensure dividend is at least 192 or at most -64
1636+
%yy = and i8 %y, 63 ; Ensure divisor is at most 63 and at least -63
1637+
%div = sdiv i8 %xx, %yy
1638+
%cmp = icmp ne i8 %div, 0
1639+
ret i1 %cmp
1640+
}
1641+
1642+
define i1 @udiv_exact_nonzero_dividend_never_zero(i8 %x) {
1643+
; CHECK-LABEL: @udiv_exact_nonzero_dividend_never_zero(
1644+
; CHECK-NEXT: ret i1 true
1645+
;
1646+
%num = or i8 %x, 1 ; Ensure dividend is non-zero
1647+
%denum = shl i8 1, 2 ; Divisor = 4
1648+
%div = udiv exact i8 %num, %denum
1649+
%cmp = icmp ne i8 %div, 0
1650+
ret i1 %cmp
1651+
}
1652+
1653+
; Test exact division with non-zero dividend guarantees non-zero result for SDIV
1654+
define i1 @sdiv_exact_nonzero_dividend_never_zero(i8 %x) {
1655+
; CHECK-LABEL: @sdiv_exact_nonzero_dividend_never_zero(
1656+
; CHECK-NEXT: ret i1 true
1657+
;
1658+
%num = or i8 %x, 1 ; Ensure dividend is non-zero
1659+
%denum = shl i8 1, 2 ; Divisor = 4
1660+
%div = sdiv exact i8 %num, %denum
1661+
%cmp = icmp ne i8 %div, 0
1662+
ret i1 %cmp
1663+
}

0 commit comments

Comments
 (0)