summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2005-10-18 23:23:37 +0000
committerNate Begeman <natebegeman@mac.com>2005-10-18 23:23:37 +0000
commit78afac2ddd5fdff66e53b0cea6dccc978740b874 (patch)
tree8a3c7b5cb67ddc0b6beae8555d85f20b97c50c2a
parent0a71a9ac86e9a8fb89f1638e600e6b1ae45d0013 (diff)
downloadbcm5719-llvm-78afac2ddd5fdff66e53b0cea6dccc978740b874.tar.gz
bcm5719-llvm-78afac2ddd5fdff66e53b0cea6dccc978740b874.zip
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
-rw-r--r--llvm/include/llvm/Target/TargetLowering.h6
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp9
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp21
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.cpp13
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.h3
5 files changed, 45 insertions, 7 deletions
diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h
index 734c8dc0297..02278e9e422 100644
--- a/llvm/include/llvm/Target/TargetLowering.h
+++ b/llvm/include/llvm/Target/TargetLowering.h
@@ -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
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 72ee7501082..4a89578eaa0 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -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) {
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index c55bd30a2dd..75480930311 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -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);
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 8cc538df83a..5256e4839d1 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -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
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 0b3690ddf69..f44f192e693 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -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);
OpenPOWER on IntegriCloud