[MIPS GlobalISel] Handle position independent code
authorPetar Avramovic <Petar.Avramovic@rt-rk.com>
Fri, 31 May 2019 08:27:06 +0000 (08:27 +0000)
committerPetar Avramovic <Petar.Avramovic@rt-rk.com>
Fri, 31 May 2019 08:27:06 +0000 (08:27 +0000)
Handle position independent code for MIPS32.
When callee is global address, lower call will emit callee
as G_GLOBAL_VALUE and add target flag if needed.
Support $gp in getRegBankFromRegClass().
Select G_GLOBAL_VALUE, specially handle case when
there are target flags attached by lowerCall.

Differential Revision: https://reviews.llvm.org/D62589

llvm-svn: 362210

llvm/lib/Target/Mips/MipsCallLowering.cpp
llvm/lib/Target/Mips/MipsInstructionSelector.cpp
llvm/lib/Target/Mips/MipsMachineFunction.cpp
llvm/lib/Target/Mips/MipsMachineFunction.h
llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp
llvm/test/CodeGen/Mips/GlobalISel/instruction-select/gloal_address_pic.mir [new file with mode: 0644]
llvm/test/CodeGen/Mips/GlobalISel/irtranslator/global_address_pic.ll [new file with mode: 0644]
llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/global_address_pic.ll [new file with mode: 0644]
llvm/test/CodeGen/Mips/GlobalISel/regbankselect/global_address_pic.mir [new file with mode: 0644]

index 04aff60..50fb986 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "MipsCallLowering.h"
 #include "MipsCCState.h"
+#include "MipsMachineFunction.h"
 #include "MipsTargetMachine.h"
 #include "llvm/CodeGen/Analysis.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
@@ -522,10 +523,22 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   MachineInstrBuilder CallSeqStart =
       MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN);
 
+  const bool IsCalleeGlobalPIC =
+      Callee.isGlobal() && TM.isPositionIndependent();
+
   MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(
-      Callee.isReg() ? Mips::JALRPseudo : Mips::JAL);
+      Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL);
   MIB.addDef(Mips::SP, RegState::Implicit);
-  MIB.add(Callee);
+  if (IsCalleeGlobalPIC) {
+    unsigned CalleeReg =
+        MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32));
+    MachineInstr *CalleeGlobalValue =
+        MIRBuilder.buildGlobalValue(CalleeReg, Callee.getGlobal());
+    if (!Callee.getGlobal()->hasLocalLinkage())
+      CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL);
+    MIB.addUse(CalleeReg);
+  } else
+    MIB.add(Callee);
   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
   MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));
 
@@ -568,6 +581,12 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   NextStackOffset = alignTo(NextStackOffset, StackAlignment);
   CallSeqStart.addImm(NextStackOffset).addImm(0);
 
+  if (IsCalleeGlobalPIC) {
+    MIRBuilder.buildCopy(
+        Mips::GP,
+        MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel());
+    MIB.addDef(Mips::GP, RegState::Implicit);
+  }
   MIRBuilder.insertInstr(MIB);
   if (MIB->getOpcode() == Mips::JALRPseudo) {
     const MipsSubtarget &STI =
index a03e7ef..442244a 100644 (file)
@@ -11,6 +11,7 @@
 /// \todo This should be generated by TableGen.
 //===----------------------------------------------------------------------===//
 
+#include "MipsMachineFunction.h"
 #include "MipsRegisterBankInfo.h"
 #include "MipsTargetMachine.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
@@ -356,29 +357,59 @@ bool MipsInstructionSelector::select(MachineInstr &I,
     return true;
   }
   case G_GLOBAL_VALUE: {
-    if (MF.getTarget().isPositionIndependent())
-      return false;
-
     const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
-    unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
-    MachineInstr *LUi, *ADDiu;
+    if (MF.getTarget().isPositionIndependent()) {
+      MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
+                                .addDef(I.getOperand(0).getReg())
+                                .addReg(MF.getInfo<MipsFunctionInfo>()
+                                            ->getGlobalBaseRegForGlobalISel())
+                                .addGlobalAddress(GVal);
+      // Global Values that don't have local linkage are handled differently
+      // when they are part of call sequence. MipsCallLowering::lowerCall
+      // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
+      // MO_GOT_CALL flag when Callee doesn't have local linkage.
+      if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL)
+        LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL);
+      else
+        LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT);
+      LWGOT->addMemOperand(
+          MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
+                                      MachineMemOperand::MOLoad, 4, 4));
+      if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
+        return false;
 
-    LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
-              .addDef(LUiReg)
-              .addGlobalAddress(GVal);
-    LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
+      if (GVal->hasLocalLinkage()) {
+        unsigned LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+        LWGOT->getOperand(0).setReg(LWGOTDef);
 
-    ADDiu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
+        MachineInstr *ADDiu =
+            BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
                 .addDef(I.getOperand(0).getReg())
-                .addUse(LUiReg)
+                .addReg(LWGOTDef)
                 .addGlobalAddress(GVal);
-    ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
-
-    if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
-      return false;
-    if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
-      return false;
+        ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
+        if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
+          return false;
+      }
+    } else {
+      unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+
+      MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
+                              .addDef(LUiReg)
+                              .addGlobalAddress(GVal);
+      LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
+      if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
+        return false;
 
+      MachineInstr *ADDiu =
+          BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
+              .addDef(I.getOperand(0).getReg())
+              .addUse(LUiReg)
+              .addGlobalAddress(GVal);
+      ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
+      if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
+        return false;
+    }
     I.eraseFromParent();
     return true;
   }
index 5774905..d489fac 100644 (file)
@@ -51,6 +51,14 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() {
   return GlobalBaseReg;
 }
 
+unsigned MipsFunctionInfo::getGlobalBaseRegForGlobalISel() {
+  if (!GlobalBaseReg) {
+    getGlobalBaseReg();
+    initGlobalBaseReg();
+  }
+  return GlobalBaseReg;
+}
+
 void MipsFunctionInfo::initGlobalBaseReg() {
   if (!GlobalBaseReg)
     return;
index b2c6c8d..d9d53c8 100644 (file)
@@ -33,6 +33,7 @@ public:
 
   bool globalBaseRegSet() const;
   unsigned getGlobalBaseReg();
+  unsigned getGlobalBaseRegForGlobalISel();
 
   // Insert instructions to initialize the global base register in the
   // first MBB of the function.
index 1192db7..4814ef4 100644 (file)
@@ -79,6 +79,7 @@ const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
   case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
   case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
   case Mips::SP32RegClassID:
+  case Mips::GP32RegClassID:
     return getRegBank(Mips::GPRBRegBankID);
   case Mips::FGRCCRegClassID:
   case Mips::FGR32RegClassID:
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/gloal_address_pic.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/gloal_address_pic.mir
new file mode 100644 (file)
index 0000000..d91a36e
--- /dev/null
@@ -0,0 +1,165 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -relocation-model=pic -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
+--- |
+
+  @val = global i32 0
+  @val_with_local_linkage = internal global i32 1
+
+  declare i32 @f(i32, i32)
+  define internal void @f_with_local_linkage() {entry: ret void}
+  define void @call_global() {entry: ret void}
+  define void @call_global_with_local_linkage() {entry: ret void}
+  define void @ret_global_int() {entry: ret void}
+  define void @ret_global_int_with_local_linkage() {entry: ret void}
+
+...
+---
+name:            f_with_local_linkage
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0, $a1
+
+    ; MIPS32-LABEL: name: f_with_local_linkage
+    ; MIPS32: liveins: $a0, $a1
+    ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+    ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu [[COPY1]], [[COPY]]
+    ; MIPS32: $v0 = COPY [[ADDu]]
+    ; MIPS32: RetRA implicit $v0
+    %0:gprb(s32) = COPY $a0
+    %1:gprb(s32) = COPY $a1
+    %2:gprb(s32) = G_ADD %1, %0
+    $v0 = COPY %2(s32)
+    RetRA implicit $v0
+
+...
+---
+name:            call_global
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0, $a1, $t9, $v0
+
+    ; MIPS32-LABEL: name: call_global
+    ; MIPS32: liveins: $a0, $a1, $t9, $v0, $t9, $v0
+    ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu $v0, $t9
+    ; MIPS32: [[ADDu1:%[0-9]+]]:gpr32 = ADDu $v0, $t9
+    ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+    ; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+    ; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[ADDu]], target-flags(mips-got-call) @f :: (load 4 from got)
+    ; MIPS32: $a0 = COPY [[COPY]]
+    ; MIPS32: $a1 = COPY [[COPY1]]
+    ; MIPS32: $gp = COPY [[ADDu1]]
+    ; MIPS32: JALRPseudo [[LW]], csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $gp, implicit-def $v0
+    ; MIPS32: [[COPY2:%[0-9]+]]:gpr32 = COPY $v0
+    ; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+    ; MIPS32: $v0 = COPY [[COPY2]]
+    ; MIPS32: RetRA implicit $v0
+    %4:gpr32 = ADDu $v0, $t9
+    %0:gprb(s32) = COPY $a0
+    %1:gprb(s32) = COPY $a1
+    ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+    %3:gpr32(p0) = G_GLOBAL_VALUE target-flags(mips-got-call) @f
+    $a0 = COPY %0(s32)
+    $a1 = COPY %1(s32)
+    $gp = COPY %4
+    JALRPseudo %3(p0), csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $gp, implicit-def $v0
+    %2:gprb(s32) = COPY $v0
+    ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+    $v0 = COPY %2(s32)
+    RetRA implicit $v0
+
+...
+---
+name:            call_global_with_local_linkage
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0, $a1, $t9, $v0
+
+    ; MIPS32-LABEL: name: call_global_with_local_linkage
+    ; MIPS32: liveins: $a0, $a1, $t9, $v0, $t9, $v0
+    ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu $v0, $t9
+    ; MIPS32: [[ADDu1:%[0-9]+]]:gpr32 = ADDu $v0, $t9
+    ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+    ; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+    ; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[ADDu]], target-flags(mips-got) @f_with_local_linkage :: (load 4 from got)
+    ; MIPS32: [[ADDiu:%[0-9]+]]:gpr32 = ADDiu [[LW]], target-flags(mips-abs-lo) @f_with_local_linkage
+    ; MIPS32: $a0 = COPY [[COPY]]
+    ; MIPS32: $a1 = COPY [[COPY1]]
+    ; MIPS32: $gp = COPY [[ADDu1]]
+    ; MIPS32: JALRPseudo [[ADDiu]], csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $gp, implicit-def $v0
+    ; MIPS32: [[COPY2:%[0-9]+]]:gpr32 = COPY $v0
+    ; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+    ; MIPS32: $v0 = COPY [[COPY2]]
+    ; MIPS32: RetRA implicit $v0
+    %4:gpr32 = ADDu $v0, $t9
+    %0:gprb(s32) = COPY $a0
+    %1:gprb(s32) = COPY $a1
+    ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+    %3:gpr32(p0) = G_GLOBAL_VALUE @f_with_local_linkage
+    $a0 = COPY %0(s32)
+    $a1 = COPY %1(s32)
+    $gp = COPY %4
+    JALRPseudo %3(p0), csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $gp, implicit-def $v0
+    %2:gprb(s32) = COPY $v0
+    ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+    $v0 = COPY %2(s32)
+    RetRA implicit $v0
+
+...
+---
+name:            ret_global_int
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    ; MIPS32-LABEL: name: ret_global_int
+    ; MIPS32: liveins: $t9, $v0
+    ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu $v0, $t9
+    ; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[ADDu]], target-flags(mips-got) @val :: (load 4 from got)
+    ; MIPS32: [[LW1:%[0-9]+]]:gpr32 = LW [[LW]], 0 :: (load 4 from @val)
+    ; MIPS32: $v0 = COPY [[LW1]]
+    ; MIPS32: RetRA implicit $v0
+    %1:gprb(p0) = G_GLOBAL_VALUE @val
+    %0:gprb(s32) = G_LOAD %1(p0) :: (load 4 from @val)
+    $v0 = COPY %0(s32)
+    RetRA implicit $v0
+
+...
+---
+name:            ret_global_int_with_local_linkage
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    ; MIPS32-LABEL: name: ret_global_int_with_local_linkage
+    ; MIPS32: liveins: $t9, $v0
+    ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu $v0, $t9
+    ; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[ADDu]], target-flags(mips-got) @val_with_local_linkage :: (load 4 from got)
+    ; MIPS32: [[ADDiu:%[0-9]+]]:gpr32 = ADDiu [[LW]], target-flags(mips-abs-lo) @val_with_local_linkage
+    ; MIPS32: [[LW1:%[0-9]+]]:gpr32 = LW [[ADDiu]], 0 :: (load 4 from @val_with_local_linkage)
+    ; MIPS32: $v0 = COPY [[LW1]]
+    ; MIPS32: RetRA implicit $v0
+    %1:gprb(p0) = G_GLOBAL_VALUE @val_with_local_linkage
+    %0:gprb(s32) = G_LOAD %1(p0) :: (load 4 from @val_with_local_linkage)
+    $v0 = COPY %0(s32)
+    RetRA implicit $v0
+
+...
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/irtranslator/global_address_pic.ll b/llvm/test/CodeGen/Mips/GlobalISel/irtranslator/global_address_pic.ll
new file mode 100644 (file)
index 0000000..1987337
--- /dev/null
@@ -0,0 +1,62 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -relocation-model=pic -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32_PIC
+
+declare i32 @f(i32 %a, i32 %b);
+
+define internal i32 @f_with_local_linkage(i32 %x, i32 %y) {
+  ; MIPS32_PIC-LABEL: name: f_with_local_linkage
+  ; MIPS32_PIC: bb.1.entry:
+  ; MIPS32_PIC:   liveins: $a0, $a1
+  ; MIPS32_PIC:   [[COPY:%[0-9]+]]:_(s32) = COPY $a0
+  ; MIPS32_PIC:   [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
+  ; MIPS32_PIC:   [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY1]], [[COPY]]
+  ; MIPS32_PIC:   $v0 = COPY [[ADD]](s32)
+  ; MIPS32_PIC:   RetRA implicit $v0
+entry:
+  %add = add i32 %y, %x
+  ret i32 %add
+}
+
+define i32 @call_global(i32 %a, i32 %b) {
+  ; MIPS32_PIC-LABEL: name: call_global
+  ; MIPS32_PIC: bb.1.entry:
+  ; MIPS32_PIC:   liveins: $a0, $a1, $t9, $v0
+  ; MIPS32_PIC:   [[ADDu:%[0-9]+]]:gpr32 = ADDu $v0, $t9
+  ; MIPS32_PIC:   [[COPY:%[0-9]+]]:_(s32) = COPY $a0
+  ; MIPS32_PIC:   [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
+  ; MIPS32_PIC:   ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+  ; MIPS32_PIC:   [[GV:%[0-9]+]]:gpr32(p0) = G_GLOBAL_VALUE target-flags(mips-got-call) @f
+  ; MIPS32_PIC:   $a0 = COPY [[COPY]](s32)
+  ; MIPS32_PIC:   $a1 = COPY [[COPY1]](s32)
+  ; MIPS32_PIC:   $gp = COPY [[ADDu]]
+  ; MIPS32_PIC:   JALRPseudo [[GV]](p0), csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $gp, implicit-def $v0
+  ; MIPS32_PIC:   [[COPY2:%[0-9]+]]:_(s32) = COPY $v0
+  ; MIPS32_PIC:   ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+  ; MIPS32_PIC:   $v0 = COPY [[COPY2]](s32)
+  ; MIPS32_PIC:   RetRA implicit $v0
+entry:
+  %call = call i32 @f(i32 %a, i32 %b)
+  ret i32 %call
+}
+
+define i32 @call_global_with_local_linkage(i32 %a, i32 %b) {
+  ; MIPS32_PIC-LABEL: name: call_global_with_local_linkage
+  ; MIPS32_PIC: bb.1.entry:
+  ; MIPS32_PIC:   liveins: $a0, $a1, $t9, $v0
+  ; MIPS32_PIC:   [[ADDu:%[0-9]+]]:gpr32 = ADDu $v0, $t9
+  ; MIPS32_PIC:   [[COPY:%[0-9]+]]:_(s32) = COPY $a0
+  ; MIPS32_PIC:   [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
+  ; MIPS32_PIC:   ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+  ; MIPS32_PIC:   [[GV:%[0-9]+]]:gpr32(p0) = G_GLOBAL_VALUE @f_with_local_linkage
+  ; MIPS32_PIC:   $a0 = COPY [[COPY]](s32)
+  ; MIPS32_PIC:   $a1 = COPY [[COPY1]](s32)
+  ; MIPS32_PIC:   $gp = COPY [[ADDu]]
+  ; MIPS32_PIC:   JALRPseudo [[GV]](p0), csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $gp, implicit-def $v0
+  ; MIPS32_PIC:   [[COPY2:%[0-9]+]]:_(s32) = COPY $v0
+  ; MIPS32_PIC:   ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+  ; MIPS32_PIC:   $v0 = COPY [[COPY2]](s32)
+  ; MIPS32_PIC:   RetRA implicit $v0
+entry:
+  %call = call i32 @f_with_local_linkage(i32 %a, i32 %b)
+  ret i32 %call
+}
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/global_address_pic.ll b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/global_address_pic.ll
new file mode 100644 (file)
index 0000000..e293a56
--- /dev/null
@@ -0,0 +1,97 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc  -O0 -mtriple=mipsel-linux-gnu -global-isel -relocation-model=pic -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32_PIC
+
+declare i32 @f(i32 %a, i32 %b);
+
+define internal i32 @f_with_local_linkage(i32 %x, i32 %y) {
+; MIPS32_PIC-LABEL: f_with_local_linkage:
+; MIPS32_PIC:       # %bb.0: # %entry
+; MIPS32_PIC-NEXT:    addu $2, $5, $4
+; MIPS32_PIC-NEXT:    jr $ra
+; MIPS32_PIC-NEXT:    nop
+entry:
+  %add = add i32 %y, %x
+  ret i32 %add
+}
+
+define i32 @call_global(i32 %a, i32 %b) {
+; MIPS32_PIC-LABEL: call_global:
+; MIPS32_PIC:       # %bb.0: # %entry
+; MIPS32_PIC-NEXT:    lui $2, %hi(_gp_disp)
+; MIPS32_PIC-NEXT:    addiu $2, $2, %lo(_gp_disp)
+; MIPS32_PIC-NEXT:    addiu $sp, $sp, -24
+; MIPS32_PIC-NEXT:    .cfi_def_cfa_offset 24
+; MIPS32_PIC-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32_PIC-NEXT:    .cfi_offset 31, -4
+; MIPS32_PIC-NEXT:    addu $1, $2, $25
+; MIPS32_PIC-NEXT:    lw $25, %call16(f)($1)
+; MIPS32_PIC-NEXT:    move $gp, $1
+; MIPS32_PIC-NEXT:    jalr $25
+; MIPS32_PIC-NEXT:    nop
+; MIPS32_PIC-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32_PIC-NEXT:    addiu $sp, $sp, 24
+; MIPS32_PIC-NEXT:    jr $ra
+; MIPS32_PIC-NEXT:    nop
+entry:
+  %call = call i32 @f(i32 %a, i32 %b)
+  ret i32 %call
+}
+
+define i32 @call_global_with_local_linkage(i32 %a, i32 %b) {
+; MIPS32_PIC-LABEL: call_global_with_local_linkage:
+; MIPS32_PIC:       # %bb.0: # %entry
+; MIPS32_PIC-NEXT:    lui $2, %hi(_gp_disp)
+; MIPS32_PIC-NEXT:    addiu $2, $2, %lo(_gp_disp)
+; MIPS32_PIC-NEXT:    addiu $sp, $sp, -24
+; MIPS32_PIC-NEXT:    .cfi_def_cfa_offset 24
+; MIPS32_PIC-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32_PIC-NEXT:    .cfi_offset 31, -4
+; MIPS32_PIC-NEXT:    addu $1, $2, $25
+; MIPS32_PIC-NEXT:    lw $2, %got(f_with_local_linkage)($1)
+; MIPS32_PIC-NEXT:    addiu $25, $2, %lo(f_with_local_linkage)
+; MIPS32_PIC-NEXT:    move $gp, $1
+; MIPS32_PIC-NEXT:    jalr $25
+; MIPS32_PIC-NEXT:    nop
+; MIPS32_PIC-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32_PIC-NEXT:    addiu $sp, $sp, 24
+; MIPS32_PIC-NEXT:    jr $ra
+; MIPS32_PIC-NEXT:    nop
+entry:
+  %call = call i32 @f_with_local_linkage(i32 %a, i32 %b)
+  ret i32 %call
+}
+
+
+@val = global i32 0
+@val_with_local_linkage = internal global i32 1
+
+define i32 @ret_global_int() {
+; MIPS32_PIC-LABEL: ret_global_int:
+; MIPS32_PIC:       # %bb.0: # %entry
+; MIPS32_PIC-NEXT:    lui $2, %hi(_gp_disp)
+; MIPS32_PIC-NEXT:    addiu $2, $2, %lo(_gp_disp)
+; MIPS32_PIC-NEXT:    addu $1, $2, $25
+; MIPS32_PIC-NEXT:    lw $1, %got(val)($1)
+; MIPS32_PIC-NEXT:    lw $2, 0($1)
+; MIPS32_PIC-NEXT:    jr $ra
+; MIPS32_PIC-NEXT:    nop
+entry:
+  %0 = load i32, i32* @val
+  ret i32 %0
+}
+
+define i32 @ret_global_int_with_local_linkage() {
+; MIPS32_PIC-LABEL: ret_global_int_with_local_linkage:
+; MIPS32_PIC:       # %bb.0: # %entry
+; MIPS32_PIC-NEXT:    lui $2, %hi(_gp_disp)
+; MIPS32_PIC-NEXT:    addiu $2, $2, %lo(_gp_disp)
+; MIPS32_PIC-NEXT:    addu $1, $2, $25
+; MIPS32_PIC-NEXT:    lw $1, %got(val_with_local_linkage)($1)
+; MIPS32_PIC-NEXT:    addiu $1, $1, %lo(val_with_local_linkage)
+; MIPS32_PIC-NEXT:    lw $2, 0($1)
+; MIPS32_PIC-NEXT:    jr $ra
+; MIPS32_PIC-NEXT:    nop
+entry:
+  %0 = load i32, i32* @val_with_local_linkage
+  ret i32 %0
+}
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/regbankselect/global_address_pic.mir b/llvm/test/CodeGen/Mips/GlobalISel/regbankselect/global_address_pic.mir
new file mode 100644 (file)
index 0000000..163c693
--- /dev/null
@@ -0,0 +1,48 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -relocation-model=pic -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
+--- |
+
+  declare i32 @f(i32, i32)
+  define void @call_global() {entry: ret void}
+
+...
+---
+name:            call_global
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0, $a1, $t9, $v0
+
+    ; MIPS32-LABEL: name: call_global
+    ; MIPS32: liveins: $a0, $a1, $t9, $v0
+    ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu $v0, $t9
+    ; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0
+    ; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1
+    ; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+    ; MIPS32: [[GV:%[0-9]+]]:gpr32(p0) = G_GLOBAL_VALUE target-flags(mips-got-call) @f
+    ; MIPS32: $a0 = COPY [[COPY]](s32)
+    ; MIPS32: $a1 = COPY [[COPY1]](s32)
+    ; MIPS32: $gp = COPY [[ADDu]]
+    ; MIPS32: JALRPseudo [[GV]](p0), csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $gp, implicit-def $v0
+    ; MIPS32: [[COPY2:%[0-9]+]]:gprb(s32) = COPY $v0
+    ; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+    ; MIPS32: $v0 = COPY [[COPY2]](s32)
+    ; MIPS32: RetRA implicit $v0
+    %4:gpr32 = ADDu $v0, $t9
+    %0:_(s32) = COPY $a0
+    %1:_(s32) = COPY $a1
+    ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
+    %3:gpr32(p0) = G_GLOBAL_VALUE target-flags(mips-got-call) @f
+    $a0 = COPY %0(s32)
+    $a1 = COPY %1(s32)
+    $gp = COPY %4
+    JALRPseudo %3(p0), csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $gp, implicit-def $v0
+    %2:_(s32) = COPY $v0
+    ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
+    $v0 = COPY %2(s32)
+    RetRA implicit $v0
+
+...
+