[DAGCombine] Fix demanded bits computation for exact shifts.

Fixes a miscompilation of MultiSource/Benchmarks/MallocBench/gs

llvm-svn: 240796
This commit is contained in:
Benjamin Kramer 2015-06-26 16:59:31 +00:00
parent 289ec857d2
commit 1dcd8b09b4
2 changed files with 32 additions and 1 deletions

View File

@ -700,6 +700,13 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
if (ShAmt >= BitWidth)
break;
APInt InDemandedMask = (NewMask << ShAmt);
// If the shift is exact, then it does demand the low bits (and knows that
// they are zero).
if (cast<BinaryWithFlagsSDNode>(Op)->Flags.hasExact())
InDemandedMask |= APInt::getLowBitsSet(BitWidth, ShAmt);
// If this is ((X << C1) >>u ShAmt), see if we can simplify this into a
// single shift. We can do this if the top bits (which are shifted out)
// are never demanded.
@ -722,7 +729,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
}
// Compute the new bits that are at the top now.
if (SimplifyDemandedBits(InOp, (NewMask << ShAmt),
if (SimplifyDemandedBits(InOp, InDemandedMask,
KnownZero, KnownOne, TLO, Depth+1))
return true;
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
@ -753,6 +760,11 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
APInt InDemandedMask = (NewMask << ShAmt);
// If the shift is exact, then it does demand the low bits (and knows that
// they are zero).
if (cast<BinaryWithFlagsSDNode>(Op)->Flags.hasExact())
InDemandedMask |= APInt::getLowBitsSet(BitWidth, ShAmt);
// If any of the demanded bits are produced by the sign extension, we also
// demand the input sign bit.
APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt);

View File

@ -193,3 +193,22 @@ define i32 @test11(i32 %b) {
; X32: movl $-2, %[[REG:.*]]
; X32: roll %{{.*}}, %[[REG]]
}
%struct.ref_s = type { %union.v, i16, i16 }
%union.v = type { i64 }
define %struct.ref_s* @test12(%struct.ref_s* %op, i64 %osbot, i64 %intval) {
%neg = shl i64 %intval, 32
%sext = xor i64 %neg, -4294967296
%idx.ext = ashr exact i64 %sext, 32
%add.ptr = getelementptr inbounds %struct.ref_s, %struct.ref_s* %op, i64 %idx.ext
ret %struct.ref_s* %add.ptr
; X64-LABEL: test12:
; X64: shlq $32, %[[REG:.*]]
; X64-NOT: not
; X64: sarq $28, %[[REG]]
; X32-LABEL: test12:
; X32: leal
; X32-NOT: not
; X32: shll $2, %eax
}