mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-08 21:32:39 +00:00
Make PPC call lowering more aggressive, making the isel matching code simple
enough to be autogenerated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28354 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7e399c14ab
commit
c703a8fbf8
@ -152,7 +152,6 @@ namespace {
|
||||
|
||||
private:
|
||||
SDOperand SelectSETCC(SDOperand Op);
|
||||
SDOperand SelectCALL(SDOperand Op);
|
||||
};
|
||||
}
|
||||
|
||||
@ -864,66 +863,6 @@ SDOperand PPCDAGToDAGISel::SelectSETCC(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.
|
||||
@ -947,9 +886,6 @@ void PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
|
||||
case ISD::SETCC:
|
||||
Result = SelectSETCC(Op);
|
||||
return;
|
||||
case PPCISD::CALL:
|
||||
Result = SelectCALL(Op);
|
||||
return;
|
||||
case PPCISD::GlobalBaseReg:
|
||||
Result = getGlobalBaseReg();
|
||||
return;
|
||||
|
@ -276,6 +276,8 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
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";
|
||||
@ -877,6 +879,21 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
|
||||
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();
|
||||
@ -1026,22 +1043,59 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
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);
|
||||
|
||||
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::BCTRL, NodeTys, Ops);
|
||||
InFlag = Chain.getValue(1);
|
||||
Callee.Val = 0;
|
||||
}
|
||||
|
||||
// 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)
|
||||
Ops.push_back(InFlag);
|
||||
Chain = DAG.getNode(PPCISD::CALL, NodeTys, Ops);
|
||||
InFlag = Chain.getValue(1);
|
||||
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();
|
||||
@ -1086,6 +1140,11 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
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);
|
||||
|
@ -75,9 +75,17 @@ namespace llvm {
|
||||
/// 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,
|
||||
|
||||
|
@ -24,7 +24,6 @@ def SDT_PPCShiftOp : SDTypeProfile<1, 2, [ // PPCshl, PPCsra, PPCsrl
|
||||
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>
|
||||
@ -73,10 +72,14 @@ def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeq,[SDNPHasChain]>;
|
||||
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, []>;
|
||||
@ -308,11 +311,11 @@ let isCall = 1, noResults = 1, PPC970_Unit = 7,
|
||||
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
|
||||
@ -701,8 +704,10 @@ def MCRF : XLForm_3<19, 0, (ops CRRC:$BF, CRRC:$BFA),
|
||||
//
|
||||
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;
|
||||
@ -1013,7 +1018,13 @@ def : Pat<(rotl GPRC:$in, GPRC:$sh),
|
||||
(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)>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user