Patch to clean up function call pseudos and support the BLA instruction,
authorNate Begeman <natebegeman@mac.com>
Wed, 16 Nov 2005 00:48:01 +0000 (00:48 +0000)
committerNate Begeman <natebegeman@mac.com>
Wed, 16 Nov 2005 00:48:01 +0000 (00:48 +0000)
which branches to an absolute address.  This is required to support objc
direct dispatch.

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

lib/Target/PowerPC/PPCAsmPrinter.cpp
lib/Target/PowerPC/PPCCodeEmitter.cpp
lib/Target/PowerPC/PPCISelDAGToDAG.cpp
lib/Target/PowerPC/PPCISelPattern.cpp
lib/Target/PowerPC/PPCInstrInfo.td

index fd3c13ed691c199c84c6c4bd2b87df670ee2336f..9ef6579d304bd8974d952848a8721d9f173e276b 100644 (file)
@@ -152,6 +152,10 @@ namespace {
                 TM.getInstrInfo()->isCall(MI->getOpcode()));
       }
     }
+    void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo,
+                             MVT::ValueType VT) {
+     O << (int)MI->getOperand(OpNo).getImmedValue()*4;
+    }
     void printPICLabel(const MachineInstr *MI, unsigned OpNo,
                        MVT::ValueType VT) {
       // FIXME: should probably be converted to cout.width and cout.fill
index 6a8df47b50d6313dad063e1f33e892e7d573c765..d576b79eb715914d0e4c2622db289e9a5ab1f08d 100644 (file)
@@ -196,7 +196,7 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) {
                       MO.getGlobal()->hasWeakLinkage() ||
                       MO.getGlobal()->isExternal();
     unsigned Reloc = 0;
-    if (MI.getOpcode() == PPC::CALLpcrel)
+    if (MI.getOpcode() == PPC::BL)
       Reloc = PPC::reloc_pcrel_bx;
     else {
       switch (MI.getOpcode()) {
index 64161b59e210eb0f603e8e215cb014d1ba18101b..ad0a0a02193cc9352d26f5b40134cc2fb4ac4962 100644 (file)
@@ -735,6 +735,14 @@ SDOperand PPCDAGToDAGISel::SelectSETCC(SDOperand Op) {
   return SDOperand(N, 0);
 }
 
+/// 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 = Select(N->getOperand(0));
@@ -744,13 +752,18 @@ SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
   
   if (GlobalAddressSDNode *GASD =
       dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) {
-    CallOpcode = PPC::CALLpcrel;
+    CallOpcode = PPC::BL;
     CallOperands.push_back(CurDAG->getTargetGlobalAddress(GASD->getGlobal(),
                                                           MVT::i32));
   } else if (ExternalSymbolSDNode *ESSDN =
              dyn_cast<ExternalSymbolSDNode>(N->getOperand(1))) {
-    CallOpcode = PPC::CALLpcrel;
+    CallOpcode = PPC::BL;
     CallOperands.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;
+    CallOperands.push_back(getI32Imm((int)C->getValue() >> 2));
   } else {
     // Copy the callee address into the CTR register.
     SDOperand Callee = Select(N->getOperand(1));
@@ -759,11 +772,9 @@ SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
     // Copy the callee address into R12 on darwin.
     SDOperand R12 = CurDAG->getRegister(PPC::R12, MVT::i32);
     Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R12, Callee);
-    
-    CallOperands.push_back(getI32Imm(20));  // Information to encode indcall
-    CallOperands.push_back(getI32Imm(0));   // Information to encode indcall
+
     CallOperands.push_back(R12);
-    CallOpcode = PPC::CALLindirect;
+    CallOpcode = PPC::BCTRL;
   }
   
   unsigned GPR_idx = 0, FPR_idx = 0;
index 1a9d09c64bc9b638b6af265348b95a7af3ec9d1c..628295c095c24c56272ba21ca3575716be68e72f 100644 (file)
@@ -842,18 +842,15 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
     // Emit the correct call instruction based on the type of symbol called.
     if (GlobalAddressSDNode *GASD =
         dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {
-      CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(),
-                                                           true);
+      CallMI = BuildMI(PPC::BL, 1).addGlobalAddress(GASD->getGlobal(), true);
     } else if (ExternalSymbolSDNode *ESSDN =
                dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) {
-      CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(),
-                                                            true);
+      CallMI = BuildMI(PPC::BL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
     } else {
       Tmp1 = SelectExpr(N.getOperand(1));
       BuildMI(BB, PPC::MTCTR, 1).addReg(Tmp1);
       BuildMI(BB, PPC::OR4, 2, PPC::R12).addReg(Tmp1).addReg(Tmp1);
-      CallMI = BuildMI(PPC::CALLindirect, 3).addImm(20).addImm(0)
-        .addReg(PPC::R12);
+      CallMI = BuildMI(PPC::BCTRL, 1).addReg(PPC::R12);
     }
 
     // Load the register args to virtual regs
index 73362a9846f529c983a62f88ab0a0a024de089f6..f65de6115df871137b7cc1ce0a3e8fc7fe7c715f 100644 (file)
@@ -128,6 +128,9 @@ def s16immX4  : Operand<i32> {   // Multiply imm by 4 before printing.
 def target : Operand<i32> {
   let PrintMethod = "printBranchOperand";
 }
+def aaddr : Operand<i32> {
+  let PrintMethod = "printAbsAddrOperand";
+}
 def piclabel: Operand<i32> {
   let PrintMethod = "printPICLabel";
 }
@@ -186,9 +189,6 @@ let isBranch = 1, isTerminator = 1 in {
                                 target:$true, target:$false),
                            "; COND_BRANCH", []>;
   def B   : IForm<18, 0, 0, (ops target:$func), "b $func", BrB>;
-//def BA  : IForm<18, 1, 0, (ops target:$func), "ba $func", BrB>;
-  def BL  : IForm<18, 0, 1, (ops target:$func), "bl $func", BrB>;
-//def BLA : IForm<18, 1, 1, (ops target:$func), "bla $func", BrB>;
 
   // FIXME: 4*CR# needs to be added to the BI field!
   // This will only work for CR0 as it stands now
@@ -217,10 +217,9 @@ let isCall = 1,
           LR,CTR,
           CR0,CR1,CR5,CR6,CR7] in {
   // Convenient aliases for call instructions
-  def CALLpcrel : IForm<18, 0, 1, (ops target:$func, variable_ops),
-                        "bl $func", BrB>;
-  def CALLindirect : XLForm_2_ext<19, 528, 20, 0, 1,
-                                  (ops variable_ops), "bctrl", BrB>;
+  def BL  : IForm<18, 0, 1, (ops target:$func, variable_ops), "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>;
 }
 
 // D-Form instructions.  Most instructions that perform an operation on a