[llvm-branch-commits] [llvm-branch] r327751 - Backporting r325653:

Simon Dardis via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Mar 16 15:14:38 PDT 2018


Author: sdardis
Date: Fri Mar 16 15:14:38 2018
New Revision: 327751

URL: http://llvm.org/viewvc/llvm-project?rev=327751&view=rev
Log:
Backporting r325653:
------------------------------------------------------------------------
r325653 | sdardis | 2018-02-21 00:06:53 +0000 (Wed, 21 Feb 2018) | 31 lines

[mips] Spectre variant two mitigation for MIPSR2

This patch provides mitigation for CVE-2017-5715, Spectre variant two,
which affects the P5600 and P6600. It implements the LLVM part of
-mindirect-jump=hazard. It is _not_ enabled by default for the P5600.

The migitation strategy suggested by MIPS for these processors is to use
hazard barrier instructions. 'jalr.hb' and 'jr.hb' are hazard
barrier variants of the 'jalr' and 'jr' instructions respectively.

These instructions impede the execution of instruction stream until
architecturally defined hazards (changes to the instruction stream,
privileged registers which may affect execution) are cleared. These
instructions in MIPS' designs are not speculated past.

These instructions are used with the attribute +use-indirect-jump-hazard
when branching indirectly and for indirect function calls.

These instructions are defined by the MIPS32R2 ISA, so this mitigation
method is not compatible with processors which implement an earlier
revision of the MIPS ISA.

Performance benchmarking of this option with -fpic and lld using
-z hazardplt shows a difference of overall 10%~ time increase
for the LLVM testsuite. Certain benchmarks such as methcall show a
substantially larger increase in time due to their nature.

Reviewers: atanasyan, zoran.jovanovic

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

------------------------------------------------------------------------

Added:
    llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/
    llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/calls.ll
    llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-call.mir
    llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-tailcall.mir
    llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll
    llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-branch.ll
    llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll
    llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-micromips.ll
    llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-mips32.ll
Modified:
    llvm/branches/release_50/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
    llvm/branches/release_50/lib/Target/Mips/MicroMips32r6InstrInfo.td
    llvm/branches/release_50/lib/Target/Mips/MicroMips64r6InstrInfo.td
    llvm/branches/release_50/lib/Target/Mips/MicroMipsInstrInfo.td
    llvm/branches/release_50/lib/Target/Mips/Mips.td
    llvm/branches/release_50/lib/Target/Mips/Mips32r6InstrInfo.td
    llvm/branches/release_50/lib/Target/Mips/Mips64InstrInfo.td
    llvm/branches/release_50/lib/Target/Mips/Mips64r6InstrInfo.td
    llvm/branches/release_50/lib/Target/Mips/MipsDSPInstrFormats.td
    llvm/branches/release_50/lib/Target/Mips/MipsInstrFormats.td
    llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.cpp
    llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.h
    llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.td
    llvm/branches/release_50/lib/Target/Mips/MipsLongBranch.cpp
    llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.cpp
    llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.h
    llvm/branches/release_50/test/CodeGen/Mips/tailcall/tailcall.ll

Modified: llvm/branches/release_50/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/AsmParser/MipsAsmParser.cpp?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/branches/release_50/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Fri Mar 16 15:14:38 2018
@@ -5133,6 +5133,7 @@ unsigned MipsAsmParser::checkTargetMatch
   // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
   // and registers Rd and Base for microMIPS lwp instruction
   case Mips::JALR_HB:
+  case Mips::JALR_HB64:
   case Mips::JALRC_HB_MMR6:
   case Mips::JALRC_MMR6:
     if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())

Modified: llvm/branches/release_50/lib/Target/Mips/MicroMips32r6InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MicroMips32r6InstrInfo.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MicroMips32r6InstrInfo.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/MicroMips32r6InstrInfo.td Fri Mar 16 15:14:38 2018
@@ -1878,4 +1878,16 @@ let AddedComplexity = 41 in {
   def : StoreRegImmPat<SDC1_D64_MMR6, f64>, FGR_64, ISA_MICROMIPS32R6;
 }
 
-def TAILCALL_MMR6 : TailCall<BC_MMR6, brtarget26_mm>, ISA_MICROMIPS32R6;
+def TAILCALL_MMR6 : TailCall<BC_MMR6, brtarget26_mm>, ISA_MICROMIPS64R6;
+
+def TAILCALLREG_MMR6 : TailCallReg<JRC16_MM, GPR32Opnd>, ISA_MICROMIPS32R6;
+
+def PseudoIndirectBranch_MMR6 : PseudoIndirectBranchBase<JRC16_MMR6,
+                                                         GPR32Opnd>,
+                                ISA_MICROMIPS32R6;
+
+def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)),
+              (TAILCALL_MMR6 tglobaladdr:$dst)>, ISA_MICROMIPS32R6;
+
+def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)),
+              (TAILCALL_MMR6 texternalsym:$dst)>, ISA_MICROMIPS32R6;

Modified: llvm/branches/release_50/lib/Target/Mips/MicroMips64r6InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MicroMips64r6InstrInfo.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MicroMips64r6InstrInfo.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/MicroMips64r6InstrInfo.td Fri Mar 16 15:14:38 2018
@@ -352,6 +352,8 @@ class LWUPC_MM64R6_DESC {
   bit IsPCRelativeLoad = 1;
 }
 
+class JRC16_64_MMR6_DESC : JRC16_MMR6_DESC_BASE<"jrc16", GPR64Opnd>;
+
 //===----------------------------------------------------------------------===//
 //
 // Instruction Definitions
@@ -465,6 +467,9 @@ let DecoderNamespace = "MicroMipsR6" in
   def LWUPC_MM64R6 : R6MMR6Rel, LWUPC_MM64R6_ENC, LWUPC_MM64R6_DESC,
                      ISA_MICROMIPS64R6;
 }
+let DecoderNamespace = "MicroMips64r6" in
+  def JRC16_64_MMR6 : R6MMR6Rel, JRC16_64_MMR6_DESC, JRC16_MMR6_ENC,
+                      ISA_MICROMIPS64R6;
 
 let AdditionalPredicates = [InMicroMips] in
 defm : MaterializeImms<i64, ZERO_64, DADDIU_MM64R6, LUi64, ORi64>;
@@ -505,6 +510,9 @@ def : MipsPat<(subc GPR64:$lhs, GPR64:$r
 
 def : MipsPat<(atomic_load_64 addr:$a), (LD_MM64R6 addr:$a)>, ISA_MICROMIPS64R6;
 
+def TAILCALLREG64_MMR6 : TailCallReg<JRC16_64_MMR6, GPR64Opnd>,
+                         ISA_MICROMIPS64R6;
+
 //===----------------------------------------------------------------------===//
 //
 // Instruction aliases

Modified: llvm/branches/release_50/lib/Target/Mips/MicroMipsInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MicroMipsInstrInfo.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MicroMipsInstrInfo.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/MicroMipsInstrInfo.td Fri Mar 16 15:14:38 2018
@@ -993,6 +993,12 @@ let DecoderNamespace = "MicroMips", Pred
 
 def TAILCALL_MM : TailCall<J_MM, jmptarget_mm>, ISA_MIPS1_NOT_32R6_64R6;
 
+def TAILCALLREG_MM  : TailCallReg<JRC16_MM, GPR32Opnd>,
+                      ISA_MICROMIPS32_NOT_MIPS32R6;
+
+def PseudoIndirectBranch_MM : PseudoIndirectBranchBase<JR_MM, GPR32Opnd>,
+                              ISA_MICROMIPS32_NOT_MIPS32R6;
+
 let DecoderNamespace = "MicroMips" in {
   def RDHWR_MM : MMRel, R6MMR6Rel, ReadHardware<GPR32Opnd, HWRegsOpnd>,
                  RDHWR_FM_MM, ISA_MICROMIPS32_NOT_MIPS32R6;

Modified: llvm/branches/release_50/lib/Target/Mips/Mips.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/Mips.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/Mips.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/Mips.td Fri Mar 16 15:14:38 2018
@@ -193,6 +193,10 @@ def FeatureMT : SubtargetFeature<"mt", "
 def FeatureLongCalls : SubtargetFeature<"long-calls", "UseLongCalls", "true",
                                         "Disable use of the jal instruction">;
 
+def FeatureUseIndirectJumpsHazard : SubtargetFeature<"use-indirect-jump-hazard",
+                                                    "UseIndirectJumpsHazard",
+                                                    "true", "Use indirect jump"
+                        " guards to prevent certain speculation based attacks">;
 //===----------------------------------------------------------------------===//
 // Mips processors supported.
 //===----------------------------------------------------------------------===//

Modified: llvm/branches/release_50/lib/Target/Mips/Mips32r6InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/Mips32r6InstrInfo.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/Mips32r6InstrInfo.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/Mips32r6InstrInfo.td Fri Mar 16 15:14:38 2018
@@ -1008,3 +1008,42 @@ def : MipsPat<(select i32:$cond, immz, i
               (SELEQZ i32:$f, i32:$cond)>,
               ISA_MIPS32R6;
 }
+
+// Pseudo instructions
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1,
+    hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in {
+  class TailCallRegR6<Instruction JumpInst, Register RT, RegisterOperand RO> :
+    PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>,
+    PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)>;
+}
+
+class PseudoIndirectBranchBaseR6<Instruction JumpInst, Register RT,
+                                 RegisterOperand RO> :
+    MipsPseudo<(outs), (ins RO:$rs), [(brind RO:$rs)],
+               II_IndirectBranchPseudo>,
+    PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)> {
+  let isTerminator=1;
+  let isBarrier=1;
+  let hasDelaySlot = 1;
+  let isBranch = 1;
+  let isIndirectBranch = 1;
+  bit isCTI = 1;
+}
+
+
+let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
+                            NoIndirectJumpGuards] in {
+  def TAILCALLR6REG : TailCallRegR6<JALR, ZERO, GPR32Opnd>, ISA_MIPS32R6;
+  def PseudoIndirectBranchR6 : PseudoIndirectBranchBaseR6<JALR, ZERO,
+                                                          GPR32Opnd>,
+                               ISA_MIPS32R6;
+}
+
+let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
+                            UseIndirectJumpsHazard] in {
+  def TAILCALLHBR6REG : TailCallReg<JR_HB_R6, GPR32Opnd>, ISA_MIPS32R6;
+  def PseudoIndrectHazardBranchR6 : PseudoIndirectBranchBase<JR_HB_R6,
+                                                             GPR32Opnd>,
+                                    ISA_MIPS32R6;
+}
+

Modified: llvm/branches/release_50/lib/Target/Mips/Mips64InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/Mips64InstrInfo.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/Mips64InstrInfo.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/Mips64InstrInfo.td Fri Mar 16 15:14:38 2018
@@ -236,13 +236,32 @@ let isCodeGenOnly = 1 in {
   def BGTZ64 : CBranchZero<"bgtz", brtarget, setgt, GPR64Opnd>, BGEZ_FM<7, 0>;
   def BLEZ64 : CBranchZero<"blez", brtarget, setle, GPR64Opnd>, BGEZ_FM<6, 0>;
   def BLTZ64 : CBranchZero<"bltz", brtarget, setlt, GPR64Opnd>, BGEZ_FM<1, 0>;
-  def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>;
+  let AdditionalPredicates = [NoIndirectJumpGuards] in
+    def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>;
 }
+let AdditionalPredicates = [NotInMicroMips],
+    DecoderNamespace = "Mips64" in {
+  def JR_HB64 : JR_HB_DESC<GPR64Opnd>, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6;
+  def JALR_HB64 : JALR_HB_DESC<GPR64Opnd>, JALR_HB_ENC, ISA_MIPS32R2;
+}
+def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>;
 
-def TAILCALLREG64 : TailCallReg<GPR64Opnd>;
+let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
+                            NoIndirectJumpGuards] in {
+  def TAILCALLREG64 : TailCallReg<JR64, GPR64Opnd>, ISA_MIPS3_NOT_32R6_64R6,
+                      PTR_64;
+  def PseudoIndirectBranch64 : PseudoIndirectBranchBase<JR64, GPR64Opnd>,
+                               ISA_MIPS3_NOT_32R6_64R6;
+}
 
-def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>;
-def PseudoIndirectBranch64 : PseudoIndirectBranchBase<GPR64Opnd>;
+let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
+                            UseIndirectJumpsHazard] in {
+  def TAILCALLREGHB64 : TailCallReg<JR_HB64, GPR64Opnd>,
+                        ISA_MIPS32R2_NOT_32R6_64R6, PTR_64;
+  def PseudoIndirectHazardBranch64 : PseudoIndirectBranchBase<JR_HB64,
+                                                              GPR64Opnd>,
+                                     ISA_MIPS32R2_NOT_32R6_64R6;
+}
 
 /// Multiply and Divide Instructions.
 let AdditionalPredicates = [NotInMicroMips] in {
@@ -515,6 +534,10 @@ def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GP
             ISA_MIPS3;
 }
 
+
+let AdditionalPredicates = [UseIndirectJumpsHazard] in
+  def JALRHB64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR_HB64, RA_64>;
+
 //===----------------------------------------------------------------------===//
 //  Arbitrary patterns that map to one or more instructions
 //===----------------------------------------------------------------------===//
@@ -803,6 +826,8 @@ let AdditionalPredicates = [NotInMicroMi
                       (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rd, GPR32Opnd:$rt), 0>,
                       ISA_MIPS3;
 
+  def : MipsInstAlias<"jalr.hb $rs", (JALR_HB64 RA_64, GPR64Opnd:$rs), 1>,
+        ISA_MIPS64;
 // Two operand (implicit 0 selector) versions:
   def : MipsInstAlias<"dmtc0 $rt, $rd",
                       (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>;

Modified: llvm/branches/release_50/lib/Target/Mips/Mips64r6InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/Mips64r6InstrInfo.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/Mips64r6InstrInfo.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/Mips64r6InstrInfo.td Fri Mar 16 15:14:38 2018
@@ -104,6 +104,16 @@ class JIC64_DESC : JMP_IDX_COMPACT_DESC_
 
 class LL64_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9, II_LL>;
 class SC64_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd, II_SC>;
+
+class JR_HB64_R6_DESC : JR_HB_DESC_BASE<"jr.hb", GPR64Opnd> {
+  bit isBranch = 1;
+  bit isIndirectBranch = 1;
+  bit hasDelaySlot = 1;
+  bit isTerminator=1;
+  bit isBarrier=1;
+  bit isCTI = 1;
+  InstrItinClass Itinerary = II_JR_HB;
+}
 //===----------------------------------------------------------------------===//
 //
 // Instruction Definitions
@@ -136,6 +146,7 @@ def SCD_R6 : SCD_R6_ENC, SCD_R6_DESC, IS
 let DecoderNamespace = "Mips32r6_64r6_GP64" in {
   def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64;
   def SELNEZ64 : SELNEZ_ENC, SELNEZ64_DESC, ISA_MIPS32R6, GPR_64;
+  def JR_HB64_R6 : JR_HB_R6_ENC, JR_HB64_R6_DESC, ISA_MIPS32R6;
 }
 let AdditionalPredicates = [NotInMicroMips],
     DecoderNamespace = "Mips32r6_64r6_PTR64" in {
@@ -277,3 +288,22 @@ def : MipsPat<(select (i32 (setne i32:$c
 def : MipsPat<(select (i32 (seteq i32:$cond, immz)), immz, i64:$f),
               (SELNEZ64 i64:$f, (SLL64_32 i32:$cond))>,
               ISA_MIPS64R6;
+
+// Pseudo instructions
+
+let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
+                            NoIndirectJumpGuards] in {
+  def TAILCALL64R6REG : TailCallRegR6<JALR64, ZERO_64, GPR64Opnd>, ISA_MIPS64R6;
+  def PseudoIndirectBranch64R6 : PseudoIndirectBranchBaseR6<JALR64, ZERO_64,
+                                                            GPR64Opnd>,
+                                 ISA_MIPS64R6;
+}
+
+let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
+                            UseIndirectJumpsHazard] in {
+  def TAILCALLHB64R6REG : TailCallReg<JR_HB64_R6, GPR64Opnd>,
+                          ISA_MIPS64R6;
+  def PseudoIndrectHazardBranch64R6 : PseudoIndirectBranchBase<JR_HB64_R6,
+                                                                 GPR64Opnd>,
+                                      ISA_MIPS64R6;
+}

Modified: llvm/branches/release_50/lib/Target/Mips/MipsDSPInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MipsDSPInstrFormats.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MipsDSPInstrFormats.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/MipsDSPInstrFormats.td Fri Mar 16 15:14:38 2018
@@ -53,7 +53,7 @@ class DSPInst<string opstr = "">
 
 class PseudoDSP<dag outs, dag ins, list<dag> pattern,
                 InstrItinClass itin = IIPseudo>
-    : MipsPseudo<outs, ins, pattern, itin>, PredicateControl {
+    : MipsPseudo<outs, ins, pattern, itin> {
   let InsnPredicates = [HasDSP];
 }
 

Modified: llvm/branches/release_50/lib/Target/Mips/MipsInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MipsInstrFormats.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MipsInstrFormats.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/MipsInstrFormats.td Fri Mar 16 15:14:38 2018
@@ -128,7 +128,7 @@ class InstSE<dag outs, dag ins, string a
 // Mips Pseudo Instructions Format
 class MipsPseudo<dag outs, dag ins, list<dag> pattern,
                  InstrItinClass itin = IIPseudo> :
-  MipsInst<outs, ins, "", pattern, itin, Pseudo> {
+  MipsInst<outs, ins, "", pattern, itin, Pseudo>, PredicateControl {
   let isCodeGenOnly = 1;
   let isPseudo = 1;
 }
@@ -136,7 +136,7 @@ class MipsPseudo<dag outs, dag ins, list
 // Mips32/64 Pseudo Instruction Format
 class PseudoSE<dag outs, dag ins, list<dag> pattern,
                InstrItinClass itin = IIPseudo> :
-  MipsPseudo<outs, ins, pattern, itin>, PredicateControl {
+  MipsPseudo<outs, ins, pattern, itin> {
   let EncodingPredicates = [HasStdEnc];
 }
 

Modified: llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.cpp?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.cpp (original)
+++ llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.cpp Fri Mar 16 15:14:38 2018
@@ -286,7 +286,7 @@ unsigned MipsInstrInfo::getEquivalentCom
     case Mips::JR:
     case Mips::PseudoReturn:
     case Mips::PseudoIndirectBranch:
-    case Mips::TAILCALLREG:
+    case Mips::PseudoIndirectBranch_MM:
       canUseShortMicroMipsCTI = true;
       break;
     }
@@ -365,18 +365,19 @@ unsigned MipsInstrInfo::getEquivalentCom
     // For MIPSR6, the instruction 'jic' can be used for these cases. Some
     // tools will accept 'jrc reg' as an alias for 'jic 0, $reg'.
     case Mips::JR:
+    case Mips::PseudoIndirectBranchR6:
+    case Mips::PseudoIndirectBranch_MM:
     case Mips::PseudoReturn:
-    case Mips::PseudoIndirectBranch:
-    case Mips::TAILCALLREG:
+    case Mips::TAILCALLR6REG:
       if (canUseShortMicroMipsCTI)
         return Mips::JRC16_MM;
       return Mips::JIC;
     case Mips::JALRPseudo:
       return Mips::JIALC;
     case Mips::JR64:
+    case Mips::PseudoIndirectBranch64R6:
     case Mips::PseudoReturn64:
-    case Mips::PseudoIndirectBranch64:
-    case Mips::TAILCALLREG64:
+    case Mips::TAILCALL64R6REG:
       return Mips::JIC64;
     case Mips::JALR64Pseudo:
       return Mips::JIALC64;
@@ -526,3 +527,26 @@ bool MipsInstrInfo::findCommutedOpIndice
   }
   return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2);
 }
+
+//  Perform target specific instruction verification.
+bool MipsInstrInfo::verifyInstruction(const MachineInstr &MI,
+                                      StringRef &ErrInfo) const {
+  switch (MI.getOpcode()) {
+    case Mips::TAILCALLREG:
+    case Mips::PseudoIndirectBranch:
+    case Mips::JR:
+    case Mips::JR64:
+    case Mips::JALR:
+    case Mips::JALR64:
+    case Mips::JALRPseudo:
+      if (!Subtarget.useIndirectJumpsHazard())
+        return true;
+
+      ErrInfo = "invalid instruction when using jump guards!";
+      return false;
+    default:
+      return true;
+  }
+
+  return true;
+}

Modified: llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.h?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.h (original)
+++ llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.h Fri Mar 16 15:14:38 2018
@@ -138,6 +138,10 @@ public:
   bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,
                              unsigned &SrcOpIdx2) const override;
 
+  /// Perform target specific instruction verification.
+  bool verifyInstruction(const MachineInstr &MI,
+                         StringRef &ErrInfo) const override;
+
 protected:
   bool isZeroImm(const MachineOperand &op) const;
 

Modified: llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.td?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.td (original)
+++ llvm/branches/release_50/lib/Target/Mips/MipsInstrInfo.td Fri Mar 16 15:14:38 2018
@@ -212,6 +212,8 @@ def HasMicroMips64r6 : Predicate<"Subtar
                        AssemblerPredicate<"FeatureMicroMips,FeatureMips64r6">;
 def InMips16Mode :    Predicate<"Subtarget->inMips16Mode()">,
                       AssemblerPredicate<"FeatureMips16">;
+def NotInMips16Mode : Predicate<"!Subtarget->inMips16Mode()">,
+                      AssemblerPredicate<"!FeatureMips16">;
 def HasCnMips    :    Predicate<"Subtarget->hasCnMips()">,
                       AssemblerPredicate<"FeatureCnMips">;
 def NotCnMips    :    Predicate<"!Subtarget->hasCnMips()">,
@@ -242,7 +244,10 @@ def HasMadd4 : Predicate<"!Subtarget->di
                AssemblerPredicate<"!FeatureMadd4">;
 def HasMT  : Predicate<"Subtarget->hasMT()">,
              AssemblerPredicate<"FeatureMT">;
-
+def UseIndirectJumpsHazard : Predicate<"Subtarget->useIndirectJumpsHazard()">,
+                            AssemblerPredicate<"FeatureUseIndirectJumpsHazard">;
+def NoIndirectJumpGuards : Predicate<"!Subtarget->useIndirectJumpsHazard()">,
+                           AssemblerPredicate<"!FeatureUseIndirectJumpsHazard">;
 //===----------------------------------------------------------------------===//
 // Mips GPR size adjectives.
 // They are mutually exclusive.
@@ -1480,8 +1485,9 @@ let isCall = 1, isTerminator = 1, isRetu
     PseudoSE<(outs), (ins calltarget:$target), [], II_J>,
     PseudoInstExpansion<(JumpInst Opnd:$target)>;
 
-  class TailCallReg<RegisterOperand RO> :
-    MipsPseudo<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>;
+  class TailCallReg<Instruction JumpInst, RegisterOperand RO> :
+    PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>,
+    PseudoInstExpansion<(JumpInst RO:$rs)>;
 }
 
 class BAL_BR_Pseudo<Instruction RealInst> :
@@ -2005,7 +2011,7 @@ def BLTZL   : MMRel, CBranchZero<"bltzl"
 def B       : UncondBranch<BEQ>;
 
 def JAL  : MMRel, JumpLink<"jal", calltarget>, FJ<3>;
-let AdditionalPredicates = [NotInMicroMips] in {
+let AdditionalPredicates = [NotInMicroMips, NoIndirectJumpGuards] in {
   def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM;
   def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>;
 }
@@ -2025,14 +2031,16 @@ def BAL_BR : BAL_BR_Pseudo<BGEZAL>;
 let Predicates = [NotInMicroMips] in { 
   def TAILCALL : TailCall<J, jmptarget>;
 }
-
-def TAILCALLREG : TailCallReg<GPR32Opnd>;
+let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
+                            NoIndirectJumpGuards] in
+  def TAILCALLREG : TailCallReg<JR, GPR32Opnd>, ISA_MIPS1_NOT_32R6_64R6;
 
 // Indirect branches are matched as PseudoIndirectBranch/PseudoIndirectBranch64
 // then are expanded to JR, JR64, JALR, or JALR64 depending on the ISA.
-class PseudoIndirectBranchBase<RegisterOperand RO> :
+class PseudoIndirectBranchBase<Instruction JumpInst, RegisterOperand RO> :
     MipsPseudo<(outs), (ins RO:$rs), [(brind RO:$rs)],
-               II_IndirectBranchPseudo> {
+               II_IndirectBranchPseudo>,
+    PseudoInstExpansion<(JumpInst RO:$rs)> {
   let isTerminator=1;
   let isBarrier=1;
   let hasDelaySlot = 1;
@@ -2041,7 +2049,10 @@ class PseudoIndirectBranchBase<RegisterO
   bit isCTI = 1;
 }
 
-def PseudoIndirectBranch : PseudoIndirectBranchBase<GPR32Opnd>;
+let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
+                            NoIndirectJumpGuards] in
+  def PseudoIndirectBranch : PseudoIndirectBranchBase<JR, GPR32Opnd>,
+                             ISA_MIPS1_NOT_32R6_64R6;
 
 // Return instructions are matched as a RetRA instruction, then are expanded
 // into PseudoReturn/PseudoReturn64 after register allocation. Finally,
@@ -2213,8 +2224,8 @@ class JALR_HB_DESC_BASE<string instr_asm
   list<dag> Pattern = [];
 }
 
-class JR_HB_DESC : InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>,
-                   JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> {
+class JR_HB_DESC<RegisterOperand RO> :
+  InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>, JR_HB_DESC_BASE<"jr.hb", RO> {
   let isBranch=1;
   let isIndirectBranch=1;
   let hasDelaySlot=1;
@@ -2223,8 +2234,9 @@ class JR_HB_DESC : InstSE<(outs), (ins),
   bit isCTI = 1;
 }
 
-class JALR_HB_DESC : InstSE<(outs), (ins), "", [], II_JALR_HB, FrmJ>,
-                     JALR_HB_DESC_BASE<"jalr.hb", GPR32Opnd> {
+class JALR_HB_DESC<RegisterOperand RO> :
+  InstSE<(outs), (ins), "", [], II_JALR_HB, FrmJ>, JALR_HB_DESC_BASE<"jalr.hb",
+                                                                     RO> {
   let isIndirectBranch=1;
   let hasDelaySlot=1;
   bit isCTI = 1;
@@ -2233,8 +2245,19 @@ class JALR_HB_DESC : InstSE<(outs), (ins
 class JR_HB_ENC : JR_HB_FM<8>;
 class JALR_HB_ENC : JALR_HB_FM<9>;
 
-def JR_HB : JR_HB_DESC, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6;
-def JALR_HB : JALR_HB_DESC, JALR_HB_ENC, ISA_MIPS32;
+def JR_HB : JR_HB_DESC<GPR32Opnd>, JR_HB_ENC, ISA_MIPS32R2_NOT_32R6_64R6;
+def JALR_HB : JALR_HB_DESC<GPR32Opnd>, JALR_HB_ENC, ISA_MIPS32;
+
+let AdditionalPredicates = [NotInMicroMips, UseIndirectJumpsHazard] in
+  def JALRHBPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR_HB, RA>;
+
+
+let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
+                            UseIndirectJumpsHazard] in {
+  def TAILCALLREGHB : TailCallReg<JR_HB, GPR32Opnd>, ISA_MIPS32_NOT_32R6_64R6;
+  def PseudoIndirectHazardBranch : PseudoIndirectBranchBase<JR_HB, GPR32Opnd>,
+                                   ISA_MIPS32R2_NOT_32R6_64R6;
+}
 
 class TLB<string asmstr, InstrItinClass itin = NoItinerary> :
   InstSE<(outs), (ins), asmstr, [], itin, FrmOther, asmstr>;
@@ -2368,7 +2391,8 @@ def : MipsInstAlias<"j $rs", (JR GPR32Op
 let Predicates = [NotInMicroMips] in {
 def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>;
 }
-def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, ISA_MIPS32;
+def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>,
+      ISA_MIPS32;
 def : MipsInstAlias<"neg $rt, $rs",
                     (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>;
 def : MipsInstAlias<"neg $rt",

Modified: llvm/branches/release_50/lib/Target/Mips/MipsLongBranch.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MipsLongBranch.cpp?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MipsLongBranch.cpp (original)
+++ llvm/branches/release_50/lib/Target/Mips/MipsLongBranch.cpp Fri Mar 16 15:14:38 2018
@@ -341,11 +341,16 @@ void MipsLongBranch::expandToLongBranch(
         BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP)
           .addReg(Mips::SP).addImm(8);
 
-      if (Subtarget.hasMips32r6())
+      if (Subtarget.hasMips32r6() && !Subtarget.useIndirectJumpsHazard())
         BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR))
           .addReg(Mips::ZERO).addReg(Mips::AT);
-      else
-        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR)).addReg(Mips::AT);
+      else {
+        unsigned JROp =
+            Subtarget.useIndirectJumpsHazard()
+                ? (Subtarget.hasMips32r6() ? Mips::JR_HB_R6 : Mips::JR_HB)
+                : Mips::JR;
+        BuildMI(*BalTgtMBB, Pos, DL, TII->get(JROp)).addReg(Mips::AT);
+      }
 
       if (Subtarget.isTargetNaCl()) {
         BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::NOP));
@@ -414,14 +419,21 @@ void MipsLongBranch::expandToLongBranch(
       BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64)
         .addReg(Mips::SP_64).addImm(0);
 
-      if (Subtarget.hasMips64r6())
+      if (Subtarget.hasMips64r6() && !Subtarget.useIndirectJumpsHazard())
         BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR64))
-          .addReg(Mips::ZERO_64).addReg(Mips::AT_64);
-      else
-        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64);
+            .addReg(Mips::ZERO_64)
+            .addReg(Mips::AT_64);
+      else {
+        unsigned JROp =
+            Subtarget.useIndirectJumpsHazard()
+                ? (Subtarget.hasMips32r6() ? Mips::JR_HB64_R6 : Mips::JR_HB64)
+                : Mips::JR64;
+        BuildMI(*BalTgtMBB, Pos, DL, TII->get(JROp)).addReg(Mips::AT_64);
+      }
 
       BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64)
-        .addReg(Mips::SP_64).addImm(16);
+          .addReg(Mips::SP_64)
+          .addImm(16);
       BalTgtMBB->rbegin()->bundleWithPred();
     }
 

Modified: llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.cpp?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.cpp (original)
+++ llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.cpp Fri Mar 16 15:14:38 2018
@@ -70,8 +70,8 @@ MipsSubtarget::MipsSubtarget(const Tripl
       InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false),
       HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 | Mips_Os16),
       Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false),
-      HasEVA(false), DisableMadd4(false), HasMT(false), TM(TM),
-      TargetTriple(TT), TSInfo(),
+      HasEVA(false), DisableMadd4(false), HasMT(false),
+      UseIndirectJumpsHazard(false), TM(TM), TargetTriple(TT), TSInfo(),
       InstrInfo(
           MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))),
       FrameLowering(MipsFrameLowering::create(*this)),
@@ -103,6 +103,15 @@ MipsSubtarget::MipsSubtarget(const Tripl
   if (IsFPXX && (isABI_N32() || isABI_N64()))
     report_fatal_error("FPXX is not permitted for the N32/N64 ABI's.", false);
 
+  if (UseIndirectJumpsHazard) {
+    if (InMicroMipsMode)
+      report_fatal_error(
+          "cannot combine indirect jumps with hazard barriers and microMIPS");
+    if (!hasMips32r2())
+      report_fatal_error(
+          "indirect jumps with hazard barriers requires MIPS32R2 or later");
+  }
+
   if (hasMips32r6()) {
     StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
 

Modified: llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.h?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.h (original)
+++ llvm/branches/release_50/lib/Target/Mips/MipsSubtarget.h Fri Mar 16 15:14:38 2018
@@ -152,6 +152,10 @@ class MipsSubtarget : public MipsGenSubt
   // HasMT -- support MT ASE.
   bool HasMT;
 
+  // Use hazard variants of the jump register instructions for indirect
+  // function calls and jump tables.
+  bool UseIndirectJumpsHazard;
+
   // Disable use of the `jal` instruction.
   bool UseLongCalls = false;
 
@@ -266,6 +270,9 @@ public:
   bool disableMadd4() const { return DisableMadd4; }
   bool hasEVA() const { return HasEVA; }
   bool hasMT() const { return HasMT; }
+  bool useIndirectJumpsHazard() const {
+    return UseIndirectJumpsHazard && hasMips32r2();
+  }
   bool useSmallSection() const { return UseSmallSection; }
 
   bool hasStandardEncoding() const { return !inMips16Mode(); }

Added: llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/calls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/calls.ll?rev=327751&view=auto
==============================================================================
--- llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/calls.ll (added)
+++ llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/calls.ll Fri Mar 16 15:14:38 2018
@@ -0,0 +1,188 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc  < %s -mtriple=mips-mti-linux-gnu -relocation-model=static \
+; RUN:   -mips-tail-calls=1 -mcpu=mips32r2 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=MIPS32R2
+; RUN: llc  < %s -mtriple=mips-img-linux-gnu -relocation-model=static \
+; RUN:   -mips-tail-calls=1 -mcpu=mips32r6 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=MIPS32R6
+; RUN: llc  < %s -mtriple=mips64-mti-linux-gnu -relocation-model=static \
+; RUN:   -mips-tail-calls=1 -mcpu=mips64r2 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=MIPS64R2
+; RUN: llc  < %s -mtriple=mips64-img-linux-gnu -relocation-model=static \
+; RUN:   -mips-tail-calls=1 -mcpu=mips64r6 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=MIPS64R6
+
+; RUN: llc  < %s -mtriple=mips-mti-linux-gnu -relocation-model=pic \
+; RUN:   -mips-tail-calls=1 -mcpu=mips32r2 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=PIC-MIPS32R2
+; RUN: llc  < %s -mtriple=mips-img-linux-gnu -relocation-model=pic \
+; RUN:   -mips-tail-calls=1 -mcpu=mips32r6 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=PIC-MIPS32R6
+; RUN: llc  < %s -mtriple=mips64-mti-linux-gnu -relocation-model=pic \
+; RUN:   -mips-tail-calls=1 -mcpu=mips64r2 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=PIC-MIPS64R2
+; RUN: llc  < %s -mtriple=mips64-img-linux-gnu -relocation-model=pic \
+; RUN:   -mips-tail-calls=1 -mcpu=mips64r6 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=PIC-MIPS64R6
+
+define void @fooNonTail(void (i32)* nocapture %f1) nounwind {
+; MIPS32R2-LABEL: fooNonTail:
+; MIPS32R2:       # BB#0: # %entry
+; MIPS32R2-NEXT:    addiu $sp, $sp, -24
+; MIPS32R2-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32R2-NEXT:    move $1, $4
+; MIPS32R2-NEXT:    move $25, $1
+; MIPS32R2-NEXT:    jalr.hb $25
+; MIPS32R2-NEXT:    addiu $4, $zero, 13
+; MIPS32R2-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32R2-NEXT:    jr $ra
+; MIPS32R2-NEXT:    addiu $sp, $sp, 24
+;
+; MIPS32R6-LABEL: fooNonTail:
+; MIPS32R6:       # BB#0: # %entry
+; MIPS32R6-NEXT:    addiu $sp, $sp, -24
+; MIPS32R6-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32R6-NEXT:    move $1, $4
+; MIPS32R6-NEXT:    move $25, $1
+; MIPS32R6-NEXT:    jalr.hb $25
+; MIPS32R6-NEXT:    addiu $4, $zero, 13
+; MIPS32R6-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32R6-NEXT:    jr $ra
+; MIPS32R6-NEXT:    addiu $sp, $sp, 24
+;
+; MIPS64R2-LABEL: fooNonTail:
+; MIPS64R2:       # BB#0: # %entry
+; MIPS64R2-NEXT:    daddiu $sp, $sp, -16
+; MIPS64R2-NEXT:    sd $ra, 8($sp) # 8-byte Folded Spill
+; MIPS64R2-NEXT:    move $1, $4
+; MIPS64R2-NEXT:    move $25, $1
+; MIPS64R2-NEXT:    jalr.hb $25
+; MIPS64R2-NEXT:    daddiu $4, $zero, 13
+; MIPS64R2-NEXT:    ld $ra, 8($sp) # 8-byte Folded Reload
+; MIPS64R2-NEXT:    jr $ra
+; MIPS64R2-NEXT:    daddiu $sp, $sp, 16
+;
+; MIPS64R6-LABEL: fooNonTail:
+; MIPS64R6:       # BB#0: # %entry
+; MIPS64R6-NEXT:    daddiu $sp, $sp, -16
+; MIPS64R6-NEXT:    sd $ra, 8($sp) # 8-byte Folded Spill
+; MIPS64R6-NEXT:    move $1, $4
+; MIPS64R6-NEXT:    move $25, $1
+; MIPS64R6-NEXT:    jalr.hb $25
+; MIPS64R6-NEXT:    daddiu $4, $zero, 13
+; MIPS64R6-NEXT:    ld $ra, 8($sp) # 8-byte Folded Reload
+; MIPS64R6-NEXT:    jr $ra
+; MIPS64R6-NEXT:    daddiu $sp, $sp, 16
+;
+; PIC-MIPS32R2-LABEL: fooNonTail:
+; PIC-MIPS32R2:       # BB#0: # %entry
+; PIC-MIPS32R2-NEXT:    addiu $sp, $sp, -24
+; PIC-MIPS32R2-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; PIC-MIPS32R2-NEXT:    move $1, $4
+; PIC-MIPS32R2-NEXT:    move $25, $1
+; PIC-MIPS32R2-NEXT:    jalr.hb $25
+; PIC-MIPS32R2-NEXT:    addiu $4, $zero, 13
+; PIC-MIPS32R2-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; PIC-MIPS32R2-NEXT:    jr $ra
+; PIC-MIPS32R2-NEXT:    addiu $sp, $sp, 24
+;
+; PIC-MIPS32R6-LABEL: fooNonTail:
+; PIC-MIPS32R6:       # BB#0: # %entry
+; PIC-MIPS32R6-NEXT:    addiu $sp, $sp, -24
+; PIC-MIPS32R6-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; PIC-MIPS32R6-NEXT:    move $1, $4
+; PIC-MIPS32R6-NEXT:    move $25, $1
+; PIC-MIPS32R6-NEXT:    jalr.hb $25
+; PIC-MIPS32R6-NEXT:    addiu $4, $zero, 13
+; PIC-MIPS32R6-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; PIC-MIPS32R6-NEXT:    jr $ra
+; PIC-MIPS32R6-NEXT:    addiu $sp, $sp, 24
+;
+; PIC-MIPS64R2-LABEL: fooNonTail:
+; PIC-MIPS64R2:       # BB#0: # %entry
+; PIC-MIPS64R2-NEXT:    daddiu $sp, $sp, -16
+; PIC-MIPS64R2-NEXT:    sd $ra, 8($sp) # 8-byte Folded Spill
+; PIC-MIPS64R2-NEXT:    move $1, $4
+; PIC-MIPS64R2-NEXT:    move $25, $1
+; PIC-MIPS64R2-NEXT:    jalr.hb $25
+; PIC-MIPS64R2-NEXT:    daddiu $4, $zero, 13
+; PIC-MIPS64R2-NEXT:    ld $ra, 8($sp) # 8-byte Folded Reload
+; PIC-MIPS64R2-NEXT:    jr $ra
+; PIC-MIPS64R2-NEXT:    daddiu $sp, $sp, 16
+;
+; PIC-MIPS64R6-LABEL: fooNonTail:
+; PIC-MIPS64R6:       # BB#0: # %entry
+; PIC-MIPS64R6-NEXT:    daddiu $sp, $sp, -16
+; PIC-MIPS64R6-NEXT:    sd $ra, 8($sp) # 8-byte Folded Spill
+; PIC-MIPS64R6-NEXT:    move $1, $4
+; PIC-MIPS64R6-NEXT:    move $25, $1
+; PIC-MIPS64R6-NEXT:    jalr.hb $25
+; PIC-MIPS64R6-NEXT:    daddiu $4, $zero, 13
+; PIC-MIPS64R6-NEXT:    ld $ra, 8($sp) # 8-byte Folded Reload
+; PIC-MIPS64R6-NEXT:    jr $ra
+; PIC-MIPS64R6-NEXT:    daddiu $sp, $sp, 16
+entry:
+  call void %f1(i32 13) nounwind
+  ret void
+}
+
+define i32 @fooTail(i32 (i32)* nocapture %f1) nounwind {
+; MIPS32R2-LABEL: fooTail:
+; MIPS32R2:       # BB#0: # %entry
+; MIPS32R2-NEXT:    move $1, $4
+; MIPS32R2-NEXT:    move $25, $1
+; MIPS32R2-NEXT:    jr.hb $25
+; MIPS32R2-NEXT:    addiu $4, $zero, 14
+;
+; MIPS32R6-LABEL: fooTail:
+; MIPS32R6:       # BB#0: # %entry
+; MIPS32R6-NEXT:    move $1, $4
+; MIPS32R6-NEXT:    move $25, $1
+; MIPS32R6-NEXT:    jr.hb $25
+; MIPS32R6-NEXT:    addiu $4, $zero, 14
+;
+; MIPS64R2-LABEL: fooTail:
+; MIPS64R2:       # BB#0: # %entry
+; MIPS64R2-NEXT:    move $1, $4
+; MIPS64R2-NEXT:    move $25, $1
+; MIPS64R2-NEXT:    jr.hb $25
+; MIPS64R2-NEXT:    daddiu $4, $zero, 14
+;
+; MIPS64R6-LABEL: fooTail:
+; MIPS64R6:       # BB#0: # %entry
+; MIPS64R6-NEXT:    move $1, $4
+; MIPS64R6-NEXT:    move $25, $1
+; MIPS64R6-NEXT:    jr.hb $25
+; MIPS64R6-NEXT:    daddiu $4, $zero, 14
+;
+; PIC-MIPS32R2-LABEL: fooTail:
+; PIC-MIPS32R2:       # BB#0: # %entry
+; PIC-MIPS32R2-NEXT:    move $1, $4
+; PIC-MIPS32R2-NEXT:    move $25, $1
+; PIC-MIPS32R2-NEXT:    jr.hb $25
+; PIC-MIPS32R2-NEXT:    addiu $4, $zero, 14
+;
+; PIC-MIPS32R6-LABEL: fooTail:
+; PIC-MIPS32R6:       # BB#0: # %entry
+; PIC-MIPS32R6-NEXT:    move $1, $4
+; PIC-MIPS32R6-NEXT:    move $25, $1
+; PIC-MIPS32R6-NEXT:    jr.hb $25
+; PIC-MIPS32R6-NEXT:    addiu $4, $zero, 14
+;
+; PIC-MIPS64R2-LABEL: fooTail:
+; PIC-MIPS64R2:       # BB#0: # %entry
+; PIC-MIPS64R2-NEXT:    move $1, $4
+; PIC-MIPS64R2-NEXT:    move $25, $1
+; PIC-MIPS64R2-NEXT:    jr.hb $25
+; PIC-MIPS64R2-NEXT:    daddiu $4, $zero, 14
+;
+; PIC-MIPS64R6-LABEL: fooTail:
+; PIC-MIPS64R6:       # BB#0: # %entry
+; PIC-MIPS64R6-NEXT:    move $1, $4
+; PIC-MIPS64R6-NEXT:    move $25, $1
+; PIC-MIPS64R6-NEXT:    jr.hb $25
+; PIC-MIPS64R6-NEXT:    daddiu $4, $zero, 14
+entry:
+   %0 = tail call i32 %f1(i32 14) nounwind
+   ret i32 %0
+}

Added: llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-call.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-call.mir?rev=327751&view=auto
==============================================================================
--- llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-call.mir (added)
+++ llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-call.mir Fri Mar 16 15:14:38 2018
@@ -0,0 +1,58 @@
+# RUN: not llc -mtriple=mips-mti-linux-gnu -mcpu=mips32r2 %s \
+# RUN:         -start-after=expand-isel-pseudos -stop-after=expand-isel-pseudos \
+# RUN:         -verify-machineinstrs -mattr=+use-indirect-jump-hazard -o - 2>&1 \
+# RUN:   | FileCheck %s
+
+# Test that calls are checked when using indirect jumps guards (hazard variant).
+
+# CHECK: Bad machine code: invalid instruction when using jump guards!
+--- |
+  define i32 @fooTail(i32 (i32)* nocapture %f1) {
+  entry:
+    %0 = tail call i32 %f1(i32 14)
+    ret i32 %0
+  }
+...
+---
+name:            fooTail
+alignment:       2
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gpr32, preferred-register: '' }
+  - { id: 1, class: gpr32, preferred-register: '' }
+liveins:
+  - { reg: '%a0', virtual-reg: '%0' }
+frameInfo:
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    1
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:
+stack:
+constants:
+body:             |
+  bb.0.entry:
+    liveins: %a0
+
+    %0:gpr32 = COPY %a0
+    %1:gpr32 = ADDiu %zero, 14
+    %a0 = COPY %1
+    TAILCALLREG %0, csr_o32, implicit-def dead %at, implicit %a0
+
+...

Added: llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-tailcall.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-tailcall.mir?rev=327751&view=auto
==============================================================================
--- llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-tailcall.mir (added)
+++ llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-tailcall.mir Fri Mar 16 15:14:38 2018
@@ -0,0 +1,59 @@
+# RUN: not llc -mtriple=mips-mti-linux-gnu -mcpu=mips32r2 %s \
+# RUN:         -start-after=expand-isel-pseudos -stop-after=expand-isel-pseudos \
+# RUN:         -verify-machineinstrs -mattr=+use-indirect-jump-hazard -o - 2>&1 \
+# RUN:   | FileCheck %s
+
+# That that tail calls are checked when using indirect jump guards (hazard variant).
+
+# CHECK: Bad machine code: invalid instruction when using jump guards!
+--- |
+  define i32 @fooTail(i32 (i32)* nocapture %f1) {
+  entry:
+    %0 = tail call i32 %f1(i32 14)
+    ret i32 %0
+  }
+
+...
+---
+name:            fooTail
+alignment:       2
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gpr32, preferred-register: '' }
+  - { id: 1, class: gpr32, preferred-register: '' }
+liveins:
+  - { reg: '%a0', virtual-reg: '%0' }
+frameInfo:
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    1
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  maxCallFrameSize: 4294967295
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:
+stack:
+constants:
+body:             |
+  bb.0.entry:
+    liveins: %a0
+
+    %0:gpr32 = COPY %a0
+    %1:gpr32 = ADDiu %zero, 14
+    %a0 = COPY %1
+    TAILCALLREG %0, csr_o32, implicit-def dead %at, implicit %a0
+
+...

Added: llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll?rev=327751&view=auto
==============================================================================
--- llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll (added)
+++ llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll Fri Mar 16 15:14:38 2018
@@ -0,0 +1,657 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc  < %s -mtriple=mips-mti-linux-gnu -relocation-model=static \
+; RUN:   -mips-tail-calls=1 -mcpu=mips32r2 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=MIPS32R2
+; RUN: llc  < %s -mtriple=mips-img-linux-gnu -relocation-model=static \
+; RUN:   -mips-tail-calls=1 -mcpu=mips32r6 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=MIPS32R6
+; RUN: llc  < %s -mtriple=mips64-mti-linux-gnu -relocation-model=static \
+; RUN:   -mips-tail-calls=1 -mcpu=mips64r2 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=MIPS64R2
+; RUN: llc  < %s -mtriple=mips64-img-linux-gnu -relocation-model=static \
+; RUN:   -mips-tail-calls=1 -mcpu=mips64r6 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=MIPS64R6
+
+; RUN: llc  < %s -mtriple=mips-mti-linux-gnu -relocation-model=pic \
+; RUN:   -mips-tail-calls=1 -mcpu=mips32r2 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=PIC-MIPS32R2
+; RUN: llc  < %s -mtriple=mips-img-linux-gnu -relocation-model=pic \
+; RUN:   -mips-tail-calls=1 -mcpu=mips32r6 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=PIC-MIPS32R6
+; RUN: llc  < %s -mtriple=mips64-mti-linux-gnu -relocation-model=pic \
+; RUN:   -mips-tail-calls=1 -mcpu=mips64r2 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=PIC-MIPS64R2
+; RUN: llc  < %s -mtriple=mips64-img-linux-gnu -relocation-model=pic \
+; RUN:   -mips-tail-calls=1 -mcpu=mips64r6 -mattr=+use-indirect-jump-hazard \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=PIC-MIPS64R6
+
+ at .str = private unnamed_addr constant [2 x i8] c"A\00", align 1
+ at .str.1 = private unnamed_addr constant [2 x i8] c"B\00", align 1
+ at .str.2 = private unnamed_addr constant [2 x i8] c"C\00", align 1
+ at .str.3 = private unnamed_addr constant [2 x i8] c"D\00", align 1
+ at .str.4 = private unnamed_addr constant [2 x i8] c"E\00", align 1
+ at .str.5 = private unnamed_addr constant [2 x i8] c"F\00", align 1
+ at .str.6 = private unnamed_addr constant [2 x i8] c"G\00", align 1
+ at .str.7 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+
+define i8* @_Z3fooi(i32 signext %Letter) {
+; MIPS32R2-LABEL: _Z3fooi:
+; MIPS32R2:       # BB#0: # %entry
+; MIPS32R2-NEXT:    addiu $sp, $sp, -16
+; MIPS32R2-NEXT:  $cfi0:
+; MIPS32R2-NEXT:    .cfi_def_cfa_offset 16
+; MIPS32R2-NEXT:    sltiu $1, $4, 7
+; MIPS32R2-NEXT:    beqz $1, $BB0_3
+; MIPS32R2-NEXT:    sw $4, 4($sp)
+; MIPS32R2-NEXT:  $BB0_1: # %entry
+; MIPS32R2-NEXT:    sll $1, $4, 2
+; MIPS32R2-NEXT:    lui $2, %hi($JTI0_0)
+; MIPS32R2-NEXT:    addu $1, $1, $2
+; MIPS32R2-NEXT:    lw $1, %lo($JTI0_0)($1)
+; MIPS32R2-NEXT:    jr.hb $1
+; MIPS32R2-NEXT:    nop
+; MIPS32R2-NEXT:  $BB0_2: # %sw.bb
+; MIPS32R2-NEXT:    lui $1, %hi($.str)
+; MIPS32R2-NEXT:    addiu $1, $1, %lo($.str)
+; MIPS32R2-NEXT:    j $BB0_10
+; MIPS32R2-NEXT:    sw $1, 8($sp)
+; MIPS32R2-NEXT:  $BB0_3: # %sw.epilog
+; MIPS32R2-NEXT:    lui $1, %hi($.str.7)
+; MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.7)
+; MIPS32R2-NEXT:    j $BB0_10
+; MIPS32R2-NEXT:    sw $1, 8($sp)
+; MIPS32R2-NEXT:  $BB0_4: # %sw.bb1
+; MIPS32R2-NEXT:    lui $1, %hi($.str.1)
+; MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.1)
+; MIPS32R2-NEXT:    j $BB0_10
+; MIPS32R2-NEXT:    sw $1, 8($sp)
+; MIPS32R2-NEXT:  $BB0_5: # %sw.bb2
+; MIPS32R2-NEXT:    lui $1, %hi($.str.2)
+; MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.2)
+; MIPS32R2-NEXT:    j $BB0_10
+; MIPS32R2-NEXT:    sw $1, 8($sp)
+; MIPS32R2-NEXT:  $BB0_6: # %sw.bb3
+; MIPS32R2-NEXT:    lui $1, %hi($.str.3)
+; MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.3)
+; MIPS32R2-NEXT:    j $BB0_10
+; MIPS32R2-NEXT:    sw $1, 8($sp)
+; MIPS32R2-NEXT:  $BB0_7: # %sw.bb4
+; MIPS32R2-NEXT:    lui $1, %hi($.str.4)
+; MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.4)
+; MIPS32R2-NEXT:    j $BB0_10
+; MIPS32R2-NEXT:    sw $1, 8($sp)
+; MIPS32R2-NEXT:  $BB0_8: # %sw.bb5
+; MIPS32R2-NEXT:    lui $1, %hi($.str.5)
+; MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.5)
+; MIPS32R2-NEXT:    j $BB0_10
+; MIPS32R2-NEXT:    sw $1, 8($sp)
+; MIPS32R2-NEXT:  $BB0_9: # %sw.bb6
+; MIPS32R2-NEXT:    lui $1, %hi($.str.6)
+; MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.6)
+; MIPS32R2-NEXT:    sw $1, 8($sp)
+; MIPS32R2-NEXT:  $BB0_10: # %return
+; MIPS32R2-NEXT:    lw $2, 8($sp)
+; MIPS32R2-NEXT:    jr $ra
+; MIPS32R2-NEXT:    addiu $sp, $sp, 16
+;
+; MIPS32R6-LABEL: _Z3fooi:
+; MIPS32R6:       # BB#0: # %entry
+; MIPS32R6-NEXT:    addiu $sp, $sp, -16
+; MIPS32R6-NEXT:  $cfi0:
+; MIPS32R6-NEXT:    .cfi_def_cfa_offset 16
+; MIPS32R6-NEXT:    sltiu $1, $4, 7
+; MIPS32R6-NEXT:    beqz $1, $BB0_3
+; MIPS32R6-NEXT:    sw $4, 4($sp)
+; MIPS32R6-NEXT:  $BB0_1: # %entry
+; MIPS32R6-NEXT:    sll $1, $4, 2
+; MIPS32R6-NEXT:    lui $2, %hi($JTI0_0)
+; MIPS32R6-NEXT:    addu $1, $1, $2
+; MIPS32R6-NEXT:    lw $1, %lo($JTI0_0)($1)
+; MIPS32R6-NEXT:    jr.hb $1
+; MIPS32R6-NEXT:    nop
+; MIPS32R6-NEXT:  $BB0_2: # %sw.bb
+; MIPS32R6-NEXT:    lui $1, %hi($.str)
+; MIPS32R6-NEXT:    addiu $1, $1, %lo($.str)
+; MIPS32R6-NEXT:    j $BB0_10
+; MIPS32R6-NEXT:    sw $1, 8($sp)
+; MIPS32R6-NEXT:  $BB0_3: # %sw.epilog
+; MIPS32R6-NEXT:    lui $1, %hi($.str.7)
+; MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.7)
+; MIPS32R6-NEXT:    j $BB0_10
+; MIPS32R6-NEXT:    sw $1, 8($sp)
+; MIPS32R6-NEXT:  $BB0_4: # %sw.bb1
+; MIPS32R6-NEXT:    lui $1, %hi($.str.1)
+; MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.1)
+; MIPS32R6-NEXT:    j $BB0_10
+; MIPS32R6-NEXT:    sw $1, 8($sp)
+; MIPS32R6-NEXT:  $BB0_5: # %sw.bb2
+; MIPS32R6-NEXT:    lui $1, %hi($.str.2)
+; MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.2)
+; MIPS32R6-NEXT:    j $BB0_10
+; MIPS32R6-NEXT:    sw $1, 8($sp)
+; MIPS32R6-NEXT:  $BB0_6: # %sw.bb3
+; MIPS32R6-NEXT:    lui $1, %hi($.str.3)
+; MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.3)
+; MIPS32R6-NEXT:    j $BB0_10
+; MIPS32R6-NEXT:    sw $1, 8($sp)
+; MIPS32R6-NEXT:  $BB0_7: # %sw.bb4
+; MIPS32R6-NEXT:    lui $1, %hi($.str.4)
+; MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.4)
+; MIPS32R6-NEXT:    j $BB0_10
+; MIPS32R6-NEXT:    sw $1, 8($sp)
+; MIPS32R6-NEXT:  $BB0_8: # %sw.bb5
+; MIPS32R6-NEXT:    lui $1, %hi($.str.5)
+; MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.5)
+; MIPS32R6-NEXT:    j $BB0_10
+; MIPS32R6-NEXT:    sw $1, 8($sp)
+; MIPS32R6-NEXT:  $BB0_9: # %sw.bb6
+; MIPS32R6-NEXT:    lui $1, %hi($.str.6)
+; MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.6)
+; MIPS32R6-NEXT:    sw $1, 8($sp)
+; MIPS32R6-NEXT:  $BB0_10: # %return
+; MIPS32R6-NEXT:    lw $2, 8($sp)
+; MIPS32R6-NEXT:    jr $ra
+; MIPS32R6-NEXT:    addiu $sp, $sp, 16
+;
+; MIPS64R2-LABEL: _Z3fooi:
+; MIPS64R2:       # BB#0: # %entry
+; MIPS64R2-NEXT:    daddiu $sp, $sp, -16
+; MIPS64R2-NEXT:  .Lcfi0:
+; MIPS64R2-NEXT:    .cfi_def_cfa_offset 16
+; MIPS64R2-NEXT:    sw $4, 4($sp)
+; MIPS64R2-NEXT:    lwu $2, 4($sp)
+; MIPS64R2-NEXT:    sltiu $1, $2, 7
+; MIPS64R2-NEXT:    beqz $1, .LBB0_3
+; MIPS64R2-NEXT:    nop
+; MIPS64R2-NEXT:  .LBB0_1: # %entry
+; MIPS64R2-NEXT:    daddiu $1, $zero, 8
+; MIPS64R2-NEXT:    dmult $2, $1
+; MIPS64R2-NEXT:    mflo $1
+; MIPS64R2-NEXT:    lui $2, %highest(.LJTI0_0)
+; MIPS64R2-NEXT:    daddiu $2, $2, %higher(.LJTI0_0)
+; MIPS64R2-NEXT:    dsll $2, $2, 16
+; MIPS64R2-NEXT:    daddiu $2, $2, %hi(.LJTI0_0)
+; MIPS64R2-NEXT:    dsll $2, $2, 16
+; MIPS64R2-NEXT:    daddu $1, $1, $2
+; MIPS64R2-NEXT:    ld $1, %lo(.LJTI0_0)($1)
+; MIPS64R2-NEXT:    jr.hb $1
+; MIPS64R2-NEXT:    nop
+; MIPS64R2-NEXT:  .LBB0_2: # %sw.bb
+; MIPS64R2-NEXT:    lui $1, %highest(.L.str)
+; MIPS64R2-NEXT:    daddiu $1, $1, %higher(.L.str)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %hi(.L.str)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %lo(.L.str)
+; MIPS64R2-NEXT:    j .LBB0_10
+; MIPS64R2-NEXT:    sd $1, 8($sp)
+; MIPS64R2-NEXT:  .LBB0_3: # %sw.epilog
+; MIPS64R2-NEXT:    lui $1, %highest(.L.str.7)
+; MIPS64R2-NEXT:    daddiu $1, $1, %higher(.L.str.7)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %hi(.L.str.7)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %lo(.L.str.7)
+; MIPS64R2-NEXT:    j .LBB0_10
+; MIPS64R2-NEXT:    sd $1, 8($sp)
+; MIPS64R2-NEXT:  .LBB0_4: # %sw.bb1
+; MIPS64R2-NEXT:    lui $1, %highest(.L.str.1)
+; MIPS64R2-NEXT:    daddiu $1, $1, %higher(.L.str.1)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %hi(.L.str.1)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %lo(.L.str.1)
+; MIPS64R2-NEXT:    j .LBB0_10
+; MIPS64R2-NEXT:    sd $1, 8($sp)
+; MIPS64R2-NEXT:  .LBB0_5: # %sw.bb2
+; MIPS64R2-NEXT:    lui $1, %highest(.L.str.2)
+; MIPS64R2-NEXT:    daddiu $1, $1, %higher(.L.str.2)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %hi(.L.str.2)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %lo(.L.str.2)
+; MIPS64R2-NEXT:    j .LBB0_10
+; MIPS64R2-NEXT:    sd $1, 8($sp)
+; MIPS64R2-NEXT:  .LBB0_6: # %sw.bb3
+; MIPS64R2-NEXT:    lui $1, %highest(.L.str.3)
+; MIPS64R2-NEXT:    daddiu $1, $1, %higher(.L.str.3)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %hi(.L.str.3)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %lo(.L.str.3)
+; MIPS64R2-NEXT:    j .LBB0_10
+; MIPS64R2-NEXT:    sd $1, 8($sp)
+; MIPS64R2-NEXT:  .LBB0_7: # %sw.bb4
+; MIPS64R2-NEXT:    lui $1, %highest(.L.str.4)
+; MIPS64R2-NEXT:    daddiu $1, $1, %higher(.L.str.4)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %hi(.L.str.4)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %lo(.L.str.4)
+; MIPS64R2-NEXT:    j .LBB0_10
+; MIPS64R2-NEXT:    sd $1, 8($sp)
+; MIPS64R2-NEXT:  .LBB0_8: # %sw.bb5
+; MIPS64R2-NEXT:    lui $1, %highest(.L.str.5)
+; MIPS64R2-NEXT:    daddiu $1, $1, %higher(.L.str.5)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %hi(.L.str.5)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %lo(.L.str.5)
+; MIPS64R2-NEXT:    j .LBB0_10
+; MIPS64R2-NEXT:    sd $1, 8($sp)
+; MIPS64R2-NEXT:  .LBB0_9: # %sw.bb6
+; MIPS64R2-NEXT:    lui $1, %highest(.L.str.6)
+; MIPS64R2-NEXT:    daddiu $1, $1, %higher(.L.str.6)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %hi(.L.str.6)
+; MIPS64R2-NEXT:    dsll $1, $1, 16
+; MIPS64R2-NEXT:    daddiu $1, $1, %lo(.L.str.6)
+; MIPS64R2-NEXT:    sd $1, 8($sp)
+; MIPS64R2-NEXT:  .LBB0_10: # %return
+; MIPS64R2-NEXT:    ld $2, 8($sp)
+; MIPS64R2-NEXT:    jr $ra
+; MIPS64R2-NEXT:    daddiu $sp, $sp, 16
+;
+; MIPS64R6-LABEL: _Z3fooi:
+; MIPS64R6:       # BB#0: # %entry
+; MIPS64R6-NEXT:    daddiu $sp, $sp, -16
+; MIPS64R6-NEXT:  .Lcfi0:
+; MIPS64R6-NEXT:    .cfi_def_cfa_offset 16
+; MIPS64R6-NEXT:    sw $4, 4($sp)
+; MIPS64R6-NEXT:    lwu $2, 4($sp)
+; MIPS64R6-NEXT:    sltiu $1, $2, 7
+; MIPS64R6-NEXT:    beqzc $1, .LBB0_3
+; MIPS64R6-NEXT:  .LBB0_1: # %entry
+; MIPS64R6-NEXT:    dsll $1, $2, 3
+; MIPS64R6-NEXT:    lui $2, %highest(.LJTI0_0)
+; MIPS64R6-NEXT:    daddiu $2, $2, %higher(.LJTI0_0)
+; MIPS64R6-NEXT:    dsll $2, $2, 16
+; MIPS64R6-NEXT:    daddiu $2, $2, %hi(.LJTI0_0)
+; MIPS64R6-NEXT:    dsll $2, $2, 16
+; MIPS64R6-NEXT:    daddu $1, $1, $2
+; MIPS64R6-NEXT:    ld $1, %lo(.LJTI0_0)($1)
+; MIPS64R6-NEXT:    jr.hb $1
+; MIPS64R6-NEXT:    nop
+; MIPS64R6-NEXT:  .LBB0_2: # %sw.bb
+; MIPS64R6-NEXT:    lui $1, %highest(.L.str)
+; MIPS64R6-NEXT:    daddiu $1, $1, %higher(.L.str)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %hi(.L.str)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %lo(.L.str)
+; MIPS64R6-NEXT:    j .LBB0_10
+; MIPS64R6-NEXT:    sd $1, 8($sp)
+; MIPS64R6-NEXT:  .LBB0_3: # %sw.epilog
+; MIPS64R6-NEXT:    lui $1, %highest(.L.str.7)
+; MIPS64R6-NEXT:    daddiu $1, $1, %higher(.L.str.7)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %hi(.L.str.7)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %lo(.L.str.7)
+; MIPS64R6-NEXT:    j .LBB0_10
+; MIPS64R6-NEXT:    sd $1, 8($sp)
+; MIPS64R6-NEXT:  .LBB0_4: # %sw.bb1
+; MIPS64R6-NEXT:    lui $1, %highest(.L.str.1)
+; MIPS64R6-NEXT:    daddiu $1, $1, %higher(.L.str.1)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %hi(.L.str.1)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %lo(.L.str.1)
+; MIPS64R6-NEXT:    j .LBB0_10
+; MIPS64R6-NEXT:    sd $1, 8($sp)
+; MIPS64R6-NEXT:  .LBB0_5: # %sw.bb2
+; MIPS64R6-NEXT:    lui $1, %highest(.L.str.2)
+; MIPS64R6-NEXT:    daddiu $1, $1, %higher(.L.str.2)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %hi(.L.str.2)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %lo(.L.str.2)
+; MIPS64R6-NEXT:    j .LBB0_10
+; MIPS64R6-NEXT:    sd $1, 8($sp)
+; MIPS64R6-NEXT:  .LBB0_6: # %sw.bb3
+; MIPS64R6-NEXT:    lui $1, %highest(.L.str.3)
+; MIPS64R6-NEXT:    daddiu $1, $1, %higher(.L.str.3)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %hi(.L.str.3)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %lo(.L.str.3)
+; MIPS64R6-NEXT:    j .LBB0_10
+; MIPS64R6-NEXT:    sd $1, 8($sp)
+; MIPS64R6-NEXT:  .LBB0_7: # %sw.bb4
+; MIPS64R6-NEXT:    lui $1, %highest(.L.str.4)
+; MIPS64R6-NEXT:    daddiu $1, $1, %higher(.L.str.4)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %hi(.L.str.4)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %lo(.L.str.4)
+; MIPS64R6-NEXT:    j .LBB0_10
+; MIPS64R6-NEXT:    sd $1, 8($sp)
+; MIPS64R6-NEXT:  .LBB0_8: # %sw.bb5
+; MIPS64R6-NEXT:    lui $1, %highest(.L.str.5)
+; MIPS64R6-NEXT:    daddiu $1, $1, %higher(.L.str.5)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %hi(.L.str.5)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %lo(.L.str.5)
+; MIPS64R6-NEXT:    j .LBB0_10
+; MIPS64R6-NEXT:    sd $1, 8($sp)
+; MIPS64R6-NEXT:  .LBB0_9: # %sw.bb6
+; MIPS64R6-NEXT:    lui $1, %highest(.L.str.6)
+; MIPS64R6-NEXT:    daddiu $1, $1, %higher(.L.str.6)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %hi(.L.str.6)
+; MIPS64R6-NEXT:    dsll $1, $1, 16
+; MIPS64R6-NEXT:    daddiu $1, $1, %lo(.L.str.6)
+; MIPS64R6-NEXT:    sd $1, 8($sp)
+; MIPS64R6-NEXT:  .LBB0_10: # %return
+; MIPS64R6-NEXT:    ld $2, 8($sp)
+; MIPS64R6-NEXT:    jr $ra
+; MIPS64R6-NEXT:    daddiu $sp, $sp, 16
+;
+; PIC-MIPS32R2-LABEL: _Z3fooi:
+; PIC-MIPS32R2:       # BB#0: # %entry
+; PIC-MIPS32R2-NEXT:    lui $2, %hi(_gp_disp)
+; PIC-MIPS32R2-NEXT:    addiu $2, $2, %lo(_gp_disp)
+; PIC-MIPS32R2-NEXT:    addiu $sp, $sp, -16
+; PIC-MIPS32R2-NEXT:  $cfi0:
+; PIC-MIPS32R2-NEXT:    .cfi_def_cfa_offset 16
+; PIC-MIPS32R2-NEXT:    addu $2, $2, $25
+; PIC-MIPS32R2-NEXT:    sltiu $1, $4, 7
+; PIC-MIPS32R2-NEXT:    beqz $1, $BB0_3
+; PIC-MIPS32R2-NEXT:    sw $4, 4($sp)
+; PIC-MIPS32R2-NEXT:  $BB0_1: # %entry
+; PIC-MIPS32R2-NEXT:    sll $1, $4, 2
+; PIC-MIPS32R2-NEXT:    lw $3, %got($JTI0_0)($2)
+; PIC-MIPS32R2-NEXT:    addu $1, $1, $3
+; PIC-MIPS32R2-NEXT:    lw $1, %lo($JTI0_0)($1)
+; PIC-MIPS32R2-NEXT:    addu $1, $1, $2
+; PIC-MIPS32R2-NEXT:    jr.hb $1
+; PIC-MIPS32R2-NEXT:    nop
+; PIC-MIPS32R2-NEXT:  $BB0_2: # %sw.bb
+; PIC-MIPS32R2-NEXT:    lw $1, %got($.str)($2)
+; PIC-MIPS32R2-NEXT:    addiu $1, $1, %lo($.str)
+; PIC-MIPS32R2-NEXT:    b $BB0_10
+; PIC-MIPS32R2-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R2-NEXT:  $BB0_3: # %sw.epilog
+; PIC-MIPS32R2-NEXT:    lw $1, %got($.str.7)($2)
+; PIC-MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.7)
+; PIC-MIPS32R2-NEXT:    b $BB0_10
+; PIC-MIPS32R2-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R2-NEXT:  $BB0_4: # %sw.bb1
+; PIC-MIPS32R2-NEXT:    lw $1, %got($.str.1)($2)
+; PIC-MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.1)
+; PIC-MIPS32R2-NEXT:    b $BB0_10
+; PIC-MIPS32R2-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R2-NEXT:  $BB0_5: # %sw.bb2
+; PIC-MIPS32R2-NEXT:    lw $1, %got($.str.2)($2)
+; PIC-MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.2)
+; PIC-MIPS32R2-NEXT:    b $BB0_10
+; PIC-MIPS32R2-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R2-NEXT:  $BB0_6: # %sw.bb3
+; PIC-MIPS32R2-NEXT:    lw $1, %got($.str.3)($2)
+; PIC-MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.3)
+; PIC-MIPS32R2-NEXT:    b $BB0_10
+; PIC-MIPS32R2-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R2-NEXT:  $BB0_7: # %sw.bb4
+; PIC-MIPS32R2-NEXT:    lw $1, %got($.str.4)($2)
+; PIC-MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.4)
+; PIC-MIPS32R2-NEXT:    b $BB0_10
+; PIC-MIPS32R2-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R2-NEXT:  $BB0_8: # %sw.bb5
+; PIC-MIPS32R2-NEXT:    lw $1, %got($.str.5)($2)
+; PIC-MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.5)
+; PIC-MIPS32R2-NEXT:    b $BB0_10
+; PIC-MIPS32R2-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R2-NEXT:  $BB0_9: # %sw.bb6
+; PIC-MIPS32R2-NEXT:    lw $1, %got($.str.6)($2)
+; PIC-MIPS32R2-NEXT:    addiu $1, $1, %lo($.str.6)
+; PIC-MIPS32R2-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R2-NEXT:  $BB0_10: # %return
+; PIC-MIPS32R2-NEXT:    lw $2, 8($sp)
+; PIC-MIPS32R2-NEXT:    jr $ra
+; PIC-MIPS32R2-NEXT:    addiu $sp, $sp, 16
+;
+; PIC-MIPS32R6-LABEL: _Z3fooi:
+; PIC-MIPS32R6:       # BB#0: # %entry
+; PIC-MIPS32R6-NEXT:    lui $2, %hi(_gp_disp)
+; PIC-MIPS32R6-NEXT:    addiu $2, $2, %lo(_gp_disp)
+; PIC-MIPS32R6-NEXT:    addiu $sp, $sp, -16
+; PIC-MIPS32R6-NEXT:  $cfi0:
+; PIC-MIPS32R6-NEXT:    .cfi_def_cfa_offset 16
+; PIC-MIPS32R6-NEXT:    addu $2, $2, $25
+; PIC-MIPS32R6-NEXT:    sltiu $1, $4, 7
+; PIC-MIPS32R6-NEXT:    beqz $1, $BB0_3
+; PIC-MIPS32R6-NEXT:    sw $4, 4($sp)
+; PIC-MIPS32R6-NEXT:  $BB0_1: # %entry
+; PIC-MIPS32R6-NEXT:    sll $1, $4, 2
+; PIC-MIPS32R6-NEXT:    lw $3, %got($JTI0_0)($2)
+; PIC-MIPS32R6-NEXT:    addu $1, $1, $3
+; PIC-MIPS32R6-NEXT:    lw $1, %lo($JTI0_0)($1)
+; PIC-MIPS32R6-NEXT:    addu $1, $1, $2
+; PIC-MIPS32R6-NEXT:    jr.hb $1
+; PIC-MIPS32R6-NEXT:    nop
+; PIC-MIPS32R6-NEXT:  $BB0_2: # %sw.bb
+; PIC-MIPS32R6-NEXT:    lw $1, %got($.str)($2)
+; PIC-MIPS32R6-NEXT:    addiu $1, $1, %lo($.str)
+; PIC-MIPS32R6-NEXT:    b $BB0_10
+; PIC-MIPS32R6-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R6-NEXT:  $BB0_3: # %sw.epilog
+; PIC-MIPS32R6-NEXT:    lw $1, %got($.str.7)($2)
+; PIC-MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.7)
+; PIC-MIPS32R6-NEXT:    b $BB0_10
+; PIC-MIPS32R6-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R6-NEXT:  $BB0_4: # %sw.bb1
+; PIC-MIPS32R6-NEXT:    lw $1, %got($.str.1)($2)
+; PIC-MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.1)
+; PIC-MIPS32R6-NEXT:    b $BB0_10
+; PIC-MIPS32R6-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R6-NEXT:  $BB0_5: # %sw.bb2
+; PIC-MIPS32R6-NEXT:    lw $1, %got($.str.2)($2)
+; PIC-MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.2)
+; PIC-MIPS32R6-NEXT:    b $BB0_10
+; PIC-MIPS32R6-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R6-NEXT:  $BB0_6: # %sw.bb3
+; PIC-MIPS32R6-NEXT:    lw $1, %got($.str.3)($2)
+; PIC-MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.3)
+; PIC-MIPS32R6-NEXT:    b $BB0_10
+; PIC-MIPS32R6-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R6-NEXT:  $BB0_7: # %sw.bb4
+; PIC-MIPS32R6-NEXT:    lw $1, %got($.str.4)($2)
+; PIC-MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.4)
+; PIC-MIPS32R6-NEXT:    b $BB0_10
+; PIC-MIPS32R6-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R6-NEXT:  $BB0_8: # %sw.bb5
+; PIC-MIPS32R6-NEXT:    lw $1, %got($.str.5)($2)
+; PIC-MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.5)
+; PIC-MIPS32R6-NEXT:    b $BB0_10
+; PIC-MIPS32R6-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R6-NEXT:  $BB0_9: # %sw.bb6
+; PIC-MIPS32R6-NEXT:    lw $1, %got($.str.6)($2)
+; PIC-MIPS32R6-NEXT:    addiu $1, $1, %lo($.str.6)
+; PIC-MIPS32R6-NEXT:    sw $1, 8($sp)
+; PIC-MIPS32R6-NEXT:  $BB0_10: # %return
+; PIC-MIPS32R6-NEXT:    lw $2, 8($sp)
+; PIC-MIPS32R6-NEXT:    jr $ra
+; PIC-MIPS32R6-NEXT:    addiu $sp, $sp, 16
+;
+; PIC-MIPS64R2-LABEL: _Z3fooi:
+; PIC-MIPS64R2:       # BB#0: # %entry
+; PIC-MIPS64R2-NEXT:    daddiu $sp, $sp, -16
+; PIC-MIPS64R2-NEXT:  .Lcfi0:
+; PIC-MIPS64R2-NEXT:    .cfi_def_cfa_offset 16
+; PIC-MIPS64R2-NEXT:    lui $1, %hi(%neg(%gp_rel(_Z3fooi)))
+; PIC-MIPS64R2-NEXT:    daddu $1, $1, $25
+; PIC-MIPS64R2-NEXT:    daddiu $2, $1, %lo(%neg(%gp_rel(_Z3fooi)))
+; PIC-MIPS64R2-NEXT:    sw $4, 4($sp)
+; PIC-MIPS64R2-NEXT:    lwu $3, 4($sp)
+; PIC-MIPS64R2-NEXT:    sltiu $1, $3, 7
+; PIC-MIPS64R2-NEXT:    beqz $1, .LBB0_3
+; PIC-MIPS64R2-NEXT:    nop
+; PIC-MIPS64R2-NEXT:  .LBB0_1: # %entry
+; PIC-MIPS64R2-NEXT:    daddiu $1, $zero, 8
+; PIC-MIPS64R2-NEXT:    dmult $3, $1
+; PIC-MIPS64R2-NEXT:    mflo $1
+; PIC-MIPS64R2-NEXT:    ld $3, %got_page(.LJTI0_0)($2)
+; PIC-MIPS64R2-NEXT:    daddu $1, $1, $3
+; PIC-MIPS64R2-NEXT:    ld $1, %got_ofst(.LJTI0_0)($1)
+; PIC-MIPS64R2-NEXT:    daddu $1, $1, $2
+; PIC-MIPS64R2-NEXT:    jr.hb $1
+; PIC-MIPS64R2-NEXT:    nop
+; PIC-MIPS64R2-NEXT:  .LBB0_2: # %sw.bb
+; PIC-MIPS64R2-NEXT:    ld $1, %got_page(.L.str)($2)
+; PIC-MIPS64R2-NEXT:    daddiu $1, $1, %got_ofst(.L.str)
+; PIC-MIPS64R2-NEXT:    b .LBB0_10
+; PIC-MIPS64R2-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R2-NEXT:  .LBB0_3: # %sw.epilog
+; PIC-MIPS64R2-NEXT:    ld $1, %got_page(.L.str.7)($2)
+; PIC-MIPS64R2-NEXT:    daddiu $1, $1, %got_ofst(.L.str.7)
+; PIC-MIPS64R2-NEXT:    b .LBB0_10
+; PIC-MIPS64R2-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R2-NEXT:  .LBB0_4: # %sw.bb1
+; PIC-MIPS64R2-NEXT:    ld $1, %got_page(.L.str.1)($2)
+; PIC-MIPS64R2-NEXT:    daddiu $1, $1, %got_ofst(.L.str.1)
+; PIC-MIPS64R2-NEXT:    b .LBB0_10
+; PIC-MIPS64R2-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R2-NEXT:  .LBB0_5: # %sw.bb2
+; PIC-MIPS64R2-NEXT:    ld $1, %got_page(.L.str.2)($2)
+; PIC-MIPS64R2-NEXT:    daddiu $1, $1, %got_ofst(.L.str.2)
+; PIC-MIPS64R2-NEXT:    b .LBB0_10
+; PIC-MIPS64R2-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R2-NEXT:  .LBB0_6: # %sw.bb3
+; PIC-MIPS64R2-NEXT:    ld $1, %got_page(.L.str.3)($2)
+; PIC-MIPS64R2-NEXT:    daddiu $1, $1, %got_ofst(.L.str.3)
+; PIC-MIPS64R2-NEXT:    b .LBB0_10
+; PIC-MIPS64R2-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R2-NEXT:  .LBB0_7: # %sw.bb4
+; PIC-MIPS64R2-NEXT:    ld $1, %got_page(.L.str.4)($2)
+; PIC-MIPS64R2-NEXT:    daddiu $1, $1, %got_ofst(.L.str.4)
+; PIC-MIPS64R2-NEXT:    b .LBB0_10
+; PIC-MIPS64R2-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R2-NEXT:  .LBB0_8: # %sw.bb5
+; PIC-MIPS64R2-NEXT:    ld $1, %got_page(.L.str.5)($2)
+; PIC-MIPS64R2-NEXT:    daddiu $1, $1, %got_ofst(.L.str.5)
+; PIC-MIPS64R2-NEXT:    b .LBB0_10
+; PIC-MIPS64R2-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R2-NEXT:  .LBB0_9: # %sw.bb6
+; PIC-MIPS64R2-NEXT:    ld $1, %got_page(.L.str.6)($2)
+; PIC-MIPS64R2-NEXT:    daddiu $1, $1, %got_ofst(.L.str.6)
+; PIC-MIPS64R2-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R2-NEXT:  .LBB0_10: # %return
+; PIC-MIPS64R2-NEXT:    ld $2, 8($sp)
+; PIC-MIPS64R2-NEXT:    jr $ra
+; PIC-MIPS64R2-NEXT:    daddiu $sp, $sp, 16
+;
+; PIC-MIPS64R6-LABEL: _Z3fooi:
+; PIC-MIPS64R6:       # BB#0: # %entry
+; PIC-MIPS64R6-NEXT:    daddiu $sp, $sp, -16
+; PIC-MIPS64R6-NEXT:  .Lcfi0:
+; PIC-MIPS64R6-NEXT:    .cfi_def_cfa_offset 16
+; PIC-MIPS64R6-NEXT:    lui $1, %hi(%neg(%gp_rel(_Z3fooi)))
+; PIC-MIPS64R6-NEXT:    daddu $1, $1, $25
+; PIC-MIPS64R6-NEXT:    daddiu $2, $1, %lo(%neg(%gp_rel(_Z3fooi)))
+; PIC-MIPS64R6-NEXT:    sw $4, 4($sp)
+; PIC-MIPS64R6-NEXT:    lwu $3, 4($sp)
+; PIC-MIPS64R6-NEXT:    sltiu $1, $3, 7
+; PIC-MIPS64R6-NEXT:    beqzc $1, .LBB0_3
+; PIC-MIPS64R6-NEXT:  .LBB0_1: # %entry
+; PIC-MIPS64R6-NEXT:    dsll $1, $3, 3
+; PIC-MIPS64R6-NEXT:    ld $3, %got_page(.LJTI0_0)($2)
+; PIC-MIPS64R6-NEXT:    daddu $1, $1, $3
+; PIC-MIPS64R6-NEXT:    ld $1, %got_ofst(.LJTI0_0)($1)
+; PIC-MIPS64R6-NEXT:    daddu $1, $1, $2
+; PIC-MIPS64R6-NEXT:    jr.hb $1
+; PIC-MIPS64R6-NEXT:    nop
+; PIC-MIPS64R6-NEXT:  .LBB0_2: # %sw.bb
+; PIC-MIPS64R6-NEXT:    ld $1, %got_page(.L.str)($2)
+; PIC-MIPS64R6-NEXT:    daddiu $1, $1, %got_ofst(.L.str)
+; PIC-MIPS64R6-NEXT:    b .LBB0_10
+; PIC-MIPS64R6-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R6-NEXT:  .LBB0_3: # %sw.epilog
+; PIC-MIPS64R6-NEXT:    ld $1, %got_page(.L.str.7)($2)
+; PIC-MIPS64R6-NEXT:    daddiu $1, $1, %got_ofst(.L.str.7)
+; PIC-MIPS64R6-NEXT:    b .LBB0_10
+; PIC-MIPS64R6-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R6-NEXT:  .LBB0_4: # %sw.bb1
+; PIC-MIPS64R6-NEXT:    ld $1, %got_page(.L.str.1)($2)
+; PIC-MIPS64R6-NEXT:    daddiu $1, $1, %got_ofst(.L.str.1)
+; PIC-MIPS64R6-NEXT:    b .LBB0_10
+; PIC-MIPS64R6-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R6-NEXT:  .LBB0_5: # %sw.bb2
+; PIC-MIPS64R6-NEXT:    ld $1, %got_page(.L.str.2)($2)
+; PIC-MIPS64R6-NEXT:    daddiu $1, $1, %got_ofst(.L.str.2)
+; PIC-MIPS64R6-NEXT:    b .LBB0_10
+; PIC-MIPS64R6-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R6-NEXT:  .LBB0_6: # %sw.bb3
+; PIC-MIPS64R6-NEXT:    ld $1, %got_page(.L.str.3)($2)
+; PIC-MIPS64R6-NEXT:    daddiu $1, $1, %got_ofst(.L.str.3)
+; PIC-MIPS64R6-NEXT:    b .LBB0_10
+; PIC-MIPS64R6-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R6-NEXT:  .LBB0_7: # %sw.bb4
+; PIC-MIPS64R6-NEXT:    ld $1, %got_page(.L.str.4)($2)
+; PIC-MIPS64R6-NEXT:    daddiu $1, $1, %got_ofst(.L.str.4)
+; PIC-MIPS64R6-NEXT:    b .LBB0_10
+; PIC-MIPS64R6-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R6-NEXT:  .LBB0_8: # %sw.bb5
+; PIC-MIPS64R6-NEXT:    ld $1, %got_page(.L.str.5)($2)
+; PIC-MIPS64R6-NEXT:    daddiu $1, $1, %got_ofst(.L.str.5)
+; PIC-MIPS64R6-NEXT:    b .LBB0_10
+; PIC-MIPS64R6-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R6-NEXT:  .LBB0_9: # %sw.bb6
+; PIC-MIPS64R6-NEXT:    ld $1, %got_page(.L.str.6)($2)
+; PIC-MIPS64R6-NEXT:    daddiu $1, $1, %got_ofst(.L.str.6)
+; PIC-MIPS64R6-NEXT:    sd $1, 8($sp)
+; PIC-MIPS64R6-NEXT:  .LBB0_10: # %return
+; PIC-MIPS64R6-NEXT:    ld $2, 8($sp)
+; PIC-MIPS64R6-NEXT:    jr $ra
+; PIC-MIPS64R6-NEXT:    daddiu $sp, $sp, 16
+entry:
+  %retval = alloca i8*, align 8
+  %Letter.addr = alloca i32, align 4
+  store i32 %Letter, i32* %Letter.addr, align 4
+  %0 = load i32, i32* %Letter.addr, align 4
+  switch i32 %0, label %sw.epilog [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+    i32 4, label %sw.bb4
+    i32 5, label %sw.bb5
+    i32 6, label %sw.bb6
+  ]
+
+sw.bb:
+  store i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0), i8** %retval, align 8
+  br label %return
+
+sw.bb1:
+  store i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i32 0, i32 0), i8** %retval, align 8
+  br label %return
+
+sw.bb2:
+  store i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.2, i32 0, i32 0), i8** %retval, align 8
+  br label %return
+
+sw.bb3:
+  store i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.3, i32 0, i32 0), i8** %retval, align 8
+  br label %return
+
+sw.bb4:
+  store i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.4, i32 0, i32 0), i8** %retval, align 8
+  br label %return
+
+sw.bb5:
+  store i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.5, i32 0, i32 0), i8** %retval, align 8
+  br label %return
+
+sw.bb6:
+  store i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.6, i32 0, i32 0), i8** %retval, align 8
+  br label %return
+
+sw.epilog:
+  store i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.7, i32 0, i32 0), i8** %retval, align 8
+  br label %return
+
+return:
+  %1 = load i8*, i8** %retval, align 8
+  ret i8* %1
+}

Added: llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-branch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-branch.ll?rev=327751&view=auto
==============================================================================
--- llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-branch.ll (added)
+++ llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-branch.ll Fri Mar 16 15:14:38 2018
@@ -0,0 +1,138 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+;       Except for the NACL version which isn't parsed by update_llc_test_checks.py
+
+; RUN: llc -mtriple=mipsel-unknown-linux-gnu -force-mips-long-branch -O3 \
+; RUN:   -mcpu=mips32r2 -mattr=+use-indirect-jump-hazard -relocation-model=pic \
+; RUN:   -verify-machineinstrs < %s | FileCheck %s -check-prefix=O32-PIC
+
+; RUN: llc -mtriple=mipsel-unknown-linux-gnu -mcpu=mips32r6 \
+; RUN:   -force-mips-long-branch -O3 -mattr=+use-indirect-jump-hazard  \
+; RUN:   -relocation-model=pic -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=O32-R6-PIC
+
+; RUN: llc -mtriple=mips64el-unknown-linux-gnu -mcpu=mips64r2 -target-abi=n64 \
+; RUN:   -force-mips-long-branch -O3 -relocation-model=pic \
+; RUN:   -mattr=+use-indirect-jump-hazard -verify-machineinstrs \
+; RUN:   < %s | FileCheck %s -check-prefix=MIPS64
+
+; RUN: llc -mtriple=mips64el-unknown-linux-gnu -mcpu=mips64r6 -target-abi=n64 \
+; RUN:   -force-mips-long-branch -O3 -mattr=+use-indirect-jump-hazard \
+; RUN:   -relocation-model=pic -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=N64-R6
+
+; Test that the long branches also get changed to their hazard variants.
+
+ at x = external global i32
+
+define void @test1(i32 signext %s) {
+; O32-PIC-LABEL: test1:
+; O32-PIC:       # BB#0: # %entry
+; O32-PIC-NEXT:    lui $2, %hi(_gp_disp)
+; O32-PIC-NEXT:    addiu $2, $2, %lo(_gp_disp)
+; O32-PIC-NEXT:    bnez $4, $BB0_3
+; O32-PIC-NEXT:    addu $2, $2, $25
+; O32-PIC-NEXT:  # BB#1: # %entry
+; O32-PIC-NEXT:    addiu $sp, $sp, -8
+; O32-PIC-NEXT:    sw $ra, 0($sp)
+; O32-PIC-NEXT:    lui $1, %hi(($BB0_4)-($BB0_2))
+; O32-PIC-NEXT:    bal $BB0_2
+; O32-PIC-NEXT:    addiu $1, $1, %lo(($BB0_4)-($BB0_2))
+; O32-PIC-NEXT:  $BB0_2: # %entry
+; O32-PIC-NEXT:    addu $1, $ra, $1
+; O32-PIC-NEXT:    lw $ra, 0($sp)
+; O32-PIC-NEXT:    jr.hb $1
+; O32-PIC-NEXT:    addiu $sp, $sp, 8
+; O32-PIC-NEXT:  $BB0_3: # %then
+; O32-PIC-NEXT:    lw $1, %got(x)($2)
+; O32-PIC-NEXT:    addiu $2, $zero, 1
+; O32-PIC-NEXT:    sw $2, 0($1)
+; O32-PIC-NEXT:  $BB0_4: # %end
+; O32-PIC-NEXT:    jr $ra
+; O32-PIC-NEXT:    nop
+;
+; O32-R6-PIC-LABEL: test1:
+; O32-R6-PIC:       # BB#0: # %entry
+; O32-R6-PIC-NEXT:    lui $2, %hi(_gp_disp)
+; O32-R6-PIC-NEXT:    addiu $2, $2, %lo(_gp_disp)
+; O32-R6-PIC-NEXT:    bnez $4, $BB0_3
+; O32-R6-PIC-NEXT:    addu $2, $2, $25
+; O32-R6-PIC-NEXT:  # BB#1: # %entry
+; O32-R6-PIC-NEXT:    addiu $sp, $sp, -8
+; O32-R6-PIC-NEXT:    sw $ra, 0($sp)
+; O32-R6-PIC-NEXT:    lui $1, %hi(($BB0_4)-($BB0_2))
+; O32-R6-PIC-NEXT:    bal $BB0_2
+; O32-R6-PIC-NEXT:    addiu $1, $1, %lo(($BB0_4)-($BB0_2))
+; O32-R6-PIC-NEXT:  $BB0_2: # %entry
+; O32-R6-PIC-NEXT:    addu $1, $ra, $1
+; O32-R6-PIC-NEXT:    lw $ra, 0($sp)
+; O32-R6-PIC-NEXT:    jr.hb $1
+; O32-R6-PIC-NEXT:    addiu $sp, $sp, 8
+; O32-R6-PIC-NEXT:  $BB0_3: # %then
+; O32-R6-PIC-NEXT:    lw $1, %got(x)($2)
+; O32-R6-PIC-NEXT:    addiu $2, $zero, 1
+; O32-R6-PIC-NEXT:    sw $2, 0($1)
+; O32-R6-PIC-NEXT:  $BB0_4: # %end
+; O32-R6-PIC-NEXT:    jrc $ra
+;
+; MIPS64-LABEL: test1:
+; MIPS64:       # BB#0: # %entry
+; MIPS64-NEXT:    lui $1, %hi(%neg(%gp_rel(test1)))
+; MIPS64-NEXT:    bnez $4, .LBB0_3
+; MIPS64-NEXT:    daddu $2, $1, $25
+; MIPS64-NEXT:  # BB#1: # %entry
+; MIPS64-NEXT:    daddiu $sp, $sp, -16
+; MIPS64-NEXT:    sd $ra, 0($sp)
+; MIPS64-NEXT:    daddiu $1, $zero, %hi(.LBB0_4-.LBB0_2)
+; MIPS64-NEXT:    dsll $1, $1, 16
+; MIPS64-NEXT:    bal .LBB0_2
+; MIPS64-NEXT:    daddiu $1, $1, %lo(.LBB0_4-.LBB0_2)
+; MIPS64-NEXT:  .LBB0_2: # %entry
+; MIPS64-NEXT:    daddu $1, $ra, $1
+; MIPS64-NEXT:    ld $ra, 0($sp)
+; MIPS64-NEXT:    jr.hb $1
+; MIPS64-NEXT:    daddiu $sp, $sp, 16
+; MIPS64-NEXT:  .LBB0_3: # %then
+; MIPS64-NEXT:    daddiu $1, $2, %lo(%neg(%gp_rel(test1)))
+; MIPS64-NEXT:    addiu $2, $zero, 1
+; MIPS64-NEXT:    ld $1, %got_disp(x)($1)
+; MIPS64-NEXT:    sw $2, 0($1)
+; MIPS64-NEXT:  .LBB0_4: # %end
+; MIPS64-NEXT:    jr $ra
+; MIPS64-NEXT:    nop
+;
+; N64-R6-LABEL: test1:
+; N64-R6:       # BB#0: # %entry
+; N64-R6-NEXT:    lui $1, %hi(%neg(%gp_rel(test1)))
+; N64-R6-NEXT:    bnez $4, .LBB0_3
+; N64-R6-NEXT:    daddu $2, $1, $25
+; N64-R6-NEXT:  # BB#1: # %entry
+; N64-R6-NEXT:    daddiu $sp, $sp, -16
+; N64-R6-NEXT:    sd $ra, 0($sp)
+; N64-R6-NEXT:    daddiu $1, $zero, %hi(.LBB0_4-.LBB0_2)
+; N64-R6-NEXT:    dsll $1, $1, 16
+; N64-R6-NEXT:    bal .LBB0_2
+; N64-R6-NEXT:    daddiu $1, $1, %lo(.LBB0_4-.LBB0_2)
+; N64-R6-NEXT:  .LBB0_2: # %entry
+; N64-R6-NEXT:    daddu $1, $ra, $1
+; N64-R6-NEXT:    ld $ra, 0($sp)
+; N64-R6-NEXT:    jr.hb $1
+; N64-R6-NEXT:    daddiu $sp, $sp, 16
+; N64-R6-NEXT:  .LBB0_3: # %then
+; N64-R6-NEXT:    daddiu $1, $2, %lo(%neg(%gp_rel(test1)))
+; N64-R6-NEXT:    addiu $2, $zero, 1
+; N64-R6-NEXT:    ld $1, %got_disp(x)($1)
+; N64-R6-NEXT:    sw $2, 0($1)
+; N64-R6-NEXT:  .LBB0_4: # %end
+; N64-R6-NEXT:    jrc $ra
+entry:
+  %cmp = icmp eq i32 %s, 0
+  br i1 %cmp, label %end, label %then
+
+then:
+  store i32 1, i32* @x, align 4
+  br label %end
+
+end:
+  ret void
+
+}

Added: llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll?rev=327751&view=auto
==============================================================================
--- llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll (added)
+++ llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll Fri Mar 16 15:14:38 2018
@@ -0,0 +1,119 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=mips-unknwon-linux-gnu -mcpu=mips32r2 \
+; RUN:   -mattr=+use-indirect-jump-hazard,+long-calls,+noabicalls %s -o - \
+; RUN:   -verify-machineinstrs | FileCheck -check-prefix=O32 %s
+
+; RUN: llc -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r2 -target-abi n32 \
+; RUN:   -mattr=+use-indirect-jump-hazard,+long-calls,+noabicalls %s -o - \
+; RUN:   -verify-machineinstrs | FileCheck -check-prefix=N32 %s
+
+; RUN: llc -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r2 -target-abi n64 \
+; RUN:   -mattr=+use-indirect-jump-hazard,+long-calls,+noabicalls %s -o - \
+; RUN:   -verify-machineinstrs | FileCheck -check-prefix=N64 %s
+
+declare void @callee()
+declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i32, i1)
+
+ at val = internal unnamed_addr global [20 x i32] zeroinitializer, align 4
+
+; Test that the long call sequence uses the hazard barrier instruction variant.
+define void @caller() {
+; O32-LABEL: caller:
+; O32:       # BB#0:
+; O32-NEXT:    addiu $sp, $sp, -24
+; O32-NEXT:  $cfi0:
+; O32-NEXT:    .cfi_def_cfa_offset 24
+; O32-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
+; O32-NEXT:  $cfi1:
+; O32-NEXT:    .cfi_offset 31, -4
+; O32-NEXT:    lui $1, %hi(callee)
+; O32-NEXT:    addiu $25, $1, %lo(callee)
+; O32-NEXT:    jalr.hb $25
+; O32-NEXT:    nop
+; O32-NEXT:    lui $1, %hi(val)
+; O32-NEXT:    addiu $1, $1, %lo(val)
+; O32-NEXT:    lui $2, 20560
+; O32-NEXT:    ori $2, $2, 20560
+; O32-NEXT:    sw $2, 96($1)
+; O32-NEXT:    sw $2, 92($1)
+; O32-NEXT:    sw $2, 88($1)
+; O32-NEXT:    sw $2, 84($1)
+; O32-NEXT:    sw $2, 80($1)
+; O32-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
+; O32-NEXT:    jr $ra
+; O32-NEXT:    addiu $sp, $sp, 24
+;
+; N32-LABEL: caller:
+; N32:       # BB#0:
+; N32-NEXT:    addiu $sp, $sp, -16
+; N32-NEXT:  .Lcfi0:
+; N32-NEXT:    .cfi_def_cfa_offset 16
+; N32-NEXT:    sd $ra, 8($sp) # 8-byte Folded Spill
+; N32-NEXT:  .Lcfi1:
+; N32-NEXT:    .cfi_offset 31, -8
+; N32-NEXT:    lui $1, %hi(callee)
+; N32-NEXT:    addiu $25, $1, %lo(callee)
+; N32-NEXT:    jalr.hb $25
+; N32-NEXT:    nop
+; N32-NEXT:    lui $1, %hi(val)
+; N32-NEXT:    addiu $1, $1, %lo(val)
+; N32-NEXT:    lui $2, 1285
+; N32-NEXT:    daddiu $2, $2, 1285
+; N32-NEXT:    dsll $2, $2, 16
+; N32-NEXT:    daddiu $2, $2, 1285
+; N32-NEXT:    dsll $2, $2, 20
+; N32-NEXT:    daddiu $2, $2, 20560
+; N32-NEXT:    sdl $2, 88($1)
+; N32-NEXT:    sdl $2, 80($1)
+; N32-NEXT:    lui $3, 20560
+; N32-NEXT:    ori $3, $3, 20560
+; N32-NEXT:    sw $3, 96($1)
+; N32-NEXT:    sdr $2, 95($1)
+; N32-NEXT:    sdr $2, 87($1)
+; N32-NEXT:    ld $ra, 8($sp) # 8-byte Folded Reload
+; N32-NEXT:    jr $ra
+; N32-NEXT:    addiu $sp, $sp, 16
+;
+; N64-LABEL: caller:
+; N64:       # BB#0:
+; N64-NEXT:    daddiu $sp, $sp, -16
+; N64-NEXT:  .Lcfi0:
+; N64-NEXT:    .cfi_def_cfa_offset 16
+; N64-NEXT:    sd $ra, 8($sp) # 8-byte Folded Spill
+; N64-NEXT:  .Lcfi1:
+; N64-NEXT:    .cfi_offset 31, -8
+; N64-NEXT:    lui $1, %highest(callee)
+; N64-NEXT:    daddiu $1, $1, %higher(callee)
+; N64-NEXT:    dsll $1, $1, 16
+; N64-NEXT:    daddiu $1, $1, %hi(callee)
+; N64-NEXT:    dsll $1, $1, 16
+; N64-NEXT:    daddiu $25, $1, %lo(callee)
+; N64-NEXT:    jalr.hb $25
+; N64-NEXT:    nop
+; N64-NEXT:    lui $1, %highest(val)
+; N64-NEXT:    daddiu $1, $1, %higher(val)
+; N64-NEXT:    dsll $1, $1, 16
+; N64-NEXT:    daddiu $1, $1, %hi(val)
+; N64-NEXT:    dsll $1, $1, 16
+; N64-NEXT:    daddiu $1, $1, %lo(val)
+; N64-NEXT:    lui $2, 1285
+; N64-NEXT:    daddiu $2, $2, 1285
+; N64-NEXT:    dsll $2, $2, 16
+; N64-NEXT:    daddiu $2, $2, 1285
+; N64-NEXT:    dsll $2, $2, 20
+; N64-NEXT:    daddiu $2, $2, 20560
+; N64-NEXT:    lui $3, 20560
+; N64-NEXT:    sdl $2, 88($1)
+; N64-NEXT:    sdl $2, 80($1)
+; N64-NEXT:    ori $3, $3, 20560
+; N64-NEXT:    sw $3, 96($1)
+; N64-NEXT:    sdr $2, 95($1)
+; N64-NEXT:    sdr $2, 87($1)
+; N64-NEXT:    ld $ra, 8($sp) # 8-byte Folded Reload
+; N64-NEXT:    jr $ra
+; N64-NEXT:    daddiu $sp, $sp, 16
+  call void @callee()
+  call void @llvm.memset.p0i8.i32(i8* bitcast (i32* getelementptr inbounds ([20 x i32], [20 x i32]* @val, i64 1, i32 0) to i8*), i8 80, i32 20, i32 4, i1 false)
+  ret  void
+}
+

Added: llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-micromips.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-micromips.ll?rev=327751&view=auto
==============================================================================
--- llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-micromips.ll (added)
+++ llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-micromips.ll Fri Mar 16 15:14:38 2018
@@ -0,0 +1,5 @@
+; RUN: not llc -mtriple=mips-unknown-linux -mcpu=mips32r2 -mattr=+micromips,+use-indirect-jump-hazard %s 2>&1 | FileCheck %s
+
+; Test that microMIPS and indirect jump with hazard barriers is not supported.
+
+; CHECK: LLVM ERROR: cannot combine indirect jumps with hazard barriers and microMIPS

Added: llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-mips32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-mips32.ll?rev=327751&view=auto
==============================================================================
--- llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-mips32.ll (added)
+++ llvm/branches/release_50/test/CodeGen/Mips/indirect-jump-hazard/unsupported-mips32.ll Fri Mar 16 15:14:38 2018
@@ -0,0 +1,5 @@
+; RUN: not llc -mtriple=mips-unknown-linux -mcpu=mips32 -mattr=+use-indirect-jump-hazard %s 2>&1 | FileCheck %s
+
+; Test that mips32 and indirect jump with hazard barriers is not supported.
+
+; CHECK: LLVM ERROR: indirect jumps with hazard barriers requires MIPS32R2 or later

Modified: llvm/branches/release_50/test/CodeGen/Mips/tailcall/tailcall.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_50/test/CodeGen/Mips/tailcall/tailcall.ll?rev=327751&r1=327750&r2=327751&view=diff
==============================================================================
--- llvm/branches/release_50/test/CodeGen/Mips/tailcall/tailcall.ll (original)
+++ llvm/branches/release_50/test/CodeGen/Mips/tailcall/tailcall.ll Fri Mar 16 15:14:38 2018
@@ -163,7 +163,7 @@ entry:
 ; STATIC32: j
 ; PIC64: jr $25
 ; PIC64R6: jrc $25
-; PIC64R6MM: jr $25
+; PIC64R6MM: jrc16 $25
 ; STATIC64: j
 ; PIC16: jalrc
 




More information about the llvm-branch-commits mailing list