diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index e23f32d9d7b..beb1cc9ff67 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -214,12 +214,18 @@ public: private: void DeleteNodeIfDead(SDNode *N, void *NodeSet); - // Try to simplify a setcc built with the specified operands and cc. If - // unable to simplify it, return a null SDOperand. + /// SimplifySetCC - Try to simplify a setcc built with the specified operands + /// and cc. If unable to simplify it, return a null SDOperand. SDOperand SimplifySetCC(MVT::ValueType VT, SDOperand N1, SDOperand N2, ISD::CondCode Cond); - + /// SimplifySelectCC - Try to simplify a select_cc built with the specified + /// operands and cc. This can be used to simplify both the select_cc node, + /// and a select node whose first operand is a setcc. + SDOperand SimplifySelectCC(MVT::ValueType VT, ISD::CondCode CC, + SDOperand N1, SDOperand N2, SDOperand N3, + SDOperand N4); + // Maps to auto-CSE operations. std::map >, SDNode *> UnaryOps; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 342148adb4a..9da30f1cf50 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -686,6 +686,80 @@ SDOperand SelectionDAG::SimplifySetCC(MVT::ValueType VT, SDOperand N1, return SDOperand(); } +SDOperand SelectionDAG::SimplifySelectCC(MVT::ValueType VT, ISD::CondCode CC, + SDOperand N1, SDOperand N2, SDOperand N3, + SDOperand N4) { + ConstantSDNode *N2C = dyn_cast(N2.Val); + ConstantSDNode *N3C = dyn_cast(N3.Val); + ConstantSDNode *N4C = dyn_cast(N4.Val); + + // Check to see if we can simplify the select into an fabs node + if (ConstantFPSDNode *CFP = dyn_cast(N2)) { + // Allow either -0.0 or 0.0 + if (CFP->getValue() == 0.0) { + // select (setg[te] X, +/-0.0), X, fneg(X) -> fabs + if ((CC == ISD::SETGE || CC == ISD::SETGT) && + N1 == N3 && N4.getOpcode() == ISD::FNEG && + N1 == N4.getOperand(0)) + return getNode(ISD::FABS, VT, N1); + + // select (setl[te] X, +/-0.0), fneg(X), X -> fabs + if ((CC == ISD::SETLT || CC == ISD::SETLE) && + N1 == N4 && N3.getOpcode() == ISD::FNEG && + N3.getOperand(0) == N4) + return getNode(ISD::FABS, VT, N4); + } + } + + // Check to see if we can perform the "gzip trick", transforming + // select_cc setlt X, 0, A, 0 -> and (sra X, size(X)-1), A + if (N2C && N2C->isNullValue() && N4C && N4C->isNullValue() && + MVT::isInteger(N1.getValueType()) && + MVT::isInteger(N3.getValueType()) && CC == ISD::SETLT) { + MVT::ValueType XType = N1.getValueType(); + MVT::ValueType AType = N3.getValueType(); + if (XType >= AType) { + // and (sra X, size(X)-1, A) -> "and (srl X, C2), A" iff A is a + // single-bit constant. FIXME: remove once the dag combiner + // exists. + if (N3C && ((N3C->getValue() & (N3C->getValue()-1)) == 0)) { + unsigned ShCtV = Log2_64(N3C->getValue()); + ShCtV = MVT::getSizeInBits(XType)-ShCtV-1; + SDOperand ShCt = getConstant(ShCtV, TLI.getShiftAmountTy()); + SDOperand Shift = getNode(ISD::SRL, XType, N1, ShCt); + if (XType > AType) + Shift = getNode(ISD::TRUNCATE, AType, Shift); + return getNode(ISD::AND, AType, Shift, N3); + } + SDOperand Shift = getNode(ISD::SRA, XType, N1, + getConstant(MVT::getSizeInBits(XType)-1, + TLI.getShiftAmountTy())); + if (XType > AType) + Shift = getNode(ISD::TRUNCATE, AType, Shift); + return getNode(ISD::AND, AType, Shift, N3); + } + } + + // Check to see if this is an integer abs. select_cc setl[te] X, 0, -X, X -> + // Y = sra (X, size(X)-1); xor (add (X, Y), Y) + if (N2C && N2C->isNullValue() && (CC == ISD::SETLT || CC == ISD::SETLE) && + N1 == N4 && N3.getOpcode() == ISD::SUB && N1 == N3.getOperand(1)) { + if (ConstantSDNode *SubC = dyn_cast(N3.getOperand(0))) { + MVT::ValueType XType = N1.getValueType(); + if (SubC->isNullValue() && MVT::isInteger(XType)) { + SDOperand Shift = getNode(ISD::SRA, XType, N1, + getConstant(MVT::getSizeInBits(XType)-1, + TLI.getShiftAmountTy())); + return getNode(ISD::XOR, XType, getNode(ISD::ADD, XType, N1, Shift), + Shift); + } + } + } + + // Could not fold it. + return SDOperand(); +} + /// getNode - Gets or creates the specified node. /// SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT) { @@ -1415,6 +1489,12 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, if (N1 == N3) // X ? Y : X --> X ? Y : 0 --> X & Y return getNode(ISD::AND, VT, N1, N2); } + if (N1.getOpcode() == ISD::SETCC) { + SDOperand Simp = SimplifySelectCC(VT, + cast(N1.getOperand(2))->get(), + N1.getOperand(0), N1.getOperand(1), N2, N3); + if (Simp.Val) return Simp; + } break; case ISD::BRCOND: if (N2C) @@ -1461,74 +1541,9 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, "LHS and RHS of condition must have same type!"); assert(N3.getValueType() == N4.getValueType() && "True and False arms of SelectCC must have same type!"); - - ConstantSDNode *N2C = dyn_cast(N2.Val); - ConstantSDNode *N3C = dyn_cast(N3.Val); - ConstantSDNode *N4C = dyn_cast(N4.Val); - ISD::CondCode CC = cast(N5)->get(); - - // Check to see if we can simplify the select into an fabs node - if (ConstantFPSDNode *CFP = dyn_cast(N2)) { - // Allow either -0.0 or 0.0 - if (CFP->getValue() == 0.0) { - // select (setg[te] X, +/-0.0), X, fneg(X) -> fabs - if ((CC == ISD::SETGE || CC == ISD::SETGT) && - N1 == N3 && N4.getOpcode() == ISD::FNEG && - N1 == N4.getOperand(0)) - return getNode(ISD::FABS, VT, N1); - - // select (setl[te] X, +/-0.0), fneg(X), X -> fabs - if ((CC == ISD::SETLT || CC == ISD::SETLE) && - N1 == N4 && N3.getOpcode() == ISD::FNEG && - N3.getOperand(0) == N4) - return getNode(ISD::FABS, VT, N4); - } - } - - // Check to see if we can perform the "gzip trick", transforming - // select_cc setlt X, 0, A, 0 -> and (sra X, size(X)-1), A - if (N2C && N2C->isNullValue() && N4C && N4C->isNullValue() && - MVT::isInteger(N1.getValueType()) && - MVT::isInteger(N3.getValueType()) && CC == ISD::SETLT) { - MVT::ValueType XType = N1.getValueType(); - MVT::ValueType AType = N3.getValueType(); - if (XType >= AType) { - // and (sra X, size(X)-1, A) -> "and (srl X, C2), A" iff A is a - // single-bit constant. FIXME: remove once the dag combiner - // exists. - if (N3C && ((N3C->getValue() & (N3C->getValue()-1)) == 0)) { - unsigned ShCtV = Log2_64(N3C->getValue()); - ShCtV = MVT::getSizeInBits(XType)-ShCtV-1; - SDOperand ShCt = getConstant(ShCtV, TLI.getShiftAmountTy()); - SDOperand Shift = getNode(ISD::SRL, XType, N1, ShCt); - if (XType > AType) - Shift = getNode(ISD::TRUNCATE, AType, Shift); - return getNode(ISD::AND, AType, Shift, N3); - } - SDOperand Shift = getNode(ISD::SRA, XType, N1, - getConstant(MVT::getSizeInBits(XType)-1, - TLI.getShiftAmountTy())); - if (XType > AType) - Shift = getNode(ISD::TRUNCATE, AType, Shift); - return getNode(ISD::AND, AType, Shift, N3); - } - } - - // Check to see if this is an integer abs. select_cc setl[te] X, 0, -X, X -> - // Y = sra (X, size(X)-1); xor (add (X, Y), Y) - if (N2C && N2C->isNullValue() && (CC == ISD::SETLT || CC == ISD::SETLE) && - N1 == N4 && N3.getOpcode() == ISD::SUB && N1 == N3.getOperand(1)) { - if (ConstantSDNode *SubC = dyn_cast(N3.getOperand(0))) { - MVT::ValueType XType = N1.getValueType(); - if (SubC->isNullValue() && MVT::isInteger(XType)) { - SDOperand Shift = getNode(ISD::SRA, XType, N1, - getConstant(MVT::getSizeInBits(XType)-1, - TLI.getShiftAmountTy())); - return getNode(ISD::XOR, XType, getNode(ISD::ADD, XType, N1, Shift), - Shift); - } - } - } + SDOperand Simp = SimplifySelectCC(VT, cast(N5)->get(), N1, + N2, N3, N4); + if (Simp.Val) return Simp; } std::vector Ops;