This patch moves <font size="2"><span style="font-size: 10pt;">transformation of JmpLink and related nodes done during instruction selection to Legalize.<br><br>Index: lib/Target/Mips/MipsISelDAGToDAG.cpp<br>===================================================================<br>
--- lib/Target/Mips/MipsISelDAGToDAG.cpp  (revision 128742)<br>+++ lib/Target/Mips/MipsISelDAGToDAG.cpp  (working copy)<br>@@ -122,7 +122,8 @@<br>     if ((Addr.getOpcode() == ISD::TargetGlobalAddress) ||<br>         (Addr.getOpcode() == ISD::TargetConstantPool) ||<br>
         (Addr.getOpcode() == ISD::TargetJumpTable) ||<br>-        (Addr.getOpcode() == ISD::TargetBlockAddress)) {<br>+        (Addr.getOpcode() == ISD::TargetBlockAddress) ||<br>+        (Addr.getOpcode() == ISD::TargetExternalSymbol)) {<br>
       Base   = CurDAG->getRegister(Mips::GP, MVT::i32);<br>       Offset = Addr;<br>       return true;<br>@@ -444,61 +445,6 @@<br>         return ResNode;<br>       // Other cases are autogenerated.<br>       break;<br>
-<br>-    /// Handle direct and indirect calls when using PIC. On PIC, when<br>-    /// GOT is smaller than about 64k (small code) the GA target is<br>-    /// loaded with only one instruction. Otherwise GA's target must<br>
-    /// be loaded with 3 instructions.<br>-    case MipsISD::JmpLink: {<br>-      if (TM.getRelocationModel() == Reloc::PIC_) {<br>-        unsigned LastOpNum = Node->getNumOperands()-1;<br>-<br>-        SDValue Chain  = Node->getOperand(0);<br>
-        SDValue Callee = Node->getOperand(1);<br>-        SDValue InFlag;<br>-<br>-        // Skip the incomming flag if present<br>-        if (Node->getOperand(LastOpNum).getValueType() == MVT::Glue)<br>-          LastOpNum--;<br>
-<br>-        if ( (isa<GlobalAddressSDNode>(Callee)) ||<br>-             (isa<ExternalSymbolSDNode>(Callee)) )<br>-        {<br>-          /// Direct call for global addresses and external symbols<br>-          SDValue GPReg = CurDAG->getRegister(Mips::GP, MVT::i32);<br>
-<br>-          // Use load to get GOT target<br>-          SDValue Ops[] = { Callee, GPReg, Chain };<br>-          SDValue Load = SDValue(CurDAG->getMachineNode(Mips::LW, dl, MVT::i32,<br>-                                     MVT::Other, Ops, 3), 0);<br>
-          Chain = Load.getValue(1);<br>-<br>-          // Call target must be on T9<br>-          Chain = CurDAG->getCopyToReg(Chain, dl, Mips::T9, Load, InFlag);<br>-        } else<br>-          /// Indirect call<br>
-          Chain = CurDAG->getCopyToReg(Chain, dl, Mips::T9, Callee, InFlag);<br>-<br>-        // Map the JmpLink operands to JALR<br>-        SDVTList NodeTys = CurDAG->getVTList(MVT::Other, MVT::Glue);<br>-        SmallVector<SDValue, 8> Ops;<br>
-        Ops.push_back(CurDAG->getRegister(Mips::T9, MVT::i32));<br>-<br>-        for (unsigned i = 2, e = LastOpNum+1; i != e; ++i)<br>-          Ops.push_back(Node->getOperand(i));<br>-        Ops.push_back(Chain);<br>
-        Ops.push_back(Chain.getValue(1));<br>-<br>-        // Emit Jump and Link Register<br>-        SDNode *ResNode = CurDAG->getMachineNode(Mips::JALR, dl, NodeTys,<br>-                                  &Ops[0], Ops.size());<br>
-<br>-        // Replace Chain and InFlag<br>-        ReplaceUses(SDValue(Node, 0), SDValue(ResNode, 0));<br>-        ReplaceUses(SDValue(Node, 1), SDValue(ResNode, 1));<br>-        return ResNode;<br>-      }<br>-    }<br>
   }<br><br>   // Select the default instruction<br>Index: lib/Target/Mips/MipsISelLowering.cpp<br>===================================================================<br>--- lib/Target/Mips/MipsISelLowering.cpp  (revision 128741)<br>
+++ lib/Target/Mips/MipsISelLowering.cpp  (working copy)<br>@@ -1201,13 +1201,35 @@<br>   // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol<br>   // node so that legalize doesn't hack it.<br>   unsigned char OpFlag = IsPIC ? MipsII::MO_GOT_CALL : MipsII::MO_NO_FLAG;<br>
-  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))<br>+  bool LoadSymAddr = false;<br>+<br>+  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {<br>     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl,<br>
-                                getPointerTy(), 0, OpFlag);<br>-  else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))<br>+                                        getPointerTy(), 0, OpFlag);<br>
+    LoadSymAddr = true;<br>+  }<br>+  else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {<br>     Callee = DAG.getTargetExternalSymbol(S->getSymbol(),<br>                                 getPointerTy(), OpFlag);<br>
+    LoadSymAddr = true;<br>+  }<br><br>+  // Create nodes that load address of callee and copy it to T9<br>+  if (IsPIC) {<br>+    if (LoadSymAddr) {<br>+      // load callee address<br>+      Callee = DAG.getLoad(MVT::i32, dl, Chain, Callee,<br>
+                                        MachinePointerInfo::getGOT(),<br>+                                        false, false, 0);<br>+      Chain = Callee.getValue(1);<br>+    }<br>+<br>+    // copy to T9<br>+    Chain = DAG.getCopyToReg(Chain, dl, Mips::T9, Callee, SDValue(0, 0));<br>
+    InFlag = Chain.getValue(1);<br>+    Callee = DAG.getRegister(Mips::T9, MVT::i32);<br>+  }<br>+<br>   // MipsJmpLink = #chain, #target_address, #opt_in_flags...<br>   //             = Chain, Callee, Reg#1, Reg#2, ...<br>
   //<br>                                                      <br></span></font>