diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 28a9471cd06..6f514db07bb 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -461,7 +461,9 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; } case Promote: - assert(0 && "Can't promote return value!"); + Tmp2 = PromoteOp(Node->getOperand(1)); + Result = DAG.getNode(ISD::RET, MVT::Other, Tmp1, Tmp2); + break; } break; case 1: // ret void @@ -484,7 +486,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; } case Promote: - assert(0 && "Can't promote return value!"); + assert(0 && "Can't promote multiple return value yet!"); } Result = DAG.getNode(ISD::RET, MVT::Other, NewValues); break; @@ -589,7 +591,44 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { Tmp1, Tmp2); break; case Promote: - assert(0 && "Can't promote setcc operands yet!"); + 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 = TransformToType[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)->getCondition()) { + 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.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp1, VT); + Tmp2 = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp2, VT); + break; + case ISD::SETGE: + case ISD::SETGT: + case ISD::SETLT: + case ISD::SETLE: + Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, VT); + Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2, VT); + break; + } + + } + Result = DAG.getSetCC(cast(Node)->getCondition(), + Tmp1, Tmp2); break; case Expand: SDOperand LHSLo, LHSHi, RHSLo, RHSHi; @@ -825,6 +864,10 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { return Result; } +/// PromoteOp - Given an operation that produces a value in an invalid type, +/// promote it to compute the value into a larger type. The produced value will +/// have the correct bits for the low portion of the register, but no guarantee +/// is made about the top bits: it may be zero, sign-extended, or garbage. SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { MVT::ValueType VT = Op.getValueType(); MVT::ValueType NVT = TransformToType[VT]; @@ -851,6 +894,9 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { std::cerr << "NODE: "; Node->dump(); std::cerr << "\n"; assert(0 && "Do not know how to promote this operator!"); abort(); + case ISD::CALL: + assert(0 && "Target's LowerCallTo implementation is buggy, returning value" + " types that are not supported by the target!"); case ISD::Constant: Result = DAG.getNode(ISD::ZERO_EXTEND, NVT, Op); assert(isa(Result) && "Didn't constant fold zext?"); @@ -875,18 +921,86 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { assert(0 && "Cannot handle promote-promote yet"); } break; + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + switch (getTypeAction(Node->getOperand(0).getValueType())) { + case Expand: assert(0 && "BUG: Smaller reg should have been promoted!"); + case Legal: + // Input is legal? Just do extend all the way to the larger type. + Result = LegalizeOp(Node->getOperand(0)); + Result = DAG.getNode(Node->getOpcode(), NVT, Result); + break; + case Promote: + // Promote the reg if it's smaller. + Result = PromoteOp(Node->getOperand(0)); + // The high bits are not guaranteed to be anything. Insert an extend. + if (Node->getOpcode() == ISD::SIGN_EXTEND) + Result = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Result, VT); + else + Result = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Result, VT); + break; + } + break; + + case ISD::FP_EXTEND: + assert(0 && "Case not implemented. Dynamically dead with 2 FP types!"); + case ISD::FP_ROUND: + switch (getTypeAction(Node->getOperand(0).getValueType())) { + case Expand: assert(0 && "BUG: Cannot expand FP regs!"); + case Promote: assert(0 && "Unreachable with 2 FP types!"); + case Legal: + // Input is legal? Do an FP_ROUND_INREG. + Result = LegalizeOp(Node->getOperand(0)); + Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, VT); + break; + } + break; + + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + switch (getTypeAction(Node->getOperand(0).getValueType())) { + case Legal: + Result = LegalizeOp(Node->getOperand(0)); + break; + + case Promote: + Result = PromoteOp(Node->getOperand(0)); + if (Node->getOpcode() == ISD::SINT_TO_FP) + Result = DAG.getNode(ISD::SIGN_EXTEND_INREG, Result.getValueType(), + Result, Node->getOperand(0).getValueType()); + else + Result = DAG.getNode(ISD::ZERO_EXTEND_INREG, Result.getValueType(), + Result, Node->getOperand(0).getValueType()); + break; + case Expand: + assert(0 && "Unimplemented"); + } + // No extra round required here. + Result = DAG.getNode(Node->getOpcode(), NVT, Result); + break; + + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + switch (getTypeAction(Node->getOperand(0).getValueType())) { + case Legal: + Tmp1 = LegalizeOp(Node->getOperand(0)); + break; + case Promote: + // The input result is prerounded, so we don't have to do anything + // special. + Tmp1 = PromoteOp(Node->getOperand(0)); + break; + case Expand: + assert(0 && "not implemented"); + } + Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1); + break; + case ISD::AND: case ISD::OR: case ISD::XOR: - // The logical ops can just execute, they don't care what the top bits - // coming in are. - Tmp1 = PromoteOp(Node->getOperand(0)); - Tmp2 = PromoteOp(Node->getOperand(1)); - assert(Tmp1.getValueType() == NVT && Tmp2.getValueType() == NVT); - Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2); - break; - case ISD::ADD: + case ISD::SUB: case ISD::MUL: // The input may have strange things in the top bits of the registers, but // these operations don't care. They may have wierd bits going out, but @@ -899,10 +1013,58 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { // However, if this is a floating point operation, they will give excess // precision that we may not be able to tolerate. If we DO allow excess // precision, just leave it, otherwise excise it. + // FIXME: Why would we need to round FP ops more than integer ones? + // Is Round(Add(Add(A,B),C)) != Round(Add(Round(Add(A,B)), C)) if (MVT::isFloatingPoint(NVT) && NoExcessFPPrecision) Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, VT); break; + case ISD::SDIV: + case ISD::SREM: + // These operators require that their input be sign extended. + Tmp1 = PromoteOp(Node->getOperand(0)); + Tmp2 = PromoteOp(Node->getOperand(1)); + if (MVT::isInteger(NVT)) { + Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, VT); + Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, VT); + } + Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2); + + // Perform FP_ROUND: this is probably overly pessimistic. + if (MVT::isFloatingPoint(NVT) && NoExcessFPPrecision) + Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, VT); + break; + + case ISD::UDIV: + case ISD::UREM: + // These operators require that their input be zero extended. + Tmp1 = PromoteOp(Node->getOperand(0)); + Tmp2 = PromoteOp(Node->getOperand(1)); + assert(MVT::isInteger(NVT) && "Operators don't apply to FP!"); + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp1, VT); + Tmp2 = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp1, VT); + Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2); + break; + + case ISD::SHL: + Tmp1 = PromoteOp(Node->getOperand(0)); + Tmp2 = LegalizeOp(Node->getOperand(1)); + Result = DAG.getNode(ISD::SHL, NVT, Tmp1, Tmp2); + break; + case ISD::SRA: + // The input value must be properly sign extended. + Tmp1 = PromoteOp(Node->getOperand(0)); + Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, VT); + Tmp2 = LegalizeOp(Node->getOperand(1)); + Result = DAG.getNode(ISD::SRA, NVT, Tmp1, Tmp2); + break; + case ISD::SRL: + // The input value must be properly zero extended. + Tmp1 = PromoteOp(Node->getOperand(0)); + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp1, VT); + Tmp2 = LegalizeOp(Node->getOperand(1)); + Result = DAG.getNode(ISD::SRL, NVT, Tmp1, Tmp2); + break; case ISD::LOAD: Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer. @@ -912,7 +1074,7 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { AddLegalizedOperand(Op.getValue(1), Result.getValue(1)); break; case ISD::SELECT: - Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the condition + Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the condition Tmp2 = PromoteOp(Node->getOperand(1)); // Legalize the op0 Tmp3 = PromoteOp(Node->getOperand(2)); // Legalize the op1 Result = DAG.getNode(ISD::SELECT, NVT, Tmp1, Tmp2, Tmp3);