Make PPC call lowering more aggressive, making the isel matching code simple
authorChris Lattner <sabre@nondot.org>
Wed, 17 May 2006 19:00:46 +0000 (19:00 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 17 May 2006 19:00:46 +0000 (19:00 +0000)
enough to be autogenerated.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28354 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCISelDAGToDAG.cpp
lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/PowerPC/PPCISelLowering.h
lib/Target/PowerPC/PPCInstrInfo.td

index 2a1d2442d818e6ec154836d7d87701802f362b21..c164020ecaab3f3331509cccbd694b2580233ec1 100644 (file)
@@ -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;
index 7a24b31c6bec5c996e1eb2e4d2f49142b70e5a0d..87e2999eb60676b5dd8cd04dd68a0f72f41feea2 100644 (file)
@@ -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);
 
-  // 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();
@@ -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);
index 0206f0c1c2adcea97d342450b5d967a7dbbfe61e..dbd25e5c85e51505e7aff35e299ae834f2c63603 100644 (file)
@@ -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,
       
index e195414fe0146f9c2baa664bb50b9f029bd3a038..d75c7940795e1332df525025776c953b63963a45 100644 (file)
@@ -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)>;