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
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.
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:
""""""""
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
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()))
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
-}
; 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
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
; 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
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