]> granicus.if.org Git - llvm/commitdiff
[InstSimplify] vector div/rem with any zero element in divisor is undef
authorSanjay Patel <spatel@rotateright.com>
Thu, 9 Mar 2017 16:20:52 +0000 (16:20 +0000)
committerSanjay Patel <spatel@rotateright.com>
Thu, 9 Mar 2017 16:20:52 +0000 (16:20 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297390 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.rst
lib/Analysis/InstructionSimplify.cpp
test/Transforms/InstCombine/vector-urem.ll
test/Transforms/InstSimplify/div.ll
test/Transforms/InstSimplify/rem.ll

index cf09a89db33b194c84b9cf37c4f84bf7974ec79a..c5771ad5248d9fa8553de046a6af6000e2a52898 100644 (file)
@@ -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
index 369cf1dd118d0362b9a30c7be6dcacbd68529077..f63b1aea795e8a53c3c189833705e7cf91347f91 100644 (file)
@@ -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()))
index 6cecc16069d36b8f67c60704b5ed26da9c8696c7..34eebeef3bb1044e8fa8655f13c9feab1726f22c 100644 (file)
@@ -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
-}
index 3136f0242fa03b36aa44aa5be294623270a31379..f0d6fbb578bede24a90327782103da593001817f 100644 (file)
@@ -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
index 86b324e0bb5702ad345744d05cffcd6eee14fe9c..eaa59ba9108ef385916c68cd967c6c86cf2703e3 100644 (file)
@@ -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