forked from OSchip/llvm-project
Codegen and legalize sin/cos/llvm.sqrt as FSIN/FCOS/FSQRT calls. This patch
was contributed by Morten Ofstad, with some minor tweaks and bug fixes added by me. llvm-svn: 21636
This commit is contained in:
parent
9efa7e7533
commit
8002640eab
|
@ -1003,12 +1003,15 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||
case TargetLowering::Custom:
|
||||
assert(0 && "Cannot promote/custom handle this yet!");
|
||||
case TargetLowering::Expand:
|
||||
if (Node->getOpcode() == ISD::FNEG) {
|
||||
switch(Node->getOpcode()) {
|
||||
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),
|
||||
Tmp2, Tmp1));
|
||||
} else if (Node->getOpcode() == ISD::FABS) {
|
||||
break;
|
||||
}
|
||||
case ISD::FABS: {
|
||||
// Expand Y = FABS(X) -> Y = (X >u 0.0) ? X : fneg(X).
|
||||
MVT::ValueType VT = Node->getValueType(0);
|
||||
Tmp2 = DAG.getConstantFP(0.0, VT);
|
||||
|
@ -1016,7 +1019,29 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||
Tmp3 = DAG.getNode(ISD::FNEG, VT, Tmp1);
|
||||
Result = DAG.getNode(ISD::SELECT, VT, Tmp2, Tmp1, Tmp3);
|
||||
Result = LegalizeOp(Result);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
case ISD::FSQRT:
|
||||
case ISD::FSIN:
|
||||
case ISD::FCOS: {
|
||||
MVT::ValueType VT = Node->getValueType(0);
|
||||
Type *T = VT == MVT::f32 ? Type::FloatTy : Type::DoubleTy;
|
||||
const char *FnName = 0;
|
||||
switch(Node->getOpcode()) {
|
||||
case ISD::FSQRT: FnName = VT == MVT::f32 ? "sqrtf" : "sqrt"; break;
|
||||
case ISD::FSIN: FnName = VT == MVT::f32 ? "sinf" : "sin"; break;
|
||||
case ISD::FCOS: FnName = VT == MVT::f32 ? "cosf" : "cos"; break;
|
||||
default: assert(0 && "Unreachable!");
|
||||
}
|
||||
std::vector<std::pair<SDOperand, const Type*> > Args;
|
||||
Args.push_back(std::make_pair(Tmp1, T));
|
||||
std::pair<SDOperand,SDOperand> CallResult =
|
||||
TLI.LowerCallTo(DAG.getEntryNode(), T, false,
|
||||
DAG.getExternalSymbol(FnName, VT), Args, DAG);
|
||||
Result = LegalizeOp(CallResult.first);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0 && "Unreachable!");
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -656,6 +656,24 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (F->getName() == "sin" || F->getName() == "sinf") {
|
||||
if (I.getNumOperands() == 2 && // Basic sanity checks.
|
||||
I.getOperand(1)->getType()->isFloatingPoint() &&
|
||||
I.getType() == I.getOperand(1)->getType()) {
|
||||
SDOperand Tmp = getValue(I.getOperand(1));
|
||||
setValue(&I, DAG.getNode(ISD::FSIN, Tmp.getValueType(), Tmp));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (F->getName() == "cos" || F->getName() == "cosf") {
|
||||
if (I.getNumOperands() == 2 && // Basic sanity checks.
|
||||
I.getOperand(1)->getType()->isFloatingPoint() &&
|
||||
I.getType() == I.getOperand(1)->getType()) {
|
||||
SDOperand Tmp = getValue(I.getOperand(1));
|
||||
setValue(&I, DAG.getNode(ISD::FCOS, Tmp.getValueType(), Tmp));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Intrinsic::vastart: visitVAStart(I); return;
|
||||
case Intrinsic::vaend: visitVAEnd(I); return;
|
||||
|
@ -677,6 +695,13 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
|
|||
setValue(&I, DAG.getSetCC(ISD::SETUO, MVT::i1,getValue(I.getOperand(1)),
|
||||
getValue(I.getOperand(2))));
|
||||
return;
|
||||
|
||||
case Intrinsic::sqrt:
|
||||
setValue(&I, DAG.getNode(ISD::FSQRT,
|
||||
getValue(I.getOperand(1)).getValueType(),
|
||||
getValue(I.getOperand(1))));
|
||||
return;
|
||||
|
||||
case Intrinsic::pcmarker: {
|
||||
SDOperand Num = getValue(I.getOperand(1));
|
||||
DAG.setRoot(DAG.getNode(ISD::PCMARKER, MVT::Other, getRoot(), Num));
|
||||
|
|
Loading…
Reference in New Issue