forked from OSchip/llvm-project
[InstSimplify] vector div/rem with any zero element in divisor is undef
This was suggested as a DAG simplification in the review for rL297026 : http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20170306/435253.html ...but let's start with IR since we have actual docs for IR (LangRef). Differential Revision: https://reviews.llvm.org/D30665 llvm-svn: 297390
This commit is contained in:
parent
129edab125
commit
2b1f6f4b92
|
@ -6329,7 +6329,9 @@ The value produced is the unsigned integer quotient of the two operands.
|
|||
Note that unsigned integer division and signed integer division are
|
||||
distinct operations; for signed integer division, use '``sdiv``'.
|
||||
|
||||
Division by zero leads to undefined behavior.
|
||||
Division by zero is undefined behavior. For vectors, if any element
|
||||
of the divisor is zero, the operation has undefined behavior.
|
||||
|
||||
|
||||
If the ``exact`` keyword is present, the result value of the ``udiv`` is
|
||||
a :ref:`poison value <poisonvalues>` if %op1 is not a multiple of %op2 (as
|
||||
|
@ -6374,9 +6376,10 @@ rounded towards zero.
|
|||
Note that signed integer division and unsigned integer division are
|
||||
distinct operations; for unsigned integer division, use '``udiv``'.
|
||||
|
||||
Division by zero leads to undefined behavior. Overflow also leads to
|
||||
undefined behavior; this is a rare case, but can occur, for example, by
|
||||
doing a 32-bit division of -2147483648 by -1.
|
||||
Division by zero is undefined behavior. For vectors, if any element
|
||||
of the divisor is zero, the operation has undefined behavior.
|
||||
Overflow also leads to undefined behavior; this is a rare case, but can
|
||||
occur, for example, by doing a 32-bit division of -2147483648 by -1.
|
||||
|
||||
If the ``exact`` keyword is present, the result value of the ``sdiv`` is
|
||||
a :ref:`poison value <poisonvalues>` if the result would be rounded.
|
||||
|
@ -6459,8 +6462,10 @@ remainder.
|
|||
|
||||
Note that unsigned integer remainder and signed integer remainder are
|
||||
distinct operations; for signed integer remainder, use '``srem``'.
|
||||
|
||||
Taking the remainder of a division by zero leads to undefined behavior.
|
||||
|
||||
Taking the remainder of a division by zero is undefined behavior.
|
||||
For vectors, if any element of the divisor is zero, the operation has
|
||||
undefined behavior.
|
||||
|
||||
Example:
|
||||
""""""""
|
||||
|
@ -6510,7 +6515,9 @@ operation <http://en.wikipedia.org/wiki/Modulo_operation>`_.
|
|||
Note that signed integer remainder and unsigned integer remainder are
|
||||
distinct operations; for unsigned integer remainder, use '``urem``'.
|
||||
|
||||
Taking the remainder of a division by zero leads to undefined behavior.
|
||||
Taking the remainder of a division by zero is undefined behavior.
|
||||
For vectors, if any element of the divisor is zero, the operation has
|
||||
undefined behavior.
|
||||
Overflow also leads to undefined behavior; this is a rare case, but can
|
||||
occur, for example, by taking the remainder of a 32-bit division of
|
||||
-2147483648 by -1. (The remainder doesn't actually overflow, but this
|
||||
|
|
|
@ -1024,6 +1024,17 @@ static Value *simplifyDivRem(Value *Op0, Value *Op1, bool IsDiv) {
|
|||
if (match(Op1, m_Zero()))
|
||||
return UndefValue::get(Ty);
|
||||
|
||||
// If any element of a constant divisor vector is zero, the whole op is undef.
|
||||
auto *Op1C = dyn_cast<Constant>(Op1);
|
||||
if (Op1C && Ty->isVectorTy()) {
|
||||
unsigned NumElts = Ty->getVectorNumElements();
|
||||
for (unsigned i = 0; i != NumElts; ++i) {
|
||||
Constant *Elt = Op1C->getAggregateElement(i);
|
||||
if (Elt && Elt->isNullValue())
|
||||
return UndefValue::get(Ty);
|
||||
}
|
||||
}
|
||||
|
||||
// undef / X -> 0
|
||||
// undef % X -> 0
|
||||
if (match(Op0, m_Undef()))
|
||||
|
|
|
@ -19,11 +19,3 @@ define <4 x i32> @test_v4i32_const_pow2(<4 x i32> %a0) {
|
|||
ret <4 x i32> %1
|
||||
}
|
||||
|
||||
define <4 x i32> @test_v4i32_const_pow2_or_zero(<4 x i32> %a0) {
|
||||
; CHECK-LABEL: @test_v4i32_const_pow2_or_zero(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = urem <4 x i32> %a0, <i32 1, i32 2, i32 0, i32 8>
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP1]]
|
||||
;
|
||||
%1 = urem <4 x i32> %a0, <i32 1, i32 2, i32 0, i32 8>
|
||||
ret <4 x i32> %1
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
; RUN: opt < %s -instsimplify -S | FileCheck %s
|
||||
|
||||
; FIXME: Division-by-zero is undef. UB in any vector lane means the whole op is undef.
|
||||
; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
|
||||
|
||||
define <2 x i8> @sdiv_zero_elt_vec(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @sdiv_zero_elt_vec(
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i8> %x, <i8 -42, i8 0>
|
||||
; CHECK-NEXT: ret <2 x i8> [[DIV]]
|
||||
; CHECK-NEXT: ret <2 x i8> undef
|
||||
;
|
||||
%div = sdiv <2 x i8> %x, <i8 -42, i8 0>
|
||||
ret <2 x i8> %div
|
||||
|
@ -13,8 +12,7 @@ define <2 x i8> @sdiv_zero_elt_vec(<2 x i8> %x) {
|
|||
|
||||
define <2 x i8> @udiv_zero_elt_vec(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @udiv_zero_elt_vec(
|
||||
; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i8> %x, <i8 0, i8 42>
|
||||
; CHECK-NEXT: ret <2 x i8> [[DIV]]
|
||||
; CHECK-NEXT: ret <2 x i8> undef
|
||||
;
|
||||
%div = udiv <2 x i8> %x, <i8 0, i8 42>
|
||||
ret <2 x i8> %div
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
; NOTE: Assertions have been autogenerated by update_test_checks.py
|
||||
; RUN: opt < %s -instsimplify -S | FileCheck %s
|
||||
|
||||
; FIXME: Division-by-zero is undef. UB in any vector lane means the whole op is undef.
|
||||
; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
|
||||
|
||||
define <2 x i8> @srem_zero_elt_vec(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @srem_zero_elt_vec(
|
||||
; CHECK-NEXT: [[REM:%.*]] = srem <2 x i8> %x, <i8 -42, i8 0>
|
||||
; CHECK-NEXT: ret <2 x i8> [[REM]]
|
||||
; CHECK-NEXT: ret <2 x i8> undef
|
||||
;
|
||||
%rem = srem <2 x i8> %x, <i8 -42, i8 0>
|
||||
ret <2 x i8> %rem
|
||||
|
@ -14,8 +13,7 @@ define <2 x i8> @srem_zero_elt_vec(<2 x i8> %x) {
|
|||
|
||||
define <2 x i8> @urem_zero_elt_vec(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @urem_zero_elt_vec(
|
||||
; CHECK-NEXT: [[REM:%.*]] = urem <2 x i8> %x, <i8 0, i8 42>
|
||||
; CHECK-NEXT: ret <2 x i8> [[REM]]
|
||||
; CHECK-NEXT: ret <2 x i8> undef
|
||||
;
|
||||
%rem = urem <2 x i8> %x, <i8 0, i8 42>
|
||||
ret <2 x i8> %rem
|
||||
|
|
Loading…
Reference in New Issue