diff options
-rw-r--r-- | lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 28 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 1 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 7 | ||||
-rw-r--r-- | test/Transforms/InstCombine/2012-07-11-AddSubDemandedBits.ll | 18 |
4 files changed, 29 insertions, 25 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0e5ecd5..013e8be 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2716,6 +2716,34 @@ SDValue DAGCombiner::visitAND(SDNode *N) { } } + if (N0.getOpcode() == ISD::ADD && N1.getOpcode() == ISD::SRL && + VT.getSizeInBits() <= 64) { + if (ConstantSDNode *ADDI = dyn_cast<ConstantSDNode>(N0.getOperand(1))) { + APInt ADDC = ADDI->getAPIntValue(); + if (!TLI.isLegalAddImmediate(ADDC.getSExtValue())) { + // Look for (and (add x, c1), (lshr y, c2)). If C1 wasn't a legal + // immediate for an add, but it is legal if its top c2 bits are set, + // transform the ADD so the immediate doesn't need to be materialized + // in a register. + if (ConstantSDNode *SRLI = dyn_cast<ConstantSDNode>(N1.getOperand(1))) { + APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), + SRLI->getZExtValue()); + if (DAG.MaskedValueIsZero(N0.getOperand(1), Mask)) { + ADDC |= Mask; + if (TLI.isLegalAddImmediate(ADDC.getSExtValue())) { + SDValue NewAdd = + DAG.getNode(ISD::ADD, N0.getDebugLoc(), VT, + N0.getOperand(0), DAG.getConstant(ADDC, VT)); + CombineTo(N0.getNode(), NewAdd); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + } + } + } + } + + return SDValue(); } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 4f642ec..e9c60ae 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -11345,6 +11345,7 @@ bool X86TargetLowering::isLegalICmpImmediate(int64_t Imm) const { } bool X86TargetLowering::isLegalAddImmediate(int64_t Imm) const { + // Can also use sub to handle negated immediates. return Imm == (int32_t)Imm; } diff --git a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 0a62242..125c74a 100644 --- a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -40,13 +40,6 @@ static bool ShrinkDemandedConstant(Instruction *I, unsigned OpNo, // This instruction is producing bits that are not demanded. Shrink the RHS. Demanded &= OpC->getValue(); - if (I->getOpcode() == Instruction::Add) { - // However, if the instruction is an add then the constant may be negated - // when the opcode is changed to sub. Check if the transformation is really - // shrinking the constant. - if (Demanded.abs().getActiveBits() > OpC->getValue().abs().getActiveBits()) - return false; - } I->setOperand(OpNo, ConstantInt::get(OpC->getType(), Demanded)); return true; } diff --git a/test/Transforms/InstCombine/2012-07-11-AddSubDemandedBits.ll b/test/Transforms/InstCombine/2012-07-11-AddSubDemandedBits.ll deleted file mode 100644 index d62a886..0000000 --- a/test/Transforms/InstCombine/2012-07-11-AddSubDemandedBits.ll +++ /dev/null @@ -1,18 +0,0 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s - -; When shrinking demanded constant operand of an add instruction, keep in -; mind the opcode can be changed to sub and the constant negated. Make sure -; the shrinking the constant would actually reduce the width. -; rdar://11793464 - -define i64 @t(i64 %key, i64* %val) nounwind { -entry: -; CHECK: @t -; CHECK-NOT: add i64 %0, 2305843009213693951 -; CHECK: add i64 %0, -1 - %shr = lshr i64 %key, 3 - %0 = load i64* %val, align 8 - %sub = sub i64 %0, 1 - %and = and i64 %sub, %shr - ret i64 %and -} |