Add the ability to lower return instructions to TargetLowering. This

allows us to lower legal return types to something else, to meet ABI
requirements (such as that i64 be returned in two i32 regs on Darwin/ppc).

llvm-svn: 23802
This commit is contained in:
Nate Begeman 2005-10-18 23:23:37 +00:00
parent 0a71a9ac86
commit 78afac2ddd
5 changed files with 45 additions and 7 deletions

View File

@ -311,6 +311,12 @@ public:
unsigned CallingConv, bool isTailCall, SDOperand Callee,
ArgListTy &Args, SelectionDAG &DAG) = 0;
/// LowerReturnTo - This hook lowers a return instruction into the appropriate
/// legal ISD::RET node for the target's current ABI. This method is optional
/// and is intended for targets that need non-standard behavior.
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG);
/// LowerVAStart - This lowers the llvm.va_start intrinsic. If not
/// implemented, this method prints a message and aborts. This method should
/// return the modified chain value. Note that VAListPtr* correspond to the

View File

@ -450,8 +450,8 @@ void SelectionDAGLowering::visitRet(ReturnInst &I) {
case MVT::f64:
break; // No extension needed!
}
DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, getRoot(), Op1));
// Allow targets to lower this further to meet ABI requirements
DAG.setRoot(TLI.LowerReturnTo(getRoot(), Op1, DAG));
}
void SelectionDAGLowering::visitBr(BranchInst &I) {
@ -898,6 +898,11 @@ MachineBasicBlock *TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
return 0;
}
SDOperand TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG) {
return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
}
SDOperand TargetLowering::LowerVAStart(SDOperand Chain,
SDOperand VAListP, Value *VAListV,
SelectionDAG &DAG) {

View File

@ -1206,6 +1206,22 @@ SDOperand PPCDAGToDAGISel::Select(SDOperand Op) {
// Other cases are autogenerated.
break;
case ISD::ANY_EXTEND:
switch(N->getValueType(0)) {
default: assert(0 && "Unhandled type in ANY_EXTEND");
case MVT::i64:
CurDAG->SelectNodeTo(N, PPC::OR8, MVT::i64, Select(N->getOperand(0)),
Select(N->getOperand(0)));
break;
}
return SDOperand(N, 0);
case ISD::ZERO_EXTEND:
assert(N->getValueType(0) == MVT::i64 &&
N->getOperand(0).getValueType() == MVT::i32 &&
"ZERO_EXTEND only supported for i32 -> i64");
CurDAG->SelectNodeTo(N, PPC::RLDICL, MVT::i64, Select(N->getOperand(0)),
getI32Imm(32));
return SDOperand(N, 0);
case ISD::SHL: {
unsigned Imm, SH, MB, ME;
if (isOpcWithIntImmediate(N->getOperand(0).Val, ISD::AND, Imm) &&
@ -1393,11 +1409,6 @@ SDOperand PPCDAGToDAGISel::Select(SDOperand Op) {
SDOperand Val = Select(N->getOperand(1));
if (N->getOperand(1).getValueType() == MVT::i32) {
Chain = CurDAG->getCopyToReg(Chain, PPC::R3, Val);
} else if (N->getOperand(1).getValueType() == MVT::i64) {
SDOperand Srl = CurDAG->getTargetNode(PPC::RLDICL, MVT::i64, Val,
getI32Imm(32), getI32Imm(32));
Chain = CurDAG->getCopyToReg(Chain, PPC::R4, Val);
Chain = CurDAG->getCopyToReg(Chain, PPC::R3, Srl);
} else {
assert(MVT::isFloatingPoint(N->getOperand(1).getValueType()));
Chain = CurDAG->getCopyToReg(Chain, PPC::F1, Val);

View File

@ -693,6 +693,19 @@ PPCTargetLowering::LowerCallTo(SDOperand Chain,
return std::make_pair(RetVal, Chain);
}
SDOperand PPCTargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG) {
if (Op.getValueType() == MVT::i64) {
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
DAG.getConstant(1, MVT::i32));
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
DAG.getConstant(0, MVT::i32));
return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Hi);
} else {
return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
}
}
SDOperand PPCTargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
Value *VAListV, SelectionDAG &DAG) {
// vastart just stores the address of the VarArgsFrameIndex slot into the

View File

@ -63,6 +63,9 @@ namespace llvm {
unsigned CC,
bool isTailCall, SDOperand Callee, ArgListTy &Args,
SelectionDAG &DAG);
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG);
virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
Value *VAListV, SelectionDAG &DAG);