Pattern-match return. Includes gross hack!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24874 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 338be66..4d9abdc 100644
--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -1043,29 +1043,6 @@
Select(N->getOperand(3)),
getI32Imm(BROpc));
}
-
- case ISD::RET: {
- SDOperand Chain = Select(N->getOperand(0)); // Token chain.
-
- if (N->getNumOperands() == 2) {
- SDOperand Val = Select(N->getOperand(1));
- if (N->getOperand(1).getValueType() == MVT::i32) {
- Chain = CurDAG->getCopyToReg(Chain, PPC::R3, Val);
- } else {
- assert(MVT::isFloatingPoint(N->getOperand(1).getValueType()));
- Chain = CurDAG->getCopyToReg(Chain, PPC::F1, Val);
- }
- } else if (N->getNumOperands() > 1) {
- assert(N->getOperand(1).getValueType() == MVT::i32 &&
- N->getOperand(2).getValueType() == MVT::i32 &&
- N->getNumOperands() == 3 && "Unknown two-register ret value!");
- Chain = CurDAG->getCopyToReg(Chain, PPC::R4, Select(N->getOperand(1)));
- Chain = CurDAG->getCopyToReg(Chain, PPC::R3, Select(N->getOperand(2)));
- }
-
- // Finally, select this to a blr (return) instruction.
- return CurDAG->SelectNodeTo(N, PPC::BLR, MVT::Other, Chain);
- }
case ISD::BR_CC:
case ISD::BRTWOWAY_CC: {
SDOperand Chain = Select(N->getOperand(0));
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index ba3fa0e..0e5000e 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -793,15 +793,26 @@
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 Copy;
+ switch (Op.getValueType()) {
+ default: assert(0 && "Unknown type to return!");
+ case MVT::i32:
+ Copy = DAG.getCopyToReg(Chain, PPC::R3, Op, SDOperand());
+ break;
+ case MVT::f32:
+ case MVT::f64:
+ Copy = DAG.getCopyToReg(Chain, PPC::F1, Op, SDOperand());
+ break;
+ case 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));
+ Copy = DAG.getCopyToReg(Chain, PPC::R3, Hi, SDOperand());
+ Copy = DAG.getCopyToReg(Copy, PPC::R4, Lo, Copy.getValue(1));
+ break;
}
+ return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
}
SDOperand PPCTargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h
index 4cce315..daf392c 100644
--- a/lib/Target/PowerPC/PPCISelLowering.h
+++ b/lib/Target/PowerPC/PPCISelLowering.h
@@ -54,12 +54,14 @@
/// at function entry, used for PIC code.
GlobalBaseReg,
-
/// These nodes represent the 32-bit PPC shifts that operate on 6-bit
/// shift amounts. These nodes are generated by the multi-precision shift
/// code.
SRL, SRA, SHL,
- };
+
+ /// Return with a flag operand, matched by 'blr'
+ RET_FLAG,
+};
}
class PPCTargetLowering : public TargetLowering {
diff --git a/lib/Target/PowerPC/PPCInstrFormats.td b/lib/Target/PowerPC/PPCInstrFormats.td
index 8b28e5f..07f0e1c 100644
--- a/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/lib/Target/PowerPC/PPCInstrFormats.td
@@ -328,12 +328,14 @@
}
class XLForm_2<bits<6> opcode, bits<10> xo, bit lk, dag OL, string asmstr,
- InstrItinClass itin>
+ InstrItinClass itin, list<dag> pattern>
: I<opcode, OL, asmstr, itin> {
bits<5> BO;
bits<5> BI;
bits<2> BH;
+ let Pattern = pattern;
+
let Inst{6-10} = BO;
let Inst{11-15} = BI;
let Inst{16-18} = 0;
@@ -343,8 +345,8 @@
}
class XLForm_2_ext<bits<6> opcode, bits<10> xo, bits<5> bo, bits<5> bi, bit lk,
- dag OL, string asmstr, InstrItinClass itin>
- : XLForm_2<opcode, xo, lk, OL, asmstr, itin> {
+ dag OL, string asmstr, InstrItinClass itin, list<dag> pattern>
+ : XLForm_2<opcode, xo, lk, OL, asmstr, itin, pattern> {
let BO = bo;
let BI = bi;
let BH = 0;
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 12a6cfb..a0356a6 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -46,6 +46,9 @@
def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeq,[SDNPHasChain]>;
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PPCCallSeq,[SDNPHasChain]>;
+def SDT_PPCRetFlag : SDTypeProfile<0, 1, [ SDTCisVT<0, FlagVT>]>;
+def retflag : SDNode<"PPCISD::RET_FLAG", SDT_PPCRetFlag, [SDNPHasChain]>;
+
//===----------------------------------------------------------------------===//
// PowerPC specific transformation functions and pattern fragments.
//
@@ -221,8 +224,8 @@
let isTerminator = 1 in {
let isReturn = 1 in
- def BLR : XLForm_2_ext<19, 16, 20, 0, 0, (ops), "blr", BrB>;
- def BCTR : XLForm_2_ext<19, 528, 20, 0, 0, (ops), "bctr", BrB>;
+ def BLR : XLForm_2_ext<19, 16, 20, 0, 0, (ops), "blr", BrB, [(ret)]>;
+ def BCTR : XLForm_2_ext<19, 528, 20, 0, 0, (ops), "bctr", BrB, []>;
}
let Defs = [LR] in
@@ -267,7 +270,8 @@
"bl $func", BrB, []>;
def BLA : IForm<18, 1, 1, (ops aaddr:$func, variable_ops),
"bla $func", BrB, []>;
- def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops variable_ops), "bctrl", BrB>;
+ def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops variable_ops), "bctrl", BrB,
+ []>;
}
// D-Form instructions. Most instructions that perform an operation on a
@@ -1052,6 +1056,8 @@
def : Pat<(f64 (extload xaddr:$src, f32)),
(FMRSD (LFSX xaddr:$src))>;
+def : Pat<(retflag FLAG), (BLR)>;
+
// Same as above, but using a temporary. FIXME: implement temporaries :)
/*
def : Pattern<(xor GPRC:$in, imm:$imm),
diff --git a/lib/Target/PowerPC/PPCRegisterInfo.td b/lib/Target/PowerPC/PPCRegisterInfo.td
index f349500..c8ac374 100644
--- a/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -132,6 +132,14 @@
// VRsave register
def VRSAVE: SPR<256, "VRsave">;
+// FIXME:
+// HACKTROCITY: define a flags reg class for things that need to take a flag.
+// this should really be handled by tablgen.
+def FLAG: SPR<1023, "Flag">;
+def FLAGRC : RegisterClass<"PPC", [FlagVT], 32, [FLAG]> {
+ let Size = 32;
+}
+
/// Register classes
// Allocate volatiles first
// then nonvolatiles in reverse order since stmw/lmw save from rN to r31