diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 899543dbbe9..19c61a5d262 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -115,6 +115,12 @@ namespace { SDOperand visitZERO_EXTEND(SDNode *N); SDOperand visitSIGN_EXTEND_INREG(SDNode *N); SDOperand visitTRUNCATE(SDNode *N); + + SDOperand visitFADD(SDNode *N); + SDOperand visitFSUB(SDNode *N); + SDOperand visitFMUL(SDNode *N); + SDOperand visitFDIV(SDNode *N); + SDOperand visitFREM(SDNode *N); SDOperand visitSINT_TO_FP(SDNode *N); SDOperand visitUINT_TO_FP(SDNode *N); SDOperand visitFP_TO_SINT(SDNode *N); @@ -341,6 +347,11 @@ SDOperand DAGCombiner::visit(SDNode *N) { case ISD::ZERO_EXTEND: return visitZERO_EXTEND(N); case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N); case ISD::TRUNCATE: return visitTRUNCATE(N); + case ISD::FADD: return visitFADD(N); + case ISD::FSUB: return visitFSUB(N); + case ISD::FMUL: return visitFMUL(N); + case ISD::FDIV: return visitFDIV(N); + case ISD::FREM: return visitFREM(N); case ISD::SINT_TO_FP: return visitSINT_TO_FP(N); case ISD::UINT_TO_FP: return visitUINT_TO_FP(N); case ISD::FP_TO_SINT: return visitFP_TO_SINT(N); @@ -375,8 +386,6 @@ SDOperand DAGCombiner::visitADD(SDNode *N) { SDOperand N1 = N->getOperand(1); ConstantSDNode *N0C = dyn_cast(N0); ConstantSDNode *N1C = dyn_cast(N1); - ConstantFPSDNode *N0CFP = dyn_cast(N0); - ConstantFPSDNode *N1CFP = dyn_cast(N1); MVT::ValueType VT = N0.getValueType(); // fold (add c1, c2) -> c1+c2 @@ -390,9 +399,6 @@ SDOperand DAGCombiner::visitADD(SDNode *N) { // fold (add x, 0) -> x if (N1C && N1C->isNullValue()) return N0; - // fold floating point (add c1, c2) -> c1+c2 - if (N0CFP && N1CFP) - return DAG.getConstantFP(N0CFP->getValue() + N1CFP->getValue(), VT); // fold (add (add x, c1), c2) -> (add x, c1+c2) if (N1C && N0.getOpcode() == ISD::ADD) { ConstantSDNode *N00C = dyn_cast(N0.getOperand(0)); @@ -404,12 +410,6 @@ SDOperand DAGCombiner::visitADD(SDNode *N) { return DAG.getNode(ISD::ADD, VT, N0.getOperand(0), DAG.getConstant(N1C->getValue()+N01C->getValue(), VT)); } - // fold (A + (-B)) -> A-B - if (N1.getOpcode() == ISD::FNEG) - return DAG.getNode(ISD::SUB, VT, N0, N1.getOperand(0)); - // fold ((-A) + B) -> B-A - if (N0.getOpcode() == ISD::FNEG) - return DAG.getNode(ISD::SUB, VT, N1, N0.getOperand(0)); // fold ((0-A) + B) -> B-A if (N0.getOpcode() == ISD::SUB && isa(N0.getOperand(0)) && cast(N0.getOperand(0))->isNullValue()) @@ -418,9 +418,8 @@ SDOperand DAGCombiner::visitADD(SDNode *N) { if (N1.getOpcode() == ISD::SUB && isa(N1.getOperand(0)) && cast(N1.getOperand(0))->isNullValue()) return DAG.getNode(ISD::SUB, VT, N0, N1.getOperand(1)); - // fold (A+(B-A)) -> B for non-fp types - if (N1.getOpcode() == ISD::SUB && N0 == N1.getOperand(1) && - !MVT::isFloatingPoint(N1.getValueType())) + // fold (A+(B-A)) -> B + if (N1.getOpcode() == ISD::SUB && N0 == N1.getOperand(1)) return N1.getOperand(0); return SDOperand(); } @@ -430,8 +429,6 @@ SDOperand DAGCombiner::visitSUB(SDNode *N) { SDOperand N1 = N->getOperand(1); ConstantSDNode *N0C = dyn_cast(N0.Val); ConstantSDNode *N1C = dyn_cast(N1.Val); - ConstantFPSDNode *N0CFP = dyn_cast(N0.Val); - ConstantFPSDNode *N1CFP = dyn_cast(N1.Val); // fold (sub c1, c2) -> c1-c2 if (N0C && N1C) @@ -440,21 +437,12 @@ SDOperand DAGCombiner::visitSUB(SDNode *N) { // fold (sub x, 0) -> x if (N1C && N1C->isNullValue()) return N0; - // fold floating point (sub c1, c2) -> c1-c2 - if (N0CFP && N1CFP) - return DAG.getConstantFP(N0CFP->getValue() - N1CFP->getValue(), - N->getValueType(0)); // fold (A+B)-A -> B - if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1 && - !MVT::isFloatingPoint(N1.getValueType())) + if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1) return N0.getOperand(1); // fold (A+B)-B -> A - if (N0.getOpcode() == ISD::ADD && N0.getOperand(1) == N1 && - !MVT::isFloatingPoint(N1.getValueType())) + if (N0.getOpcode() == ISD::ADD && N0.getOperand(1) == N1) return N0.getOperand(0); - // fold (A-(-B)) -> A+B - if (N1.getOpcode() == ISD::FNEG) - return DAG.getNode(ISD::ADD, N0.getValueType(), N0, N1.getOperand(0)); return SDOperand(); } @@ -463,8 +451,6 @@ SDOperand DAGCombiner::visitMUL(SDNode *N) { SDOperand N1 = N->getOperand(1); ConstantSDNode *N0C = dyn_cast(N0); ConstantSDNode *N1C = dyn_cast(N1); - ConstantFPSDNode *N0CFP = dyn_cast(N0); - ConstantFPSDNode *N1CFP = dyn_cast(N1); MVT::ValueType VT = N0.getValueType(); // fold (mul c1, c2) -> c1*c2 @@ -499,10 +485,6 @@ SDOperand DAGCombiner::visitMUL(SDNode *N) { return DAG.getNode(ISD::MUL, VT, N0.getOperand(0), DAG.getConstant(N1C->getValue()*N01C->getValue(), VT)); } - // fold floating point (mul c1, c2) -> c1*c2 - if (N0CFP && N1CFP) - return DAG.getConstantFP(N0CFP->getValue() * N1CFP->getValue(), - N->getValueType(0)); return SDOperand(); } @@ -511,17 +493,11 @@ SDOperand DAGCombiner::visitSDIV(SDNode *N) { SDOperand N1 = N->getOperand(1); ConstantSDNode *N0C = dyn_cast(N0.Val); ConstantSDNode *N1C = dyn_cast(N1.Val); - ConstantFPSDNode *N0CFP = dyn_cast(N0.Val); - ConstantFPSDNode *N1CFP = dyn_cast(N1.Val); // fold (sdiv c1, c2) -> c1/c2 if (N0C && N1C && !N1C->isNullValue()) return DAG.getConstant(N0C->getSignExtended() / N1C->getSignExtended(), N->getValueType(0)); - // fold floating point (sdiv c1, c2) -> c1/c2 - if (N0CFP && N1CFP) - return DAG.getConstantFP(N0CFP->getValue() / N1CFP->getValue(), - N->getValueType(0)); return SDOperand(); } @@ -548,17 +524,11 @@ SDOperand DAGCombiner::visitSREM(SDNode *N) { SDOperand N1 = N->getOperand(1); ConstantSDNode *N0C = dyn_cast(N0); ConstantSDNode *N1C = dyn_cast(N1); - ConstantFPSDNode *N0CFP = dyn_cast(N0); - ConstantFPSDNode *N1CFP = dyn_cast(N1); // fold (srem c1, c2) -> c1%c2 if (N0C && N1C && !N1C->isNullValue()) return DAG.getConstant(N0C->getSignExtended() % N1C->getSignExtended(), N->getValueType(0)); - // fold floating point (srem c1, c2) -> fmod(c1, c2) - if (N0CFP && N1CFP) - return DAG.getConstantFP(fmod(N0CFP->getValue(),N1CFP->getValue()), - N->getValueType(0)); return SDOperand(); } @@ -1233,6 +1203,89 @@ SDOperand DAGCombiner::visitTRUNCATE(SDNode *N) { return SDOperand(); } +SDOperand DAGCombiner::visitFADD(SDNode *N) { + SDOperand N0 = N->getOperand(0); + SDOperand N1 = N->getOperand(1); + MVT::ValueType VT = N->getValueType(0); + + if (ConstantFPSDNode *N0CFP = dyn_cast(N0)) + if (ConstantFPSDNode *N1CFP = dyn_cast(N1)) { + // fold floating point (fadd c1, c2) + return DAG.getConstantFP(N0CFP->getValue() + N1CFP->getValue(), + N->getValueType(0)); + } + // fold (A + (-B)) -> A-B + if (N1.getOpcode() == ISD::FNEG) + return DAG.getNode(ISD::FSUB, VT, N0, N1.getOperand(0)); + + // fold ((-A) + B) -> B-A + if (N0.getOpcode() == ISD::FNEG) + return DAG.getNode(ISD::FSUB, VT, N1, N0.getOperand(0)); + + return SDOperand(); +} + +SDOperand DAGCombiner::visitFSUB(SDNode *N) { + SDOperand N0 = N->getOperand(0); + SDOperand N1 = N->getOperand(1); + MVT::ValueType VT = N->getValueType(0); + + if (ConstantFPSDNode *N0CFP = dyn_cast(N0)) + if (ConstantFPSDNode *N1CFP = dyn_cast(N1)) { + // fold floating point (fsub c1, c2) + return DAG.getConstantFP(N0CFP->getValue() - N1CFP->getValue(), + N->getValueType(0)); + } + // fold (A-(-B)) -> A+B + if (N1.getOpcode() == ISD::FNEG) + return DAG.getNode(ISD::FADD, N0.getValueType(), N0, N1.getOperand(0)); + + return SDOperand(); +} + +SDOperand DAGCombiner::visitFMUL(SDNode *N) { + SDOperand N0 = N->getOperand(0); + SDOperand N1 = N->getOperand(1); + MVT::ValueType VT = N->getValueType(0); + + if (ConstantFPSDNode *N0CFP = dyn_cast(N0)) + if (ConstantFPSDNode *N1CFP = dyn_cast(N1)) { + // fold floating point (fmul c1, c2) + return DAG.getConstantFP(N0CFP->getValue() * N1CFP->getValue(), + N->getValueType(0)); + } + return SDOperand(); +} + +SDOperand DAGCombiner::visitFDIV(SDNode *N) { + SDOperand N0 = N->getOperand(0); + SDOperand N1 = N->getOperand(1); + MVT::ValueType VT = N->getValueType(0); + + if (ConstantFPSDNode *N0CFP = dyn_cast(N0)) + if (ConstantFPSDNode *N1CFP = dyn_cast(N1)) { + // fold floating point (fdiv c1, c2) + return DAG.getConstantFP(N0CFP->getValue() / N1CFP->getValue(), + N->getValueType(0)); + } + return SDOperand(); +} + +SDOperand DAGCombiner::visitFREM(SDNode *N) { + SDOperand N0 = N->getOperand(0); + SDOperand N1 = N->getOperand(1); + MVT::ValueType VT = N->getValueType(0); + + if (ConstantFPSDNode *N0CFP = dyn_cast(N0)) + if (ConstantFPSDNode *N1CFP = dyn_cast(N1)) { + // fold floating point (frem c1, c2) -> fmod(c1, c2) + return DAG.getConstantFP(fmod(N0CFP->getValue(),N1CFP->getValue()), + N->getValueType(0)); + } + return SDOperand(); +} + + SDOperand DAGCombiner::visitSINT_TO_FP(SDNode *N) { SDOperand N0 = N->getOperand(0); ConstantSDNode *N0C = dyn_cast(N0); diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 277f696dcbf..918f8258390 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -209,7 +209,7 @@ SDOperand SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, : BitsToDouble(0x4330000000000000ULL), MVT::f64); // subtract the bias - SDOperand Sub = DAG.getNode(ISD::SUB, MVT::f64, Load, Bias); + SDOperand Sub = DAG.getNode(ISD::FSUB, MVT::f64, Load, Bias); // final result SDOperand Result; // handle final rounding @@ -1531,6 +1531,10 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { case ISD::SHL: case ISD::SRL: case ISD::SRA: + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::FDIV: Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS switch (getTypeAction(Node->getOperand(1).getValueType())) { case Expand: assert(0 && "Not possible"); @@ -1548,6 +1552,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { case ISD::UREM: case ISD::SREM: + case ISD::FREM: Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { @@ -1715,7 +1720,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { case ISD::FNEG: { // Expand Y = FNEG(X) -> Y = SUB -0.0, X Tmp2 = DAG.getConstantFP(-0.0, Node->getValueType(0)); - Result = LegalizeOp(DAG.getNode(ISD::SUB, Node->getValueType(0), + Result = LegalizeOp(DAG.getNode(ISD::FSUB, Node->getValueType(0), Tmp2, Tmp1)); break; } @@ -1840,7 +1845,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { Node->getOperand(0), Tmp2, ISD::SETLT); True = DAG.getNode(ISD::FP_TO_SINT, NVT, Node->getOperand(0)); False = DAG.getNode(ISD::FP_TO_SINT, NVT, - DAG.getNode(ISD::SUB, VT, Node->getOperand(0), + DAG.getNode(ISD::FSUB, VT, Node->getOperand(0), Tmp2)); False = DAG.getNode(ISD::XOR, NVT, False, DAG.getConstant(1ULL << ShiftAmt, NVT)); @@ -2193,19 +2198,29 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { 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 + // these operations don't care. They may have weird bits going out, but // that too is okay if they are integer operations. 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); - - // 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. + break; + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + // The input may have strange things in the top bits of the registers, but + // these operations don't care. + 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); + + // Floating point operations 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) + if (NoExcessFPPrecision) Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, DAG.getValueType(VT)); break; @@ -2228,6 +2243,18 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, DAG.getValueType(VT)); break; + case ISD::FDIV: + case ISD::FREM: + // These operators require that their input be fp extended. + Tmp1 = PromoteOp(Node->getOperand(0)); + Tmp2 = PromoteOp(Node->getOperand(1)); + Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2); + + // Perform FP_ROUND: this is probably overly pessimistic. + if (NoExcessFPPrecision) + Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, + DAG.getValueType(VT)); + break; case ISD::UDIV: case ISD::UREM: diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index e3706c157e1..61fa31959c1 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -36,6 +36,8 @@ static bool isCommutativeBinOp(unsigned Opcode) { switch (Opcode) { case ISD::ADD: case ISD::MUL: + case ISD::FADD: + case ISD::FMUL: case ISD::AND: case ISD::OR: case ISD::XOR: return true; @@ -869,8 +871,7 @@ SDOperand SelectionDAG::SimplifySetCC(MVT::ValueType VT, SDOperand N1, return getSetCC(VT, N1, N2, NewCond); } - if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && - MVT::isInteger(N1.getValueType())) { + if (Cond == ISD::SETEQ || Cond == ISD::SETNE) { if (N1.getOpcode() == ISD::ADD || N1.getOpcode() == ISD::SUB || N1.getOpcode() == ISD::XOR) { // Simplify (X+Y) == (X+Z) --> Y == Z @@ -1187,8 +1188,8 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, } break; case ISD::FNEG: - if (OpOpcode == ISD::SUB) // -(X-Y) -> (Y-X) - return getNode(ISD::SUB, VT, Operand.Val->getOperand(1), + if (OpOpcode == ISD::FSUB) // -(X-Y) -> (Y-X) + return getNode(ISD::FSUB, VT, Operand.Val->getOperand(1), Operand.Val->getOperand(0)); if (OpOpcode == ISD::FNEG) // --X -> X return Operand.Val->getOperand(0); @@ -1236,6 +1237,13 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, case ISD::MUL: case ISD::SDIV: case ISD::SREM: + assert(MVT::isInteger(N1.getValueType()) && "Should use F* for FP ops"); + // fall through. + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::FDIV: + case ISD::FREM: assert(N1.getValueType() == N2.getValueType() && N1.getValueType() == VT && "Binary operator types must match!"); break; @@ -1513,13 +1521,13 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, if (N2CFP) { double C1 = N1CFP->getValue(), C2 = N2CFP->getValue(); switch (Opcode) { - case ISD::ADD: return getConstantFP(C1 + C2, VT); - case ISD::SUB: return getConstantFP(C1 - C2, VT); - case ISD::MUL: return getConstantFP(C1 * C2, VT); - case ISD::SDIV: + case ISD::FADD: return getConstantFP(C1 + C2, VT); + case ISD::FSUB: return getConstantFP(C1 - C2, VT); + case ISD::FMUL: return getConstantFP(C1 * C2, VT); + case ISD::FDIV: if (C2) return getConstantFP(C1 / C2, VT); break; - case ISD::SREM : + case ISD::FREM : if (C2) return getConstantFP(fmod(C1, C2), VT); break; default: break; @@ -1623,33 +1631,39 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, break; case ISD::ADD: if (!CombinerEnabled) { - if (N2.getOpcode() == ISD::FNEG) // (A+ (-B) -> A-B - return getNode(ISD::SUB, VT, N1, N2.getOperand(0)); - if (N1.getOpcode() == ISD::FNEG) // ((-A)+B) -> B-A - return getNode(ISD::SUB, VT, N2, N1.getOperand(0)); if (N1.getOpcode() == ISD::SUB && isa(N1.getOperand(0)) && cast(N1.getOperand(0))->getValue() == 0) return getNode(ISD::SUB, VT, N2, N1.getOperand(1)); // (0-A)+B -> B-A if (N2.getOpcode() == ISD::SUB && isa(N2.getOperand(0)) && cast(N2.getOperand(0))->getValue() == 0) return getNode(ISD::SUB, VT, N1, N2.getOperand(1)); // A+(0-B) -> A-B - if (N2.getOpcode() == ISD::SUB && N1 == N2.Val->getOperand(1) && - !MVT::isFloatingPoint(N2.getValueType())) + if (N2.getOpcode() == ISD::SUB && N1 == N2.Val->getOperand(1)) return N2.Val->getOperand(0); // A+(B-A) -> B } break; + case ISD::FADD: + if (!CombinerEnabled) { + if (N2.getOpcode() == ISD::FNEG) // (A+ (-B) -> A-B + return getNode(ISD::FSUB, VT, N1, N2.getOperand(0)); + if (N1.getOpcode() == ISD::FNEG) // ((-A)+B) -> B-A + return getNode(ISD::FSUB, VT, N2, N1.getOperand(0)); + } + break; + case ISD::SUB: if (!CombinerEnabled) { if (N1.getOpcode() == ISD::ADD) { - if (N1.Val->getOperand(0) == N2 && - !MVT::isFloatingPoint(N2.getValueType())) + if (N1.Val->getOperand(0) == N2) return N1.Val->getOperand(1); // (A+B)-A == B - if (N1.Val->getOperand(1) == N2 && - !MVT::isFloatingPoint(N2.getValueType())) + if (N1.Val->getOperand(1) == N2) return N1.Val->getOperand(0); // (A+B)-B == A } + } + break; + case ISD::FSUB: + if (!CombinerEnabled) { if (N2.getOpcode() == ISD::FNEG) // (A- (-B) -> A+B - return getNode(ISD::ADD, VT, N1, N2.getOperand(0)); + return getNode(ISD::FADD, VT, N1, N2.getOperand(0)); } break; case ISD::FP_ROUND_INREG: @@ -2333,7 +2347,12 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const { case ISD::SHL: return "shl"; case ISD::SRA: return "sra"; case ISD::SRL: return "srl"; - + case ISD::FADD: return "fadd"; + case ISD::FSUB: return "fsub"; + case ISD::FMUL: return "fmul"; + case ISD::FDIV: return "fdiv"; + case ISD::FREM: return "frem"; + case ISD::SETCC: return "setcc"; case ISD::SELECT: return "select"; case ISD::SELECT_CC: return "select_cc"; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index ad7a8af4af5..9eb0ed9a4a4 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -353,14 +353,34 @@ public: // void visitBinary(User &I, unsigned Opcode, bool isShift = false); - void visitAdd(User &I) { visitBinary(I, ISD::ADD); } + void visitAdd(User &I) { + visitBinary(I, I.getType()->isFloatingPoint() ? ISD::FADD : ISD::ADD); + } void visitSub(User &I); - void visitMul(User &I) { visitBinary(I, ISD::MUL); } + void visitMul(User &I) { + visitBinary(I, I.getType()->isFloatingPoint() ? ISD::FMUL : ISD::MUL); + } void visitDiv(User &I) { - visitBinary(I, I.getType()->isUnsigned() ? ISD::UDIV : ISD::SDIV); + unsigned Opc; + const Type *Ty = I.getType(); + if (Ty->isFloatingPoint()) + Opc = ISD::FDIV; + else if (Ty->isUnsigned()) + Opc = ISD::UDIV; + else + Opc = ISD::SDIV; + visitBinary(I, Opc); } void visitRem(User &I) { - visitBinary(I, I.getType()->isUnsigned() ? ISD::UREM : ISD::SREM); + unsigned Opc; + const Type *Ty = I.getType(); + if (Ty->isFloatingPoint()) + Opc = ISD::FREM; + else if (Ty->isUnsigned()) + Opc = ISD::UREM; + else + Opc = ISD::SREM; + visitBinary(I, Opc); } void visitAnd(User &I) { visitBinary(I, ISD::AND); } void visitOr (User &I) { visitBinary(I, ISD::OR); } @@ -491,14 +511,17 @@ void SelectionDAGLowering::visitBr(BranchInst &I) { void SelectionDAGLowering::visitSub(User &I) { // -0.0 - X --> fneg - if (ConstantFP *CFP = dyn_cast(I.getOperand(0))) - if (CFP->isExactlyValue(-0.0)) { - SDOperand Op2 = getValue(I.getOperand(1)); - setValue(&I, DAG.getNode(ISD::FNEG, Op2.getValueType(), Op2)); - return; - } - - visitBinary(I, ISD::SUB); + if (I.getType()->isFloatingPoint()) { + if (ConstantFP *CFP = dyn_cast(I.getOperand(0))) + if (CFP->isExactlyValue(-0.0)) { + SDOperand Op2 = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FNEG, Op2.getValueType(), Op2)); + return; + } + visitBinary(I, ISD::FSUB); + } else { + visitBinary(I, ISD::SUB); + } } void SelectionDAGLowering::visitBinary(User &I, unsigned Opcode, bool isShift) {