1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

Codegen copysign[f] into a FCOPYSIGN node

llvm-svn: 26542
This commit is contained in:
Chris Lattner 2006-03-05 05:09:38 +00:00
parent 6b0947c277
commit 4b4b3e6cbb
3 changed files with 63 additions and 4 deletions

View File

@ -1775,7 +1775,48 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break;
}
break;
case ISD::FCOPYSIGN: // FCOPYSIGN does not require LHS/RHS to match type!
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
switch (getTypeAction(Node->getOperand(1).getValueType())) {
case Expand: assert(0 && "Not possible");
case Legal:
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the RHS.
break;
case Promote:
Tmp2 = PromoteOp(Node->getOperand(1)); // Promote the RHS.
break;
}
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
default: assert(0 && "Operation not supported");
case TargetLowering::Custom:
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.Val) Result = Tmp1;
break;
case TargetLowering::Legal: break;
case TargetLowering::Expand:
// Floating point mod -> fmod libcall.
const char *FnName;
if (Node->getValueType(0) == MVT::f32) {
FnName = "copysignf";
if (Tmp2.getValueType() != MVT::f32) // Force operands to match type.
Result = DAG.UpdateNodeOperands(Result, Tmp1,
DAG.getNode(ISD::FP_ROUND, MVT::f32, Tmp2));
} else {
FnName = "copysign";
if (Tmp2.getValueType() != MVT::f64) // Force operands to match type.
Result = DAG.UpdateNodeOperands(Result, Tmp1,
DAG.getNode(ISD::FP_EXTEND, MVT::f64, Tmp2));
}
SDOperand Dummy;
Result = ExpandLibCall(FnName, Node, Dummy);
break;
}
break;
case ISD::ADDC:
case ISD::SUBC:
Tmp1 = LegalizeOp(Node->getOperand(0));
@ -2604,13 +2645,14 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
break;
case ISD::FDIV:
case ISD::FREM:
case ISD::FCOPYSIGN:
// 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)
if (NoExcessFPPrecision && Node->getOpcode() != ISD::FCOPYSIGN)
Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result,
DAG.getValueType(VT));
break;

View File

@ -1152,7 +1152,12 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
assert(N1.getValueType() == N2.getValueType() &&
N1.getValueType() == VT && "Binary operator types must match!");
break;
case ISD::FCOPYSIGN: // N1 and result must match. N1/N2 need not match.
assert(N1.getValueType() == VT &&
MVT::isFloatingPoint(N1.getValueType()) &&
MVT::isFloatingPoint(N2.getValueType()) &&
"Invalid FCOPYSIGN!");
break;
case ISD::SHL:
case ISD::SRA:
case ISD::SRL:
@ -2635,6 +2640,7 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::FMUL: return "fmul";
case ISD::FDIV: return "fdiv";
case ISD::FREM: return "frem";
case ISD::FCOPYSIGN: return "fcopysign";
case ISD::VADD: return "vadd";
case ISD::VSUB: return "vsub";
case ISD::VMUL: return "vmul";

View File

@ -1120,7 +1120,18 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
return;
} else { // Not an LLVM intrinsic.
const std::string &Name = F->getName();
if (Name[0] == 'f' && (Name == "fabs" || Name == "fabsf")) {
if (Name[0] == 'c' && (Name == "copysign" || Name == "copysignf")) {
if (I.getNumOperands() == 3 && // Basic sanity checks.
I.getOperand(1)->getType()->isFloatingPoint() &&
I.getType() == I.getOperand(1)->getType() &&
I.getType() == I.getOperand(2)->getType()) {
SDOperand LHS = getValue(I.getOperand(1));
SDOperand RHS = getValue(I.getOperand(2));
setValue(&I, DAG.getNode(ISD::FCOPYSIGN, LHS.getValueType(),
LHS, RHS));
return;
}
} else if (Name[0] == 'f' && (Name == "fabs" || Name == "fabsf")) {
if (I.getNumOperands() == 2 && // Basic sanity checks.
I.getOperand(1)->getType()->isFloatingPoint() &&
I.getType() == I.getOperand(1)->getType()) {