Add FP versions of the binary operators, keeping the int and fp worlds seperate.

Though I have done extensive testing, it is possible that this will break
things in configs I can't test.  Please let me know if this causes a problem
and I'll fix it ASAP.

llvm-svn: 23504
This commit is contained in:
Chris Lattner 2005-09-28 22:28:18 +00:00
parent 7fe6734dff
commit 6f3b577ee6
4 changed files with 209 additions and 87 deletions

View File

@ -115,6 +115,12 @@ namespace {
SDOperand visitZERO_EXTEND(SDNode *N); SDOperand visitZERO_EXTEND(SDNode *N);
SDOperand visitSIGN_EXTEND_INREG(SDNode *N); SDOperand visitSIGN_EXTEND_INREG(SDNode *N);
SDOperand visitTRUNCATE(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 visitSINT_TO_FP(SDNode *N);
SDOperand visitUINT_TO_FP(SDNode *N); SDOperand visitUINT_TO_FP(SDNode *N);
SDOperand visitFP_TO_SINT(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::ZERO_EXTEND: return visitZERO_EXTEND(N);
case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N); case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N);
case ISD::TRUNCATE: return visitTRUNCATE(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::SINT_TO_FP: return visitSINT_TO_FP(N);
case ISD::UINT_TO_FP: return visitUINT_TO_FP(N); case ISD::UINT_TO_FP: return visitUINT_TO_FP(N);
case ISD::FP_TO_SINT: return visitFP_TO_SINT(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); SDOperand N1 = N->getOperand(1);
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
MVT::ValueType VT = N0.getValueType(); MVT::ValueType VT = N0.getValueType();
// fold (add c1, c2) -> c1+c2 // fold (add c1, c2) -> c1+c2
@ -390,9 +399,6 @@ SDOperand DAGCombiner::visitADD(SDNode *N) {
// fold (add x, 0) -> x // fold (add x, 0) -> x
if (N1C && N1C->isNullValue()) if (N1C && N1C->isNullValue())
return N0; 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) // fold (add (add x, c1), c2) -> (add x, c1+c2)
if (N1C && N0.getOpcode() == ISD::ADD) { if (N1C && N0.getOpcode() == ISD::ADD) {
ConstantSDNode *N00C = dyn_cast<ConstantSDNode>(N0.getOperand(0)); ConstantSDNode *N00C = dyn_cast<ConstantSDNode>(N0.getOperand(0));
@ -404,12 +410,6 @@ SDOperand DAGCombiner::visitADD(SDNode *N) {
return DAG.getNode(ISD::ADD, VT, N0.getOperand(0), return DAG.getNode(ISD::ADD, VT, N0.getOperand(0),
DAG.getConstant(N1C->getValue()+N01C->getValue(), VT)); 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 // fold ((0-A) + B) -> B-A
if (N0.getOpcode() == ISD::SUB && isa<ConstantSDNode>(N0.getOperand(0)) && if (N0.getOpcode() == ISD::SUB && isa<ConstantSDNode>(N0.getOperand(0)) &&
cast<ConstantSDNode>(N0.getOperand(0))->isNullValue()) cast<ConstantSDNode>(N0.getOperand(0))->isNullValue())
@ -418,9 +418,8 @@ SDOperand DAGCombiner::visitADD(SDNode *N) {
if (N1.getOpcode() == ISD::SUB && isa<ConstantSDNode>(N1.getOperand(0)) && if (N1.getOpcode() == ISD::SUB && isa<ConstantSDNode>(N1.getOperand(0)) &&
cast<ConstantSDNode>(N1.getOperand(0))->isNullValue()) cast<ConstantSDNode>(N1.getOperand(0))->isNullValue())
return DAG.getNode(ISD::SUB, VT, N0, N1.getOperand(1)); return DAG.getNode(ISD::SUB, VT, N0, N1.getOperand(1));
// fold (A+(B-A)) -> B for non-fp types // fold (A+(B-A)) -> B
if (N1.getOpcode() == ISD::SUB && N0 == N1.getOperand(1) && if (N1.getOpcode() == ISD::SUB && N0 == N1.getOperand(1))
!MVT::isFloatingPoint(N1.getValueType()))
return N1.getOperand(0); return N1.getOperand(0);
return SDOperand(); return SDOperand();
} }
@ -430,8 +429,6 @@ SDOperand DAGCombiner::visitSUB(SDNode *N) {
SDOperand N1 = N->getOperand(1); SDOperand N1 = N->getOperand(1);
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0.Val); ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0.Val);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val);
ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0.Val);
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1.Val);
// fold (sub c1, c2) -> c1-c2 // fold (sub c1, c2) -> c1-c2
if (N0C && N1C) if (N0C && N1C)
@ -440,21 +437,12 @@ SDOperand DAGCombiner::visitSUB(SDNode *N) {
// fold (sub x, 0) -> x // fold (sub x, 0) -> x
if (N1C && N1C->isNullValue()) if (N1C && N1C->isNullValue())
return N0; 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 // fold (A+B)-A -> B
if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1 && if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1)
!MVT::isFloatingPoint(N1.getValueType()))
return N0.getOperand(1); return N0.getOperand(1);
// fold (A+B)-B -> A // fold (A+B)-B -> A
if (N0.getOpcode() == ISD::ADD && N0.getOperand(1) == N1 && if (N0.getOpcode() == ISD::ADD && N0.getOperand(1) == N1)
!MVT::isFloatingPoint(N1.getValueType()))
return N0.getOperand(0); 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(); return SDOperand();
} }
@ -463,8 +451,6 @@ SDOperand DAGCombiner::visitMUL(SDNode *N) {
SDOperand N1 = N->getOperand(1); SDOperand N1 = N->getOperand(1);
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
MVT::ValueType VT = N0.getValueType(); MVT::ValueType VT = N0.getValueType();
// fold (mul c1, c2) -> c1*c2 // fold (mul c1, c2) -> c1*c2
@ -499,10 +485,6 @@ SDOperand DAGCombiner::visitMUL(SDNode *N) {
return DAG.getNode(ISD::MUL, VT, N0.getOperand(0), return DAG.getNode(ISD::MUL, VT, N0.getOperand(0),
DAG.getConstant(N1C->getValue()*N01C->getValue(), VT)); 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(); return SDOperand();
} }
@ -511,17 +493,11 @@ SDOperand DAGCombiner::visitSDIV(SDNode *N) {
SDOperand N1 = N->getOperand(1); SDOperand N1 = N->getOperand(1);
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0.Val); ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0.Val);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val);
ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0.Val);
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1.Val);
// fold (sdiv c1, c2) -> c1/c2 // fold (sdiv c1, c2) -> c1/c2
if (N0C && N1C && !N1C->isNullValue()) if (N0C && N1C && !N1C->isNullValue())
return DAG.getConstant(N0C->getSignExtended() / N1C->getSignExtended(), return DAG.getConstant(N0C->getSignExtended() / N1C->getSignExtended(),
N->getValueType(0)); 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(); return SDOperand();
} }
@ -548,17 +524,11 @@ SDOperand DAGCombiner::visitSREM(SDNode *N) {
SDOperand N1 = N->getOperand(1); SDOperand N1 = N->getOperand(1);
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
// fold (srem c1, c2) -> c1%c2 // fold (srem c1, c2) -> c1%c2
if (N0C && N1C && !N1C->isNullValue()) if (N0C && N1C && !N1C->isNullValue())
return DAG.getConstant(N0C->getSignExtended() % N1C->getSignExtended(), return DAG.getConstant(N0C->getSignExtended() % N1C->getSignExtended(),
N->getValueType(0)); 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(); return SDOperand();
} }
@ -1233,6 +1203,89 @@ SDOperand DAGCombiner::visitTRUNCATE(SDNode *N) {
return SDOperand(); 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<ConstantFPSDNode>(N0))
if (ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(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<ConstantFPSDNode>(N0))
if (ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(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<ConstantFPSDNode>(N0))
if (ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(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<ConstantFPSDNode>(N0))
if (ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(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<ConstantFPSDNode>(N0))
if (ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(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 DAGCombiner::visitSINT_TO_FP(SDNode *N) {
SDOperand N0 = N->getOperand(0); SDOperand N0 = N->getOperand(0);
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);

View File

@ -209,7 +209,7 @@ SDOperand SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
: BitsToDouble(0x4330000000000000ULL), : BitsToDouble(0x4330000000000000ULL),
MVT::f64); MVT::f64);
// subtract the bias // 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 // final result
SDOperand Result; SDOperand Result;
// handle final rounding // handle final rounding
@ -1531,6 +1531,10 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
case ISD::SHL: case ISD::SHL:
case ISD::SRL: case ISD::SRL:
case ISD::SRA: case ISD::SRA:
case ISD::FADD:
case ISD::FSUB:
case ISD::FMUL:
case ISD::FDIV:
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
switch (getTypeAction(Node->getOperand(1).getValueType())) { switch (getTypeAction(Node->getOperand(1).getValueType())) {
case Expand: assert(0 && "Not possible"); case Expand: assert(0 && "Not possible");
@ -1548,6 +1552,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
case ISD::UREM: case ISD::UREM:
case ISD::SREM: case ISD::SREM:
case ISD::FREM:
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS
switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
@ -1715,7 +1720,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
case ISD::FNEG: { case ISD::FNEG: {
// Expand Y = FNEG(X) -> Y = SUB -0.0, X // Expand Y = FNEG(X) -> Y = SUB -0.0, X
Tmp2 = DAG.getConstantFP(-0.0, Node->getValueType(0)); 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)); Tmp2, Tmp1));
break; break;
} }
@ -1840,7 +1845,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
Node->getOperand(0), Tmp2, ISD::SETLT); Node->getOperand(0), Tmp2, ISD::SETLT);
True = DAG.getNode(ISD::FP_TO_SINT, NVT, Node->getOperand(0)); True = DAG.getNode(ISD::FP_TO_SINT, NVT, Node->getOperand(0));
False = DAG.getNode(ISD::FP_TO_SINT, NVT, 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)); Tmp2));
False = DAG.getNode(ISD::XOR, NVT, False, False = DAG.getNode(ISD::XOR, NVT, False,
DAG.getConstant(1ULL << ShiftAmt, NVT)); DAG.getConstant(1ULL << ShiftAmt, NVT));
@ -2193,19 +2198,29 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
case ISD::SUB: case ISD::SUB:
case ISD::MUL: case ISD::MUL:
// The input may have strange things in the top bits of the registers, but // 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. // that too is okay if they are integer operations.
Tmp1 = PromoteOp(Node->getOperand(0)); Tmp1 = PromoteOp(Node->getOperand(0));
Tmp2 = PromoteOp(Node->getOperand(1)); Tmp2 = PromoteOp(Node->getOperand(1));
assert(Tmp1.getValueType() == NVT && Tmp2.getValueType() == NVT); assert(Tmp1.getValueType() == NVT && Tmp2.getValueType() == NVT);
Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2); Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2);
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);
// However, if this is a floating point operation, they will give excess // Floating point operations will give excess precision that we may not be
// precision that we may not be able to tolerate. If we DO allow excess // able to tolerate. If we DO allow excess precision, just leave it,
// precision, just leave it, otherwise excise it. // otherwise excise it.
// FIXME: Why would we need to round FP ops more than integer ones? // 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)) // 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, Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result,
DAG.getValueType(VT)); DAG.getValueType(VT));
break; break;
@ -2228,6 +2243,18 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result,
DAG.getValueType(VT)); DAG.getValueType(VT));
break; 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::UDIV:
case ISD::UREM: case ISD::UREM:

View File

@ -36,6 +36,8 @@ static bool isCommutativeBinOp(unsigned Opcode) {
switch (Opcode) { switch (Opcode) {
case ISD::ADD: case ISD::ADD:
case ISD::MUL: case ISD::MUL:
case ISD::FADD:
case ISD::FMUL:
case ISD::AND: case ISD::AND:
case ISD::OR: case ISD::OR:
case ISD::XOR: return true; case ISD::XOR: return true;
@ -869,8 +871,7 @@ SDOperand SelectionDAG::SimplifySetCC(MVT::ValueType VT, SDOperand N1,
return getSetCC(VT, N1, N2, NewCond); return getSetCC(VT, N1, N2, NewCond);
} }
if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && if (Cond == ISD::SETEQ || Cond == ISD::SETNE) {
MVT::isInteger(N1.getValueType())) {
if (N1.getOpcode() == ISD::ADD || N1.getOpcode() == ISD::SUB || if (N1.getOpcode() == ISD::ADD || N1.getOpcode() == ISD::SUB ||
N1.getOpcode() == ISD::XOR) { N1.getOpcode() == ISD::XOR) {
// Simplify (X+Y) == (X+Z) --> Y == Z // Simplify (X+Y) == (X+Z) --> Y == Z
@ -1187,8 +1188,8 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
} }
break; break;
case ISD::FNEG: case ISD::FNEG:
if (OpOpcode == ISD::SUB) // -(X-Y) -> (Y-X) if (OpOpcode == ISD::FSUB) // -(X-Y) -> (Y-X)
return getNode(ISD::SUB, VT, Operand.Val->getOperand(1), return getNode(ISD::FSUB, VT, Operand.Val->getOperand(1),
Operand.Val->getOperand(0)); Operand.Val->getOperand(0));
if (OpOpcode == ISD::FNEG) // --X -> X if (OpOpcode == ISD::FNEG) // --X -> X
return Operand.Val->getOperand(0); return Operand.Val->getOperand(0);
@ -1236,6 +1237,13 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
case ISD::MUL: case ISD::MUL:
case ISD::SDIV: case ISD::SDIV:
case ISD::SREM: 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() && assert(N1.getValueType() == N2.getValueType() &&
N1.getValueType() == VT && "Binary operator types must match!"); N1.getValueType() == VT && "Binary operator types must match!");
break; break;
@ -1513,13 +1521,13 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
if (N2CFP) { if (N2CFP) {
double C1 = N1CFP->getValue(), C2 = N2CFP->getValue(); double C1 = N1CFP->getValue(), C2 = N2CFP->getValue();
switch (Opcode) { switch (Opcode) {
case ISD::ADD: return getConstantFP(C1 + C2, VT); case ISD::FADD: return getConstantFP(C1 + C2, VT);
case ISD::SUB: return getConstantFP(C1 - C2, VT); case ISD::FSUB: return getConstantFP(C1 - C2, VT);
case ISD::MUL: return getConstantFP(C1 * C2, VT); case ISD::FMUL: return getConstantFP(C1 * C2, VT);
case ISD::SDIV: case ISD::FDIV:
if (C2) return getConstantFP(C1 / C2, VT); if (C2) return getConstantFP(C1 / C2, VT);
break; break;
case ISD::SREM : case ISD::FREM :
if (C2) return getConstantFP(fmod(C1, C2), VT); if (C2) return getConstantFP(fmod(C1, C2), VT);
break; break;
default: break; default: break;
@ -1623,33 +1631,39 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
break; break;
case ISD::ADD: case ISD::ADD:
if (!CombinerEnabled) { 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<ConstantSDNode>(N1.getOperand(0)) && if (N1.getOpcode() == ISD::SUB && isa<ConstantSDNode>(N1.getOperand(0)) &&
cast<ConstantSDNode>(N1.getOperand(0))->getValue() == 0) cast<ConstantSDNode>(N1.getOperand(0))->getValue() == 0)
return getNode(ISD::SUB, VT, N2, N1.getOperand(1)); // (0-A)+B -> B-A return getNode(ISD::SUB, VT, N2, N1.getOperand(1)); // (0-A)+B -> B-A
if (N2.getOpcode() == ISD::SUB && isa<ConstantSDNode>(N2.getOperand(0)) && if (N2.getOpcode() == ISD::SUB && isa<ConstantSDNode>(N2.getOperand(0)) &&
cast<ConstantSDNode>(N2.getOperand(0))->getValue() == 0) cast<ConstantSDNode>(N2.getOperand(0))->getValue() == 0)
return getNode(ISD::SUB, VT, N1, N2.getOperand(1)); // A+(0-B) -> A-B return getNode(ISD::SUB, VT, N1, N2.getOperand(1)); // A+(0-B) -> A-B
if (N2.getOpcode() == ISD::SUB && N1 == N2.Val->getOperand(1) && if (N2.getOpcode() == ISD::SUB && N1 == N2.Val->getOperand(1))
!MVT::isFloatingPoint(N2.getValueType()))
return N2.Val->getOperand(0); // A+(B-A) -> B return N2.Val->getOperand(0); // A+(B-A) -> B
} }
break; 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: case ISD::SUB:
if (!CombinerEnabled) { if (!CombinerEnabled) {
if (N1.getOpcode() == ISD::ADD) { if (N1.getOpcode() == ISD::ADD) {
if (N1.Val->getOperand(0) == N2 && if (N1.Val->getOperand(0) == N2)
!MVT::isFloatingPoint(N2.getValueType()))
return N1.Val->getOperand(1); // (A+B)-A == B return N1.Val->getOperand(1); // (A+B)-A == B
if (N1.Val->getOperand(1) == N2 && if (N1.Val->getOperand(1) == N2)
!MVT::isFloatingPoint(N2.getValueType()))
return N1.Val->getOperand(0); // (A+B)-B == A return N1.Val->getOperand(0); // (A+B)-B == A
} }
}
break;
case ISD::FSUB:
if (!CombinerEnabled) {
if (N2.getOpcode() == ISD::FNEG) // (A- (-B) -> A+B 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; break;
case ISD::FP_ROUND_INREG: case ISD::FP_ROUND_INREG:
@ -2333,6 +2347,11 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::SHL: return "shl"; case ISD::SHL: return "shl";
case ISD::SRA: return "sra"; case ISD::SRA: return "sra";
case ISD::SRL: return "srl"; 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::SETCC: return "setcc";
case ISD::SELECT: return "select"; case ISD::SELECT: return "select";

View File

@ -353,14 +353,34 @@ public:
// //
void visitBinary(User &I, unsigned Opcode, bool isShift = false); 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 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) { 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) { 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 visitAnd(User &I) { visitBinary(I, ISD::AND); }
void visitOr (User &I) { visitBinary(I, ISD::OR); } void visitOr (User &I) { visitBinary(I, ISD::OR); }
@ -491,14 +511,17 @@ void SelectionDAGLowering::visitBr(BranchInst &I) {
void SelectionDAGLowering::visitSub(User &I) { void SelectionDAGLowering::visitSub(User &I) {
// -0.0 - X --> fneg // -0.0 - X --> fneg
if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0))) if (I.getType()->isFloatingPoint()) {
if (CFP->isExactlyValue(-0.0)) { if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0)))
SDOperand Op2 = getValue(I.getOperand(1)); if (CFP->isExactlyValue(-0.0)) {
setValue(&I, DAG.getNode(ISD::FNEG, Op2.getValueType(), Op2)); SDOperand Op2 = getValue(I.getOperand(1));
return; setValue(&I, DAG.getNode(ISD::FNEG, Op2.getValueType(), Op2));
} return;
}
visitBinary(I, ISD::SUB); visitBinary(I, ISD::FSUB);
} else {
visitBinary(I, ISD::SUB);
}
} }
void SelectionDAGLowering::visitBinary(User &I, unsigned Opcode, bool isShift) { void SelectionDAGLowering::visitBinary(User &I, unsigned Opcode, bool isShift) {