PR14562 - Truncation of left shift became undef

DAGCombiner::ReduceLoadWidth was converting (trunc i32 (shl i64 v, 32))
into (shl i32 v, 32) into undef. To prevent this, check the shift count
against the final result size.

Patch by: Kevin Schoedel
Reviewed by: Nadav Rotem

llvm-svn: 174972
This commit is contained in:
Paul Redmond 2013-02-12 15:21:21 +00:00
parent 71a4ab7141
commit 288604ed0c
2 changed files with 24 additions and 2 deletions

View File

@ -5163,8 +5163,15 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
EVT ShImmTy = getShiftAmountTy(Result.getValueType());
if (!isUIntN(ShImmTy.getSizeInBits(), ShLeftAmt))
ShImmTy = VT;
Result = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT,
Result, DAG.getConstant(ShLeftAmt, ShImmTy));
// If the shift amount is as large as the result size (but, presumably,
// no larger than the source) then the useful bits of the result are
// zero; we can't simply return the shortened shift, because the result
// of that operation is undefined.
if (ShLeftAmt >= VT.getSizeInBits())
Result = DAG.getConstant(0, VT);
else
Result = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT,
Result, DAG.getConstant(ShLeftAmt, ShImmTy));
}
// Return the new loaded value.

View File

@ -0,0 +1,15 @@
; RUN: llc < %s -march=x86 | FileCheck %s
@temp1 = global i64 -77129852189294865, align 8
define void @foo() nounwind {
%x = load i64* @temp1, align 8
%s = shl i64 %x, 32
%t = trunc i64 %s to i32
%z = zext i32 %t to i64
store i64 %z, i64* @temp1, align 8
; CHECK: movl $0, temp1+4
; CHECK: movl $0, temp1
ret void
}