summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
diff options
context:
space:
mode:
authorSimon Pilgrim <llvm-dev@redking.me.uk>2017-07-25 16:36:44 +0000
committerSimon Pilgrim <llvm-dev@redking.me.uk>2017-07-25 16:36:44 +0000
commit6d599331750d6b87f268481559ad99a5a0ca08a0 (patch)
tree9fb5e6d2eeddec259ff852d4e0488641fddf1416 /llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
parent8d89179e33ef80f4c1f548ae2047420bcead2684 (diff)
downloadbcm5719-llvm-6d599331750d6b87f268481559ad99a5a0ca08a0.tar.gz
bcm5719-llvm-6d599331750d6b87f268481559ad99a5a0ca08a0.zip
[DAG] Move DAGCombiner::GetDemandedBits to SelectionDAG
This patch moves the DAGCombiner::GetDemandedBits function to SelectionDAG::GetDemandedBits as a first step towards making it easier for targets to get to the source of any demanded bits without the limitations of SimplifyDemandedBits. Differential Revision: https://reviews.llvm.org/D35841 llvm-svn: 308983
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp57
1 files changed, 54 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 823e77850c4..a81f4120620 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -1952,6 +1952,57 @@ SDValue SelectionDAG::FoldSetCC(EVT VT, SDValue N1, SDValue N2,
return SDValue();
}
+/// See if the specified operand can be simplified with the knowledge that only
+/// the bits specified by Mask are used.
+SDValue SelectionDAG::GetDemandedBits(SDValue V, const APInt &Mask) {
+ switch (V.getOpcode()) {
+ default:
+ break;
+ case ISD::Constant: {
+ const ConstantSDNode *CV = cast<ConstantSDNode>(V.getNode());
+ assert(CV && "Const value should be ConstSDNode.");
+ const APInt &CVal = CV->getAPIntValue();
+ APInt NewVal = CVal & Mask;
+ if (NewVal != CVal)
+ return getConstant(NewVal, SDLoc(V), V.getValueType());
+ break;
+ }
+ case ISD::OR:
+ case ISD::XOR:
+ // If the LHS or RHS don't contribute bits to the or, drop them.
+ if (MaskedValueIsZero(V.getOperand(0), Mask))
+ return V.getOperand(1);
+ if (MaskedValueIsZero(V.getOperand(1), Mask))
+ return V.getOperand(0);
+ break;
+ case ISD::SRL:
+ // Only look at single-use SRLs.
+ if (!V.getNode()->hasOneUse())
+ break;
+ if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(V.getOperand(1))) {
+ // See if we can recursively simplify the LHS.
+ unsigned Amt = RHSC->getZExtValue();
+
+ // Watch out for shift count overflow though.
+ if (Amt >= Mask.getBitWidth())
+ break;
+ APInt NewMask = Mask << Amt;
+ if (SDValue SimplifyLHS = GetDemandedBits(V.getOperand(0), NewMask))
+ return getNode(ISD::SRL, SDLoc(V), V.getValueType(), SimplifyLHS,
+ V.getOperand(1));
+ }
+ break;
+ case ISD::AND: {
+ // X & -1 -> X (ignoring bits which aren't demanded).
+ ConstantSDNode *AndVal = isConstOrConstSplat(V.getOperand(1));
+ if (AndVal && Mask.isSubsetOf(AndVal->getAPIntValue()))
+ return V.getOperand(0);
+ break;
+ }
+ }
+ return SDValue();
+}
+
/// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We
/// use this predicate to simplify operations downstream.
bool SelectionDAG::SignBitIsZero(SDValue Op, unsigned Depth) const {
@@ -6578,7 +6629,7 @@ SDNode* SelectionDAG::mutateStrictFPToFP(SDNode *Node) {
unsigned NewOpc;
bool IsUnary = false;
switch (OrigOpc) {
- default:
+ default:
llvm_unreachable("mutateStrictFPToFP called with unexpected opcode!");
case ISD::STRICT_FADD: NewOpc = ISD::FADD; break;
case ISD::STRICT_FSUB: NewOpc = ISD::FSUB; break;
@@ -6614,7 +6665,7 @@ SDNode* SelectionDAG::mutateStrictFPToFP(SDNode *Node) {
else
Res = MorphNodeTo(Node, NewOpc, VTs, { Node->getOperand(1),
Node->getOperand(2) });
-
+
// MorphNodeTo can operate in two ways: if an existing node with the
// specified operands exists, it can just return it. Otherwise, it
// updates the node in place to have the requested operands.
@@ -6627,7 +6678,7 @@ SDNode* SelectionDAG::mutateStrictFPToFP(SDNode *Node) {
RemoveDeadNode(Node);
}
- return Res;
+ return Res;
}
/// getMachineNode - These are used for target selectors to create a new node
OpenPOWER on IntegriCloud