summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2019-09-01 11:56:52 +0000
committerRoman Lebedev <lebedev.ri@gmail.com>2019-09-01 11:56:52 +0000
commitff21e3f055adf52972c9ead61452ccce25dc677b (patch)
tree6b764f13f7c3e49db11bd474193de73b02ebbe74
parent8469a39af3d3db83cf87803b1ea56e22cb522445 (diff)
downloadbcm5719-llvm-ff21e3f055adf52972c9ead61452ccce25dc677b.tar.gz
bcm5719-llvm-ff21e3f055adf52972c9ead61452ccce25dc677b.zip
[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 llvm-svn: 370608
-rw-r--r--llvm/lib/Analysis/ConstantFolding.cpp29
-rw-r--r--llvm/test/Transforms/ConstProp/overflow-ops.ll13
2 files changed, 26 insertions, 16 deletions
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index f7cc53b345f..cedd788d226 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -2041,20 +2041,27 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
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;
diff --git a/llvm/test/Transforms/ConstProp/overflow-ops.ll b/llvm/test/Transforms/ConstProp/overflow-ops.ll
index 303b3b90ab3..1d090d5d0ea 100644
--- a/llvm/test/Transforms/ConstProp/overflow-ops.ll
+++ b/llvm/test/Transforms/ConstProp/overflow-ops.ll
@@ -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
OpenPOWER on IntegriCloud