private:
SDOperand SelectSETCC(SDOperand Op);
- SDOperand SelectCALL(SDOperand Op);
};
}
}
}
-/// isCallCompatibleAddress - Return true if the specified 32-bit value is
-/// representable in the immediate field of a Bx instruction.
-static bool isCallCompatibleAddress(ConstantSDNode *C) {
- int Addr = C->getValue();
- if (Addr & 3) return false; // Low 2 bits are implicitly zero.
- return (Addr << 6 >> 6) == Addr; // Top 6 bits have to be sext of immediate.
-}
-
-SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
- SDNode *N = Op.Val;
- SDOperand Chain, Flag;
- Select(Chain, N->getOperand(0));
- if (N->getNumOperands() == 3) // input flag
- Select(Flag, N->getOperand(2));
-
- unsigned CallOpcode;
-
- std::vector<SDOperand> CallArgs;
- if (GlobalAddressSDNode *GASD =
- dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) {
- CallOpcode = PPC::BL;
- CallArgs.push_back(N->getOperand(1));
- } else if (ExternalSymbolSDNode *ESSDN =
- dyn_cast<ExternalSymbolSDNode>(N->getOperand(1))) {
- CallOpcode = PPC::BL;
- CallArgs.push_back(N->getOperand(1));
- } else if (isa<ConstantSDNode>(N->getOperand(1)) &&
- isCallCompatibleAddress(cast<ConstantSDNode>(N->getOperand(1)))) {
- ConstantSDNode *C = cast<ConstantSDNode>(N->getOperand(1));
- CallOpcode = PPC::BLA;
- CallArgs.push_back(getI32Imm((int)C->getValue() >> 2));
- } else {
- // Copy the callee address into the CTR register.
- SDOperand Callee;
- Select(Callee, N->getOperand(1));
- if (Flag.Val)
- Chain = SDOperand(CurDAG->getTargetNode(PPC::MTCTR, MVT::Other, MVT::Flag,
- Callee, Chain, Flag), 0);
- else
- Chain = SDOperand(CurDAG->getTargetNode(PPC::MTCTR, MVT::Other, MVT::Flag,
- Callee, Chain), 0);
- Flag = Chain.getValue(1);
-
- // Copy the callee address into R12 on darwin.
- Chain = CurDAG->getCopyToReg(Chain, PPC::R12, Callee, Flag);
- Flag = Chain.getValue(1);
-
- CallOpcode = PPC::BCTRL;
- }
-
- // Emit the call itself.
- CallArgs.push_back(Chain);
- if (Flag.Val)
- CallArgs.push_back(Flag);
- Chain = SDOperand(CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag,
- CallArgs), 0);
- CodeGenMap[Op.getValue(0)] = Chain;
- CodeGenMap[Op.getValue(1)] = Chain.getValue(1);
- return Chain.getValue(Op.ResNo);
-}
// Select - Convert the specified operand from a target-independent to a
// target-specific node if it hasn't already been changed.
case ISD::SETCC:
Result = SelectSETCC(Op);
return;
- case PPCISD::CALL:
- Result = SelectCALL(Op);
- return;
case PPCISD::GlobalBaseReg:
Result = getGlobalBaseReg();
return;
case PPCISD::EXTSW_32: return "PPCISD::EXTSW_32";
case PPCISD::STD_32: return "PPCISD::STD_32";
case PPCISD::CALL: return "PPCISD::CALL";
+ case PPCISD::MTCTR: return "PPCISD::MTCTR";
+ case PPCISD::BCTRL: return "PPCISD::BCTRL";
case PPCISD::RET_FLAG: return "PPCISD::RET_FLAG";
case PPCISD::MFCR: return "PPCISD::MFCR";
case PPCISD::VCMP: return "PPCISD::VCMP";
return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues);
}
+/// isCallCompatibleAddress - Return the immediate to use if the specified
+/// 32-bit value is representable in the immediate field of a BxA instruction.
+static SDNode *isBLACompatibleAddress(SDOperand Op, SelectionDAG &DAG) {
+ ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
+ if (!C) return 0;
+
+ int Addr = C->getValue();
+ if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
+ (Addr << 6 >> 6) != Addr)
+ return 0; // Top 6 bits have to be sext of immediate.
+
+ return DAG.getConstant((int)C->getValue() >> 2, MVT::i32).Val;
+}
+
+
static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
SDOperand Chain = Op.getOperand(0);
unsigned CallingConv= cast<ConstantSDNode>(Op.getOperand(1))->getValue();
InFlag = Chain.getValue(1);
}
- // If the callee is a GlobalAddress node (quite common, every direct call is)
- // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
+ std::vector<MVT::ValueType> NodeTys;
+
+ // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
+ // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
+ // node so that legalize doesn't hack it.
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
+ else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
+ Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType());
+ else if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG))
+ // If this is an absolute destination address, use the munged value.
+ Callee = SDOperand(Dest, 0);
+ else {
+ // Otherwise, this is an indirect call. We have to use a MTCTR/BCTRL pair
+ // to do the call, we can't use PPCISD::CALL.
+ std::vector<SDOperand> Ops;
+ Ops.push_back(Chain);
+ Ops.push_back(Callee);
+ NodeTys.push_back(MVT::Other);
+ NodeTys.push_back(MVT::Flag);
+
+ if (InFlag.Val)
+ Ops.push_back(InFlag);
+ Chain = DAG.getNode(PPCISD::MTCTR, NodeTys, Ops);
+ InFlag = Chain.getValue(1);
+
+ // Copy the callee address into R12 on darwin.
+ Chain = DAG.getCopyToReg(Chain, PPC::R12, Callee, InFlag);
+ InFlag = Chain.getValue(1);
- // Create the PPCISD::CALL node itself.
- std::vector<MVT::ValueType> NodeTys;
- NodeTys.push_back(MVT::Other); // Returns a chain
- NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
- std::vector<SDOperand> Ops;
- Ops.push_back(Chain);
- Ops.push_back(Callee);
- if (InFlag.Val)
+ NodeTys.clear();
+ NodeTys.push_back(MVT::Other);
+ NodeTys.push_back(MVT::Flag);
+ Ops.clear();
+ Ops.push_back(Chain);
Ops.push_back(InFlag);
- Chain = DAG.getNode(PPCISD::CALL, NodeTys, Ops);
- InFlag = Chain.getValue(1);
+ Chain = DAG.getNode(PPCISD::BCTRL, NodeTys, Ops);
+ InFlag = Chain.getValue(1);
+ Callee.Val = 0;
+ }
+
+ // Create the PPCISD::CALL node itself.
+ if (Callee.Val) {
+ NodeTys.push_back(MVT::Other); // Returns a chain
+ NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
+ std::vector<SDOperand> Ops;
+ Ops.push_back(Chain);
+ Ops.push_back(Callee);
+ if (InFlag.Val)
+ Ops.push_back(InFlag);
+ Chain = DAG.getNode(PPCISD::CALL, NodeTys, Ops);
+ InFlag = Chain.getValue(1);
+ }
std::vector<SDOperand> ResultVals;
NodeTys.clear();
DAG.getConstant(NumBytes, MVT::i32));
NodeTys.push_back(MVT::Other);
+ // If the function returns void, just return the chain.
+ if (ResultVals.empty())
+ return Chain;
+
+ // Otherwise, merge everything together with a MERGE_VALUES node.
ResultVals.push_back(Chain);
SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys, ResultVals);
return Res.getValue(Op.ResNo);
/// STD_32 - This is the STD instruction for use with "32-bit" registers.
STD_32,
- /// CALL - A function call.
+ /// CALL - A direct function call.
CALL,
+ /// CHAIN,FLAG = MTCTR(VAL, CHAIN[, INFLAG]) - Directly corresponds to a
+ /// MTCTR instruction.
+ MTCTR,
+
+ /// CHAIN,FLAG = BCTRL(CHAIN, INFLAG) - Directly corresponds to a
+ /// BCTRL instruction.
+ BCTRL,
+
/// Return with a flag operand, matched by 'blr'
RET_FLAG,
SDTCisVT<0, i32>, SDTCisVT<1, i32>, SDTCisVT<2, i32>
]>;
def SDT_PPCCallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>;
-def SDT_PPCRetFlag : SDTypeProfile<0, 0, []>;
def SDT_PPCvperm : SDTypeProfile<1, 3, [
SDTCisVT<3, v16i8>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PPCCallSeq,[SDNPHasChain]>;
def SDT_PPCCall : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
-def call : SDNode<"PPCISD::CALL", SDT_PPCCall,
+def PPCcall : SDNode<"PPCISD::CALL", SDT_PPCCall,
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
+def PPCmtctr : SDNode<"PPCISD::MTCTR", SDT_PPCCall,
+ [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
+def PPCbctrl : SDNode<"PPCISD::BCTRL", SDTRet,
+ [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
-def retflag : SDNode<"PPCISD::RET_FLAG", SDT_PPCRetFlag,
+def retflag : SDNode<"PPCISD::RET_FLAG", SDTRet,
[SDNPHasChain, SDNPOptInFlag]>;
def PPCvcmp : SDNode<"PPCISD::VCMP" , SDT_PPCvcmp, []>;
CR0,CR1,CR5,CR6,CR7] in {
// Convenient aliases for call instructions
def BL : IForm<18, 0, 1, (ops calltarget:$func),
- "bl $func", BrB, []>;
+ "bl $func", BrB, []>; // See Pat patterns below.
def BLA : IForm<18, 1, 1, (ops aaddr:$func),
- "bla $func", BrB, []>;
+ "bla $func", BrB, [(PPCcall imm:$func)]>;
def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops), "bctrl", BrB,
- []>;
+ [(PPCbctrl)]>;
}
// D-Form instructions. Most instructions that perform an operation on a
//
def MFCTR : XFXForm_1_ext<31, 339, 9, (ops GPRC:$rT), "mfctr $rT", SprMFSPR>,
PPC970_DGroup_First, PPC970_Unit_FXU;
+let Pattern = [(PPCmtctr GPRC:$rS)] in {
def MTCTR : XFXForm_7_ext<31, 467, 9, (ops GPRC:$rS), "mtctr $rS", SprMTSPR>,
PPC970_DGroup_First, PPC970_Unit_FXU;
+}
def MTLR : XFXForm_7_ext<31, 467, 8, (ops GPRC:$rS), "mtlr $rS", SprMTSPR>,
PPC970_DGroup_First, PPC970_Unit_FXU;
(RLWNM GPRC:$in, GPRC:$sh, 0, 31)>;
def : Pat<(rotl GPRC:$in, (i32 imm:$imm)),
(RLWINM GPRC:$in, imm:$imm, 0, 31)>;
-
+
+// Calls
+def : Pat<(PPCcall tglobaladdr:$dst),
+ (BL tglobaladdr:$dst)>;
+def : Pat<(PPCcall texternalsym:$dst),
+ (BL texternalsym:$dst)>;
+
// Hi and Lo for Darwin Global Addresses.
def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>;
def : Pat<(PPClo tglobaladdr:$in, 0), (LI tglobaladdr:$in)>;