[SCCP] Resolve shifts beyond the bitwidth to undef

Shifts beyond the bitwidth are undef but SCCP resolved them to zero.
Instead, DTRT and resolve them to undef.

This reimplements the transform which caused PR27712.

llvm-svn: 269269
This commit is contained in:
David Majnemer 2016-05-12 03:07:40 +00:00
parent 8300272823
commit 96f0d383a7
3 changed files with 115 additions and 0 deletions

View File

@ -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));

View File

@ -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()

View File

@ -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
}