From 23a207d839e11123108fa799394ed383f0b6ee12 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Fri, 26 Jun 2015 16:59:31 +0000 Subject: [PATCH] [DAGCombine] Fix demanded bits computation for exact shifts. Fixes a miscompilation of MultiSource/Benchmarks/MallocBench/gs git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240796 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 14 +++++++++++++- test/CodeGen/X86/xor.ll | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index b40025b41f7..fc746588e69 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -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(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(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); diff --git a/test/CodeGen/X86/xor.ll b/test/CodeGen/X86/xor.ll index 829be41e512..0f6a601d954 100644 --- a/test/CodeGen/X86/xor.ll +++ b/test/CodeGen/X86/xor.ll @@ -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 +} -- 2.11.0