diff options
author | Chris Lattner <sabre@nondot.org> | 2006-01-30 04:09:27 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2006-01-30 04:09:27 +0000 |
commit | c6fd6cd65c88ef1f11da43c11be0152cb69013a7 (patch) | |
tree | c5b09429e2a6abe5bf4dd1ffd2598417f8f2bac2 /lib/CodeGen/SelectionDAG/TargetLowering.cpp | |
parent | 553d8007ad29ab4ba7be261e91c38556dccdd95e (diff) |
Move MaskedValueIsZero from the DAGCombiner to the TargetLowering interface,making isMaskedValueZeroForTargetNode simpler, and useable from other partsof the compiler.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25803 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/TargetLowering.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/TargetLowering.cpp | 109 |
1 files changed, 107 insertions, 2 deletions
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 2ee02ba5df..edb98f3817 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -16,6 +16,7 @@ #include "llvm/Target/MRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/MathExtras.h" using namespace llvm; TargetLowering::TargetLowering(TargetMachine &tm) @@ -130,9 +131,113 @@ const char *TargetLowering::getTargetNodeName(unsigned Opcode) const { return NULL; } + + +/// MaskedValueIsZero - Return true if 'Op & Mask' is known to be zero. We use +/// this predicate to simplify operations downstream. Op and Mask are known to +/// be the same type. +bool TargetLowering::MaskedValueIsZero(const SDOperand &Op, + uint64_t Mask) const { + unsigned SrcBits; + if (Mask == 0) return true; + + // If we know the result of a setcc has the top bits zero, use this info. + switch (Op.getOpcode()) { + case ISD::Constant: + return (cast<ConstantSDNode>(Op)->getValue() & Mask) == 0; + case ISD::SETCC: + return ((Mask & 1) == 0) && + getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult; + case ISD::ZEXTLOAD: + SrcBits = MVT::getSizeInBits(cast<VTSDNode>(Op.getOperand(3))->getVT()); + return (Mask & ((1ULL << SrcBits)-1)) == 0; // Returning only the zext bits. + case ISD::ZERO_EXTEND: + SrcBits = MVT::getSizeInBits(Op.getOperand(0).getValueType()); + return MaskedValueIsZero(Op.getOperand(0),Mask & (~0ULL >> (64-SrcBits))); + case ISD::AssertZext: + SrcBits = MVT::getSizeInBits(cast<VTSDNode>(Op.getOperand(1))->getVT()); + return (Mask & ((1ULL << SrcBits)-1)) == 0; // Returning only the zext bits. + case ISD::AND: + // If either of the operands has zero bits, the result will too. + if (MaskedValueIsZero(Op.getOperand(1), Mask) || + MaskedValueIsZero(Op.getOperand(0), Mask)) + return true; + // (X & C1) & C2 == 0 iff C1 & C2 == 0. + if (ConstantSDNode *AndRHS = dyn_cast<ConstantSDNode>(Op.getOperand(1))) + return MaskedValueIsZero(Op.getOperand(0),AndRHS->getValue() & Mask); + return false; + case ISD::OR: + case ISD::XOR: + return MaskedValueIsZero(Op.getOperand(0), Mask) && + MaskedValueIsZero(Op.getOperand(1), Mask); + case ISD::SELECT: + return MaskedValueIsZero(Op.getOperand(1), Mask) && + MaskedValueIsZero(Op.getOperand(2), Mask); + case ISD::SELECT_CC: + return MaskedValueIsZero(Op.getOperand(2), Mask) && + MaskedValueIsZero(Op.getOperand(3), Mask); + case ISD::SRL: + // (ushr X, C1) & C2 == 0 iff X & (C2 << C1) == 0 + if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { + uint64_t NewVal = Mask << ShAmt->getValue(); + SrcBits = MVT::getSizeInBits(Op.getValueType()); + if (SrcBits != 64) NewVal &= (1ULL << SrcBits)-1; + return MaskedValueIsZero(Op.getOperand(0), NewVal); + } + return false; + case ISD::SHL: + // (ushl X, C1) & C2 == 0 iff X & (C2 >> C1) == 0 + if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { + uint64_t NewVal = Mask >> ShAmt->getValue(); + return MaskedValueIsZero(Op.getOperand(0), NewVal); + } + return false; + case ISD::ADD: + // (add X, Y) & C == 0 iff (X&C)|(Y&C) == 0 and all bits are low bits. + if ((Mask&(Mask+1)) == 0) { // All low bits + if (MaskedValueIsZero(Op.getOperand(0), Mask) && + MaskedValueIsZero(Op.getOperand(1), Mask)) + return true; + } + break; + case ISD::SUB: + if (ConstantSDNode *CLHS = dyn_cast<ConstantSDNode>(Op.getOperand(0))) { + // We know that the top bits of C-X are clear if X contains less bits + // than C (i.e. no wrap-around can happen). For example, 20-X is + // positive if we can prove that X is >= 0 and < 16. + unsigned Bits = MVT::getSizeInBits(CLHS->getValueType(0)); + if ((CLHS->getValue() & (1 << (Bits-1))) == 0) { // sign bit clear + unsigned NLZ = CountLeadingZeros_64(CLHS->getValue()+1); + uint64_t MaskV = (1ULL << (63-NLZ))-1; + if (MaskedValueIsZero(Op.getOperand(1), ~MaskV)) { + // High bits are clear this value is known to be >= C. + unsigned NLZ2 = CountLeadingZeros_64(CLHS->getValue()); + if ((Mask & ((1ULL << (64-NLZ2))-1)) == 0) + return true; + } + } + } + break; + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + // Bit counting instructions can not set the high bits of the result + // register. The max number of bits sets depends on the input. + return (Mask & (MVT::getSizeInBits(Op.getValueType())*2-1)) == 0; + default: + // Allow the target to implement this method for its nodes. + if (Op.getOpcode() >= ISD::BUILTIN_OP_END) + return isMaskedValueZeroForTargetNode(Op, Mask); + break; + } + return false; +} + bool TargetLowering::isMaskedValueZeroForTargetNode(const SDOperand &Op, - uint64_t Mask, - MVIZFnPtr MVIZ) const { + uint64_t Mask) const { + assert(Op.getOpcode() >= ISD::BUILTIN_OP_END && + "Should use MaskedValueIsZero if you don't know whether Op" + " is a target node!"); return false; } |