summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/Scalar/SCCP.cpp16
-rw-r--r--llvm/test/Transforms/SCCP/pr27712.ll30
-rw-r--r--llvm/test/Transforms/SCCP/ub-shift.ll69
3 files changed, 115 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp
index 75414ef3864..c75c948329c 100644
--- a/llvm/lib/Transforms/Scalar/SCCP.cpp
+++ b/llvm/lib/Transforms/Scalar/SCCP.cpp
@@ -1416,6 +1416,14 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// X >>a undef -> undef.
if (Op1LV.isUndefined()) break;
+ // Shifting by the bitwidth or more is undefined.
+ if (Op1LV.isConstant()) {
+ auto *ShiftAmt = Op1LV.getConstantInt();
+ if (ShiftAmt->getLimitedValue() >=
+ ShiftAmt->getType()->getScalarSizeInBits())
+ break;
+ }
+
// undef >>a X -> all ones
markForcedConstant(&I, Constant::getAllOnesValue(ITy));
return true;
@@ -1425,6 +1433,14 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// X >> undef -> undef.
if (Op1LV.isUndefined()) break;
+ // Shifting by the bitwidth or more is undefined.
+ if (Op1LV.isConstant()) {
+ auto *ShiftAmt = Op1LV.getConstantInt();
+ if (ShiftAmt->getLimitedValue() >=
+ ShiftAmt->getType()->getScalarSizeInBits())
+ break;
+ }
+
// undef << X -> 0
// undef >> X -> 0
markForcedConstant(&I, Constant::getNullValue(ITy));
diff --git a/llvm/test/Transforms/SCCP/pr27712.ll b/llvm/test/Transforms/SCCP/pr27712.ll
new file mode 100644
index 00000000000..b41c3981d53
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/pr27712.ll
@@ -0,0 +1,30 @@
+; RUN: opt -sccp -S < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() {
+entry:
+ br label %lbl_1154
+
+lbl_1154:
+ %b0.0 = phi i32 [ -119, %entry ], [ 0, %lbl_1154 ]
+ %cmp11 = icmp slt i32 %b0.0, 0
+ %shl.op = shl i32 33554432, %b0.0
+ %cmp1445 = icmp ult i32 %shl.op, 33554432
+ %cmp14 = or i1 %cmp11, %cmp1445
+ br i1 %cmp14, label %lbl_1154, label %if.end19
+
+if.end19:
+ br i1 %cmp11, label %if.then22, label %cleanup26
+
+if.then22:
+ tail call void @abort()
+ unreachable
+
+cleanup26:
+ ret i32 %shl.op
+}
+; CHECK-LABEL: define i32 @main(
+; CHECK-NOT: ret i32 undef
+
+declare void @abort()
diff --git a/llvm/test/Transforms/SCCP/ub-shift.ll b/llvm/test/Transforms/SCCP/ub-shift.ll
new file mode 100644
index 00000000000..3fb2d97457d
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/ub-shift.ll
@@ -0,0 +1,69 @@
+; RUN: opt < %s -sccp -S | FileCheck %s
+
+; CHECK-LABEL: shift_undef_64
+define void @shift_undef_64(i64* %p) {
+ %r1 = lshr i64 -1, 4294967296 ; 2^32
+ ; CHECK: store i64 undef
+ store i64 %r1, i64* %p
+
+ %r2 = ashr i64 -1, 4294967297 ; 2^32 + 1
+ ; CHECK: store i64 undef
+ store i64 %r2, i64* %p
+
+ %r3 = shl i64 -1, 4294967298 ; 2^32 + 2
+ ; CHECK: store i64 undef
+ store i64 %r3, i64* %p
+
+ ret void
+}
+
+; CHECK-LABEL: shift_undef_65
+define void @shift_undef_65(i65* %p) {
+ %r1 = lshr i65 2, 18446744073709551617
+ ; CHECK: store i65 undef
+ store i65 %r1, i65* %p
+
+ %r2 = ashr i65 4, 18446744073709551617
+ ; CHECK: store i65 undef
+ store i65 %r2, i65* %p
+
+ %r3 = shl i65 1, 18446744073709551617
+ ; CHECK: store i65 undef
+ store i65 %r3, i65* %p
+
+ ret void
+}
+
+; CHECK-LABEL: shift_undef_256
+define void @shift_undef_256(i256* %p) {
+ %r1 = lshr i256 2, 18446744073709551617
+ ; CHECK: store i256 undef
+ store i256 %r1, i256* %p
+
+ %r2 = ashr i256 4, 18446744073709551618
+ ; CHECK: store i256 undef
+ store i256 %r2, i256* %p
+
+ %r3 = shl i256 1, 18446744073709551619
+ ; CHECK: store i256 undef
+ store i256 %r3, i256* %p
+
+ ret void
+}
+
+; CHECK-LABEL: shift_undef_511
+define void @shift_undef_511(i511* %p) {
+ %r1 = lshr i511 -1, 1208925819614629174706276 ; 2^80 + 100
+ ; CHECK: store i511 undef
+ store i511 %r1, i511* %p
+
+ %r2 = ashr i511 -2, 1208925819614629174706200
+ ; CHECK: store i511 undef
+ store i511 %r2, i511* %p
+
+ %r3 = shl i511 -3, 1208925819614629174706180
+ ; CHECK: store i511 undef
+ store i511 %r3, i511* %p
+
+ ret void
+}
OpenPOWER on IntegriCloud