[llvm] r370608 - [ConstantFolding] Fix 'undef' folding for @llvm.[us]{add, sub}.with.overflow ops (PR43188)

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 1 04:56:52 PDT 2019


Author: lebedevri
Date: Sun Sep  1 04:56:52 2019
New Revision: 370608

URL: http://llvm.org/viewvc/llvm-project?rev=370608&view=rev
Log:
[ConstantFolding] Fix 'undef' folding for @llvm.[us]{add,sub}.with.overflow ops (PR43188)

As we have already established/fixed in
  https://bugs.llvm.org/show_bug.cgi?id=42209
  https://reviews.llvm.org/D63065
  https://reviews.llvm.org/rL363522
the InstSimplify handling for @llvm.with.overflow ops with undefs
is correct. Therefore if ConstantFolding produces different results,
then it is wrong.

This duplication of code hints at the need for some refactoring,
but for now address the brokenness of ConstantFolding by
copying the known-good handling from rL363522.

Fixes https://bugs.llvm.org/show_bug.cgi?id=43188

Modified:
    llvm/trunk/lib/Analysis/ConstantFolding.cpp
    llvm/trunk/test/Transforms/ConstProp/overflow-ops.ll

Modified: llvm/trunk/lib/Analysis/ConstantFolding.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=370608&r1=370607&r2=370608&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ConstantFolding.cpp (original)
+++ llvm/trunk/lib/Analysis/ConstantFolding.cpp Sun Sep  1 04:56:52 2019
@@ -2041,20 +2041,27 @@ static Constant *ConstantFoldScalarCall2
 
     switch (IntrinsicID) {
     default: break;
+    case Intrinsic::usub_with_overflow:
+    case Intrinsic::ssub_with_overflow:
+    case Intrinsic::uadd_with_overflow:
+    case Intrinsic::sadd_with_overflow:
+      // X - undef -> { undef, false }
+      // undef - X -> { undef, false }
+      // X + undef -> { undef, false }
+      // undef + x -> { undef, false }
+      if (!C0 || !C1) {
+        return ConstantStruct::get(
+            cast<StructType>(Ty),
+            {UndefValue::get(Ty->getStructElementType(0)),
+             Constant::getNullValue(Ty->getStructElementType(1))});
+      }
+      LLVM_FALLTHROUGH;
     case Intrinsic::smul_with_overflow:
-    case Intrinsic::umul_with_overflow:
-      // Even if both operands are undef, we cannot fold muls to undef
-      // in the general case. For example, on i2 there are no inputs
-      // that would produce { i2 -1, i1 true } as the result.
+    case Intrinsic::umul_with_overflow: {
+      // undef * X -> { 0, false }
+      // X * undef -> { 0, false }
       if (!C0 || !C1)
         return Constant::getNullValue(Ty);
-      LLVM_FALLTHROUGH;
-    case Intrinsic::sadd_with_overflow:
-    case Intrinsic::uadd_with_overflow:
-    case Intrinsic::ssub_with_overflow:
-    case Intrinsic::usub_with_overflow: {
-      if (!C0 || !C1)
-        return UndefValue::get(Ty);
 
       APInt Res;
       bool Overflow;

Modified: llvm/trunk/test/Transforms/ConstProp/overflow-ops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ConstProp/overflow-ops.ll?rev=370608&r1=370607&r2=370608&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/ConstProp/overflow-ops.ll (original)
+++ llvm/trunk/test/Transforms/ConstProp/overflow-ops.ll Sun Sep  1 04:56:52 2019
@@ -1,5 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -constprop -S | FileCheck %s
+; RUN: opt < %s -constprop -S | FileCheck %s --check-prefixes=CHECK,CONSTPROP
+; RUN: opt < %s -instsimplify -S | FileCheck %s --check-prefixes=CHECK,INSTSIMPLIFY
+; We must *NOT* have any check-lines with prefixes other than CHECK here.
+; If we do, that means the rules are different between the passes.
 
 declare {i8, i1} @llvm.uadd.with.overflow.i8(i8, i8)
 declare {i8, i1} @llvm.usub.with.overflow.i8(i8, i8)
@@ -31,7 +34,7 @@ define {i8, i1} @uadd_2() nounwind {
 
 define {i8, i1} @uadd_undef() nounwind {
 ; CHECK-LABEL: @uadd_undef(
-; CHECK-NEXT:    ret { i8, i1 } undef
+; CHECK-NEXT:    ret { i8, i1 } { i8 undef, i1 false }
 ;
   %t = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 142, i8 undef)
   ret {i8, i1} %t
@@ -59,7 +62,7 @@ define {i8, i1} @usub_2() nounwind {
 
 define {i8, i1} @usub_undef() nounwind {
 ; CHECK-LABEL: @usub_undef(
-; CHECK-NEXT:    ret { i8, i1 } undef
+; CHECK-NEXT:    ret { i8, i1 } { i8 undef, i1 false }
 ;
   %t = call {i8, i1} @llvm.usub.with.overflow.i8(i8 4, i8 undef)
   ret {i8, i1} %t
@@ -147,7 +150,7 @@ define {i8, i1} @sadd_5() nounwind {
 
 define {i8, i1} @sadd_undef() nounwind {
 ; CHECK-LABEL: @sadd_undef(
-; CHECK-NEXT:    ret { i8, i1 } undef
+; CHECK-NEXT:    ret { i8, i1 } { i8 undef, i1 false }
 ;
   %t = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 undef, i8 -10)
   ret {i8, i1} %t
@@ -215,7 +218,7 @@ define {i8, i1} @ssub_5() nounwind {
 
 define {i8, i1} @ssub_undef() nounwind {
 ; CHECK-LABEL: @ssub_undef(
-; CHECK-NEXT:    ret { i8, i1 } undef
+; CHECK-NEXT:    ret { i8, i1 } { i8 undef, i1 false }
 ;
   %t = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 undef, i8 -10)
   ret {i8, i1} %t




More information about the llvm-commits mailing list