diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 101ce81d4486..6fd1fe4b789d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1081,6 +1081,16 @@ SDOperand DAGCombiner::visitOR(SDNode *N) { WorkList.push_back(ORNode.Val); return DAG.getNode(ISD::ZERO_EXTEND, VT, ORNode); } + // fold (or (shl/srl/sra x), (shl/srl/sra y)) -> (shl/srl/sra (or x, y)) + if (((N0.getOpcode() == ISD::SHL && N1.getOpcode() == ISD::SHL) || + (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SRL) || + (N0.getOpcode() == ISD::SRA && N1.getOpcode() == ISD::SRA)) && + N0.getOperand(1) == N1.getOperand(1)) { + SDOperand ORNode = DAG.getNode(ISD::OR, N0.getOperand(0).getValueType(), + N0.getOperand(0), N1.getOperand(0)); + WorkList.push_back(ORNode.Val); + return DAG.getNode(N0.getOpcode(), VT, ORNode, N0.getOperand(1)); + } // canonicalize shl to left side in a shl/srl pair, to match rotate if (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SHL) std::swap(N0, N1); @@ -1196,6 +1206,16 @@ SDOperand DAGCombiner::visitXOR(SDNode *N) { WorkList.push_back(XORNode.Val); return DAG.getNode(ISD::ZERO_EXTEND, VT, XORNode); } + // fold (xor (shl/srl/sra x), (shl/srl/sra y)) -> (shl/srl/sra (xor x, y)) + if (((N0.getOpcode() == ISD::SHL && N1.getOpcode() == ISD::SHL) || + (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SRL) || + (N0.getOpcode() == ISD::SRA && N1.getOpcode() == ISD::SRA)) && + N0.getOperand(1) == N1.getOperand(1)) { + SDOperand XORNode = DAG.getNode(ISD::XOR, N0.getOperand(0).getValueType(), + N0.getOperand(0), N1.getOperand(0)); + WorkList.push_back(XORNode.Val); + return DAG.getNode(N0.getOpcode(), VT, XORNode, N0.getOperand(1)); + } return SDOperand(); } @@ -1396,14 +1416,20 @@ SDOperand DAGCombiner::visitSELECT(SDNode *N) { // fold X ? Y : X --> X ? Y : 0 --> X & Y if (MVT::i1 == VT && N0 == N2) return DAG.getNode(ISD::AND, VT, N0, N1); - // If we can fold this based on the true/false value, do so. if (SimplifySelectOps(N, N1, N2)) return SDOperand(); - // fold selects based on a setcc into other things, such as min/max/abs if (N0.getOpcode() == ISD::SETCC) - return SimplifySelect(N0, N1, N2); + // FIXME: + // Check against MVT::Other for SELECT_CC, which is a workaround for targets + // having to say they don't support SELECT_CC on every type the DAG knows + // about, since there is no way to mark an opcode illegal at all value types + if (TLI.isOperationLegal(ISD::SELECT_CC, MVT::Other)) + return DAG.getNode(ISD::SELECT_CC, VT, N0.getOperand(0), N0.getOperand(1), + N1, N2, N0.getOperand(2)); + else + return SimplifySelect(N0, N1, N2); return SDOperand(); } @@ -1927,6 +1953,13 @@ SDOperand DAGCombiner::visitBRCOND(SDNode *N) { // unconditional branch if (N1C && N1C->getValue() == 1) return DAG.getNode(ISD::BR, MVT::Other, Chain, N2); + // fold a brcond with a setcc condition into a BR_CC node if BR_CC is legal + // on the target. + if (N1.getOpcode() == ISD::SETCC && + TLI.isOperationLegal(ISD::BR_CC, MVT::Other)) { + return DAG.getNode(ISD::BR_CC, MVT::Other, Chain, N1.getOperand(2), + N1.getOperand(0), N1.getOperand(1), N2); + } return SDOperand(); } @@ -1943,6 +1976,19 @@ SDOperand DAGCombiner::visitBRCONDTWOWAY(SDNode *N) { // unconditional branch to false mbb if (N1C && N1C->isNullValue()) return DAG.getNode(ISD::BR, MVT::Other, Chain, N3); + // fold a brcondtwoway with a setcc condition into a BRTWOWAY_CC node if + // BRTWOWAY_CC is legal on the target. + if (N1.getOpcode() == ISD::SETCC && + TLI.isOperationLegal(ISD::BRTWOWAY_CC, MVT::Other)) { + std::vector Ops; + Ops.push_back(Chain); + Ops.push_back(N1.getOperand(2)); + Ops.push_back(N1.getOperand(0)); + Ops.push_back(N1.getOperand(1)); + Ops.push_back(N2); + Ops.push_back(N3); + return DAG.getNode(ISD::BRTWOWAY_CC, MVT::Other, Ops); + } return SDOperand(); } diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 02031eccea91..23e544212e7c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -106,6 +106,8 @@ private: void ExpandOp(SDOperand O, SDOperand &Lo, SDOperand &Hi); SDOperand PromoteOp(SDOperand O); + void LegalizeSetCCOperands(SDOperand &LHS, SDOperand &RHS, SDOperand &CC); + SDOperand ExpandLibCall(const char *Name, SDNode *Node, SDOperand &Hi); SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, @@ -717,33 +719,22 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; case ISD::BR_CC: Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. - if (!isTypeLegal(Node->getOperand(2).getValueType())) { - Tmp2 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), - Node->getOperand(2), // LHS - Node->getOperand(3), // RHS - Node->getOperand(1))); - // If we get a SETCC back from legalizing the SETCC node we just - // created, then use its LHS, RHS, and CC directly in creating a new - // node. Otherwise, select between the true and false value based on - // comparing the result of the legalized with zero. - if (Tmp2.getOpcode() == ISD::SETCC) { - Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, Tmp2.getOperand(2), - Tmp2.getOperand(0), Tmp2.getOperand(1), - Node->getOperand(4)); - } else { - Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, - DAG.getCondCode(ISD::SETNE), - Tmp2, DAG.getConstant(0, Tmp2.getValueType()), - Node->getOperand(4)); - } - break; + Tmp2 = Node->getOperand(2); // LHS + Tmp3 = Node->getOperand(3); // RHS + Tmp4 = Node->getOperand(1); // CC + + LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4); + + // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, + // the LHS is a legal SETCC itself. In this case, we need to compare + // the result against zero to select between true and false values. + if (Tmp3.Val == 0) { + Tmp3 = DAG.getConstant(0, Tmp2.getValueType()); + Tmp4 = DAG.getCondCode(ISD::SETNE); } - - Tmp2 = LegalizeOp(Node->getOperand(2)); // LHS - Tmp3 = LegalizeOp(Node->getOperand(3)); // RHS - - Result = DAG.UpdateNodeOperands(Result, Tmp1, Node->getOperand(1), Tmp2, - Tmp3, Node->getOperand(4)); + + Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp4, Tmp2, Tmp3, + Node->getOperand(4)); switch (TLI.getOperationAction(ISD::BR_CC, Tmp3.getValueType())) { default: assert(0 && "Unexpected action for BR_CC!"); @@ -805,61 +796,44 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; } break; - case ISD::BRTWOWAY_CC: + case ISD::BRTWOWAY_CC: { Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. - if (isTypeLegal(Node->getOperand(2).getValueType())) { - Tmp2 = LegalizeOp(Node->getOperand(2)); // LHS - Tmp3 = LegalizeOp(Node->getOperand(3)); // RHS - if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(2) || - Tmp3 != Node->getOperand(3)) { - std::vector Ops; - Ops.push_back(Tmp1); - Ops.push_back(Node->getOperand(1)); - Ops.push_back(Tmp2); - Ops.push_back(Tmp3); - Ops.push_back(Node->getOperand(4)); - Ops.push_back(Node->getOperand(5)); - Result = DAG.UpdateNodeOperands(Result, Ops); - } + Tmp2 = Node->getOperand(2); // LHS + Tmp3 = Node->getOperand(3); // RHS + Tmp4 = Node->getOperand(1); // CC + + LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4); + + // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, + // the LHS is a legal SETCC itself. In this case, we need to compare + // the result against zero to select between true and false values. + if (Tmp3.Val == 0) { + Tmp3 = DAG.getConstant(0, Tmp2.getValueType()); + Tmp4 = DAG.getCondCode(ISD::SETNE); + } + std::vector Ops; + Ops.push_back(Tmp1); + Ops.push_back(Tmp4); + Ops.push_back(Tmp2); + Ops.push_back(Tmp3); + Ops.push_back(Node->getOperand(4)); + Ops.push_back(Node->getOperand(5)); + Result = DAG.UpdateNodeOperands(Result, Ops); + + // Everything is legal, see if we should expand this op or something. + switch (TLI.getOperationAction(ISD::BRTWOWAY_CC, MVT::Other)) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Legal: break; + case TargetLowering::Expand: + Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, + DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), Tmp2, + Tmp3, Tmp4), + Result.getOperand(4)); + Result = DAG.getNode(ISD::BR, MVT::Other, Result, Result.getOperand(5)); break; - } else { - Tmp2 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), - Node->getOperand(2), // LHS - Node->getOperand(3), // RHS - Node->getOperand(1))); - // If this target does not support BRTWOWAY_CC, lower it to a BRCOND/BR - // pair. - switch (TLI.getOperationAction(ISD::BRTWOWAY_CC, MVT::Other)) { - default: assert(0 && "This action is not supported yet!"); - case TargetLowering::Legal: { - // If we get a SETCC back from legalizing the SETCC node we just - // created, then use its LHS, RHS, and CC directly in creating a new - // node. Otherwise, select between the true and false value based on - // comparing the result of the legalized with zero. - std::vector Ops; - Ops.push_back(Tmp1); - if (Tmp2.getOpcode() == ISD::SETCC) { - Ops.push_back(Tmp2.getOperand(2)); - Ops.push_back(Tmp2.getOperand(0)); - Ops.push_back(Tmp2.getOperand(1)); - } else { - Ops.push_back(DAG.getCondCode(ISD::SETNE)); - Ops.push_back(Tmp2); - Ops.push_back(DAG.getConstant(0, Tmp2.getValueType())); - } - Ops.push_back(Node->getOperand(4)); - Ops.push_back(Node->getOperand(5)); - Result = DAG.UpdateNodeOperands(Result, Ops); - break; - } - case TargetLowering::Expand: - Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, Tmp2, - Node->getOperand(4)); - Result = DAG.getNode(ISD::BR, MVT::Other, Result, Node->getOperand(5)); - break; - } } break; + } case ISD::LOAD: { Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer. @@ -1315,156 +1289,47 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { } } break; - case ISD::SELECT_CC: + case ISD::SELECT_CC: { + Tmp1 = Node->getOperand(0); // LHS + Tmp2 = Node->getOperand(1); // RHS Tmp3 = LegalizeOp(Node->getOperand(2)); // True Tmp4 = LegalizeOp(Node->getOperand(3)); // False + SDOperand CC = Node->getOperand(4); - if (isTypeLegal(Node->getOperand(0).getValueType())) { - Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS - Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS - - Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4, - Node->getOperand(4)); - - // Everything is legal, see if we should expand this op or something. - switch (TLI.getOperationAction(ISD::SELECT_CC, - Node->getOperand(0).getValueType())) { - default: assert(0 && "This action is not supported yet!"); - case TargetLowering::Legal: break; - case TargetLowering::Custom: - Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; - break; - } + LegalizeSetCCOperands(Tmp1, Tmp2, CC); + + // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, + // the LHS is a legal SETCC itself. In this case, we need to compare + // the result against zero to select between true and false values. + if (Tmp2.Val == 0) { + Tmp2 = DAG.getConstant(0, Tmp1.getValueType()); + CC = DAG.getCondCode(ISD::SETNE); + } + Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4, CC); + + // Everything is legal, see if we should expand this op or something. + switch (TLI.getOperationAction(ISD::SELECT_CC, Tmp3.getValueType())) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Legal: break; + case TargetLowering::Custom: + Tmp1 = TLI.LowerOperation(Result, DAG); + if (Tmp1.Val) Result = Tmp1; break; - } else { - Tmp1 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), - Node->getOperand(0), // LHS - Node->getOperand(1), // RHS - Node->getOperand(4))); - // If we get a SETCC back from legalizing the SETCC node we just - // created, then use its LHS, RHS, and CC directly in creating a new - // node. Otherwise, select between the true and false value based on - // comparing the result of the legalized with zero. - if (Tmp1.getOpcode() == ISD::SETCC) { - Result = DAG.getNode(ISD::SELECT_CC, Tmp3.getValueType(), - Tmp1.getOperand(0), Tmp1.getOperand(1), - Tmp3, Tmp4, Tmp1.getOperand(2)); - } else { - Result = DAG.getSelectCC(Tmp1, - DAG.getConstant(0, Tmp1.getValueType()), - Tmp3, Tmp4, ISD::SETNE); - } } break; + } case ISD::SETCC: - switch (getTypeAction(Node->getOperand(0).getValueType())) { - case Legal: - Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS - Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + Tmp3 = Node->getOperand(2); + LegalizeSetCCOperands(Tmp1, Tmp2, Tmp3); + + // If we had to Expand the SetCC operands into a SELECT node, then it may + // not always be possible to return a true LHS & RHS. In this case, just + // return the value we legalized, returned in the LHS + if (Tmp2.Val == 0) { + Result = Tmp1; break; - case Promote: - Tmp1 = PromoteOp(Node->getOperand(0)); // LHS - Tmp2 = PromoteOp(Node->getOperand(1)); // RHS - - // If this is an FP compare, the operands have already been extended. - if (MVT::isInteger(Node->getOperand(0).getValueType())) { - MVT::ValueType VT = Node->getOperand(0).getValueType(); - MVT::ValueType NVT = TLI.getTypeToTransformTo(VT); - - // Otherwise, we have to insert explicit sign or zero extends. Note - // that we could insert sign extends for ALL conditions, but zero extend - // is cheaper on many machines (an AND instead of two shifts), so prefer - // it. - switch (cast(Node->getOperand(2))->get()) { - default: assert(0 && "Unknown integer comparison!"); - case ISD::SETEQ: - case ISD::SETNE: - case ISD::SETUGE: - case ISD::SETUGT: - case ISD::SETULE: - case ISD::SETULT: - // ALL of these operations will work if we either sign or zero extend - // the operands (including the unsigned comparisons!). Zero extend is - // usually a simpler/cheaper operation, so prefer it. - Tmp1 = DAG.getZeroExtendInReg(Tmp1, VT); - Tmp2 = DAG.getZeroExtendInReg(Tmp2, VT); - break; - case ISD::SETGE: - case ISD::SETGT: - case ISD::SETLT: - case ISD::SETLE: - Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, - DAG.getValueType(VT)); - Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2, - DAG.getValueType(VT)); - break; - } - } - break; - case Expand: - SDOperand LHSLo, LHSHi, RHSLo, RHSHi; - ExpandOp(Node->getOperand(0), LHSLo, LHSHi); - ExpandOp(Node->getOperand(1), RHSLo, RHSHi); - switch (cast(Node->getOperand(2))->get()) { - case ISD::SETEQ: - case ISD::SETNE: - if (RHSLo == RHSHi) - if (ConstantSDNode *RHSCST = dyn_cast(RHSLo)) - if (RHSCST->isAllOnesValue()) { - // Comparison to -1. - Tmp1 = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi); - Tmp2 = RHSLo; - break; - } - - Tmp1 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo); - Tmp2 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi); - Tmp1 = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp2); - Tmp2 = DAG.getConstant(0, Tmp1.getValueType()); - break; - default: - // If this is a comparison of the sign bit, just look at the top part. - // X > -1, x < 0 - if (ConstantSDNode *CST = dyn_cast(Node->getOperand(1))) - if ((cast(Node->getOperand(2))->get() == ISD::SETLT && - CST->getValue() == 0) || // X < 0 - (cast(Node->getOperand(2))->get() == ISD::SETGT && - (CST->isAllOnesValue()))) { // X > -1 - Tmp1 = LHSHi; - Tmp2 = RHSHi; - break; - } - - // FIXME: This generated code sucks. - ISD::CondCode LowCC; - switch (cast(Node->getOperand(2))->get()) { - default: assert(0 && "Unknown integer setcc!"); - case ISD::SETLT: - case ISD::SETULT: LowCC = ISD::SETULT; break; - case ISD::SETGT: - case ISD::SETUGT: LowCC = ISD::SETUGT; break; - case ISD::SETLE: - case ISD::SETULE: LowCC = ISD::SETULE; break; - case ISD::SETGE: - case ISD::SETUGE: LowCC = ISD::SETUGE; break; - } - - // Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison - // Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands - // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2; - - // NOTE: on targets without efficient SELECT of bools, we can always use - // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3) - Tmp1 = DAG.getSetCC(Node->getValueType(0), LHSLo, RHSLo, LowCC); - Tmp2 = DAG.getNode(ISD::SETCC, Node->getValueType(0), LHSHi, RHSHi, - Node->getOperand(2)); - Result = DAG.getSetCC(Node->getValueType(0), LHSHi, RHSHi, ISD::SETEQ); - Result = LegalizeOp(DAG.getNode(ISD::SELECT, Tmp1.getValueType(), - Result, Tmp1, Tmp2)); - AddLegalizedOperand(SDOperand(Node, 0), Result); - return Result; - } } switch (TLI.getOperationAction(ISD::SETCC, Tmp1.getValueType())) { @@ -2699,6 +2564,127 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { return Result; } +/// LegalizeSetCCOperands - Attempts to create a legal LHS and RHS for a SETCC +/// with condition CC on the current target. This usually involves legalizing +/// or promoting the arguments. In the case where LHS and RHS must be expanded, +/// there may be no choice but to create a new SetCC node to represent the +/// legalized value of setcc lhs, rhs. In this case, the value is returned in +/// LHS, and the SDOperand returned in RHS has a nil SDNode value. +void SelectionDAGLegalize::LegalizeSetCCOperands(SDOperand &LHS, + SDOperand &RHS, + SDOperand &CC) { + SDOperand Tmp1, Tmp2, Result; + + switch (getTypeAction(LHS.getValueType())) { + case Legal: + Tmp1 = LegalizeOp(LHS); // LHS + Tmp2 = LegalizeOp(RHS); // RHS + break; + case Promote: + Tmp1 = PromoteOp(LHS); // LHS + Tmp2 = PromoteOp(RHS); // RHS + + // If this is an FP compare, the operands have already been extended. + if (MVT::isInteger(LHS.getValueType())) { + MVT::ValueType VT = LHS.getValueType(); + MVT::ValueType NVT = TLI.getTypeToTransformTo(VT); + + // Otherwise, we have to insert explicit sign or zero extends. Note + // that we could insert sign extends for ALL conditions, but zero extend + // is cheaper on many machines (an AND instead of two shifts), so prefer + // it. + switch (cast(CC)->get()) { + default: assert(0 && "Unknown integer comparison!"); + case ISD::SETEQ: + case ISD::SETNE: + case ISD::SETUGE: + case ISD::SETUGT: + case ISD::SETULE: + case ISD::SETULT: + // ALL of these operations will work if we either sign or zero extend + // the operands (including the unsigned comparisons!). Zero extend is + // usually a simpler/cheaper operation, so prefer it. + Tmp1 = DAG.getZeroExtendInReg(Tmp1, VT); + Tmp2 = DAG.getZeroExtendInReg(Tmp2, VT); + break; + case ISD::SETGE: + case ISD::SETGT: + case ISD::SETLT: + case ISD::SETLE: + Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, + DAG.getValueType(VT)); + Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2, + DAG.getValueType(VT)); + break; + } + } + break; + case Expand: + SDOperand LHSLo, LHSHi, RHSLo, RHSHi; + ExpandOp(LHS, LHSLo, LHSHi); + ExpandOp(RHS, RHSLo, RHSHi); + switch (cast(CC)->get()) { + case ISD::SETEQ: + case ISD::SETNE: + if (RHSLo == RHSHi) + if (ConstantSDNode *RHSCST = dyn_cast(RHSLo)) + if (RHSCST->isAllOnesValue()) { + // Comparison to -1. + Tmp1 = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi); + Tmp2 = RHSLo; + break; + } + + Tmp1 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo); + Tmp2 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi); + Tmp1 = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp2); + Tmp2 = DAG.getConstant(0, Tmp1.getValueType()); + break; + default: + // If this is a comparison of the sign bit, just look at the top part. + // X > -1, x < 0 + if (ConstantSDNode *CST = dyn_cast(RHS)) + if ((cast(CC)->get() == ISD::SETLT && + CST->getValue() == 0) || // X < 0 + (cast(CC)->get() == ISD::SETGT && + CST->isAllOnesValue())) { // X > -1 + Tmp1 = LHSHi; + Tmp2 = RHSHi; + break; + } + + // FIXME: This generated code sucks. + ISD::CondCode LowCC; + switch (cast(CC)->get()) { + default: assert(0 && "Unknown integer setcc!"); + case ISD::SETLT: + case ISD::SETULT: LowCC = ISD::SETULT; break; + case ISD::SETGT: + case ISD::SETUGT: LowCC = ISD::SETUGT; break; + case ISD::SETLE: + case ISD::SETULE: LowCC = ISD::SETULE; break; + case ISD::SETGE: + case ISD::SETUGE: LowCC = ISD::SETUGE; break; + } + + // Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison + // Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands + // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2; + + // NOTE: on targets without efficient SELECT of bools, we can always use + // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3) + Tmp1 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSLo, RHSLo, LowCC); + Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), LHSHi, RHSHi, CC); + Result = DAG.getSetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi, ISD::SETEQ); + Result = LegalizeOp(DAG.getNode(ISD::SELECT, Tmp1.getValueType(), + Result, Tmp1, Tmp2)); + Tmp1 = Result; + } + } + LHS = Tmp1; + RHS = Tmp2; +} + /// ExpandBIT_CONVERT - Expand a BIT_CONVERT node into a store/load combination. /// The resultant code need not be legal. Note that SrcOp is the input operand /// to the BIT_CONVERT, not the BIT_CONVERT node itself. diff --git a/llvm/lib/Target/Alpha/AlphaISelLowering.cpp b/llvm/lib/Target/Alpha/AlphaISelLowering.cpp index 2990146899b5..c9cafd478e51 100644 --- a/llvm/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/llvm/lib/Target/Alpha/AlphaISelLowering.cpp @@ -56,6 +56,8 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); setOperationAction(ISD::EXTLOAD, MVT::i1, Promote); setOperationAction(ISD::EXTLOAD, MVT::f32, Expand); diff --git a/llvm/lib/Target/IA64/IA64ISelLowering.cpp b/llvm/lib/Target/IA64/IA64ISelLowering.cpp index 11b95c4e02e2..1c835a8c98d3 100644 --- a/llvm/lib/Target/IA64/IA64ISelLowering.cpp +++ b/llvm/lib/Target/IA64/IA64ISelLowering.cpp @@ -35,10 +35,14 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM) // register class for predicate registers addRegisterClass(MVT::i1, IA64::PRRegisterClass); + setOperationAction(ISD::BR_CC , MVT::Other, Expand); setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand); setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand); setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand); + // ia64 uses SELECT not SELECT_CC + setOperationAction(ISD::SELECT_CC , MVT::Other, Expand); + // We need to handle ISD::RET for void functions ourselves, // so we get a chance to restore ar.pfs before adding a // br.ret insn diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 28beeafce166..ec35f37e96e4 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -13,6 +13,7 @@ #include "PPCISelLowering.h" #include "PPCTargetMachine.h" +#include "llvm/ADT/VectorExtras.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -20,7 +21,7 @@ #include "llvm/CodeGen/SSARegMap.h" #include "llvm/Constants.h" #include "llvm/Function.h" -#include "llvm/ADT/VectorExtras.h" +#include "llvm/Support/MathExtras.h" using namespace llvm; PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) @@ -85,7 +86,7 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); - // PowerPC wants to optimize setcc i32, imm a bit. + // PowerPC wants to optimize integer setcc a bit setOperationAction(ISD::SETCC, MVT::i32, Custom); // PowerPC does not have BRCOND* which requires SetCC @@ -452,15 +453,41 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { } case ISD::SETCC: { ISD::CondCode CC = cast(Op.getOperand(2))->get(); - if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) - if (C->getValue() && !C->isAllOnesValue()) - if (CC == ISD::SETEQ || CC == ISD::SETNE || - CC == ISD::SETLT || CC == ISD::SETGT) { - MVT::ValueType VT = Op.getValueType(); - SDOperand SUB = DAG.getNode(ISD::SUB, Op.getOperand(0).getValueType(), - Op.getOperand(0), Op.getOperand(1)); - return DAG.getSetCC(VT, SUB, DAG.getConstant(0, VT), CC); - } + + // If we're comparing for equality to zero, expose the fact that this is + // implented as a ctlz/srl pair on ppc, so that the dag combiner can + // fold the new nodes. + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + if (C->isNullValue() && CC == ISD::SETEQ) { + MVT::ValueType VT = Op.getOperand(0).getValueType(); + SDOperand Zext = Op.getOperand(0); + if (VT < MVT::i32) { + VT = MVT::i32; + Zext = DAG.getNode(ISD::ZERO_EXTEND, VT, Op.getOperand(0)); + } + unsigned Log2b = Log2_32(MVT::getSizeInBits(VT)); + SDOperand Clz = DAG.getNode(ISD::CTLZ, VT, Zext); + SDOperand Scc = DAG.getNode(ISD::SRL, VT, Clz, + DAG.getConstant(Log2b, getShiftAmountTy())); + return DAG.getNode(ISD::TRUNCATE, getSetCCResultTy(), Scc); + } + // Leave comparisons against 0 and -1 alone for now, since they're usually + // optimized. FIXME: revisit this when we can custom lower all setcc + // optimizations. + if (C->isAllOnesValue() || C->isNullValue()) + break; + } + + // If we have an integer seteq/setne, turn it into a compare against zero + // by subtracting the rhs from the lhs, which is faster than setting a + // condition register, reading it back out, and masking the correct bit. + MVT::ValueType LHSVT = Op.getOperand(0).getValueType(); + if (MVT::isInteger(LHSVT) && (CC == ISD::SETEQ || CC == ISD::SETNE)) { + MVT::ValueType VT = Op.getValueType(); + SDOperand Sub = DAG.getNode(ISD::SUB, LHSVT, Op.getOperand(0), + Op.getOperand(1)); + return DAG.getSetCC(VT, Sub, DAG.getConstant(0, LHSVT), CC); + } break; } case ISD::VASTART: { diff --git a/llvm/lib/Target/PowerPC/README.txt b/llvm/lib/Target/PowerPC/README.txt index 1b05e7c4f0d7..e23c6e77b5b4 100644 --- a/llvm/lib/Target/PowerPC/README.txt +++ b/llvm/lib/Target/PowerPC/README.txt @@ -280,32 +280,6 @@ void bar() { struct foo R = { 1.0, 2.0 }; xxx(R); } ===-------------------------------------------------------------------------=== -For this: - -int h(int i, int j, int k) { - return (i==0||j==0||k == 0); -} - -We currently emit this: - -_h: - cntlzw r2, r3 - cntlzw r3, r4 - cntlzw r4, r5 - srwi r2, r2, 5 - srwi r3, r3, 5 - srwi r4, r4, 5 - or r2, r3, r2 - or r3, r2, r4 - blr - -The ctlz/shift instructions are created by the isel, so the dag combiner doesn't -have a chance to pull the shifts through the or's (eliminating two -instructions). SETCC nodes should be custom lowered in this case, not expanded -by the isel. - -===-------------------------------------------------------------------------=== - Darwin Stub LICM optimization: Loops like this: @@ -461,19 +435,3 @@ This could be done in the dag combiner, by swapping a BR_CC when a SETCC of the same operands (but backwards) exists. In this case, this wouldn't save us anything though, because the compares still wouldn't be shared. -===-------------------------------------------------------------------------=== - -A simple case we generate suboptimal code on: - -int test(int X) { - return X == 0 ? 32 : 0; -} - -_test: - cntlzw r2, r3 - srwi r2, r2, 5 - slwi r3, r2, 5 - blr - -The shifts should be one 'andi'. - diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index d692780179ca..0a63cfa12600 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -117,6 +117,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) } setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand); setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand); + setOperationAction(ISD::BR_CC , MVT::Other, Expand); + setOperationAction(ISD::SELECT_CC , MVT::Other, Expand); setOperationAction(ISD::MEMMOVE , MVT::Other, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16 , Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);