summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@mips.com>2018-04-11 12:55:10 +0000
committerSimon Dardis <simon.dardis@mips.com>2018-04-11 12:55:10 +0000
commit84bc444011dcc51cac4d95503495fa35f4f4032a (patch)
treed12706c9cbc8b2001d265670f70585fba100ced5 /test
parent417182e182569ed6ccac18a64bcef7b952cd5f8d (diff)
Merging r325653 with test fixups:
------------------------------------------------------------------------ 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 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_60@329798 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/CodeGen/Mips/indirect-jump-hazard/calls.ll188
-rw-r--r--test/CodeGen/Mips/indirect-jump-hazard/guards-verify-call.mir58
-rw-r--r--test/CodeGen/Mips/indirect-jump-hazard/guards-verify-tailcall.mir59
-rw-r--r--test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll649
-rw-r--r--test/CodeGen/Mips/indirect-jump-hazard/long-branch.ll138
-rw-r--r--test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll113
-rw-r--r--test/CodeGen/Mips/indirect-jump-hazard/unsupported-micromips.ll5
-rw-r--r--test/CodeGen/Mips/indirect-jump-hazard/unsupported-mips32.ll5
8 files changed, 1215 insertions, 0 deletions
diff --git a/test/CodeGen/Mips/indirect-jump-hazard/calls.ll b/test/CodeGen/Mips/indirect-jump-hazard/calls.ll
new file mode 100644
index 00000000000..20e89136d87
--- /dev/null
+++ b/test/CodeGen/Mips/indirect-jump-hazard/calls.ll
@@ -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
+}
diff --git a/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-call.mir b/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-call.mir
new file mode 100644
index 00000000000..1c11d700b53
--- /dev/null
+++ b/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-call.mir
@@ -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
+
+...
diff --git a/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-tailcall.mir b/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-tailcall.mir
new file mode 100644
index 00000000000..00e22b934bb
--- /dev/null
+++ b/test/CodeGen/Mips/indirect-jump-hazard/guards-verify-tailcall.mir
@@ -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
+
+...
diff --git a/test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll b/test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll
new file mode 100644
index 00000000000..c530dd614ef
--- /dev/null
+++ b/test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll
@@ -0,0 +1,649 @@
+; 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
+
+@.str = private unnamed_addr constant [2 x i8] c"A\00", align 1
+@.str.1 = private unnamed_addr constant [2 x i8] c"B\00", align 1
+@.str.2 = private unnamed_addr constant [2 x i8] c"C\00", align 1
+@.str.3 = private unnamed_addr constant [2 x i8] c"D\00", align 1
+@.str.4 = private unnamed_addr constant [2 x i8] c"E\00", align 1
+@.str.5 = private unnamed_addr constant [2 x i8] c"F\00", align 1
+@.str.6 = private unnamed_addr constant [2 x i8] c"G\00", align 1
+@.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: .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: .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: .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: .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: .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: .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: .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: .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
+}
diff --git a/test/CodeGen/Mips/indirect-jump-hazard/long-branch.ll b/test/CodeGen/Mips/indirect-jump-hazard/long-branch.ll
new file mode 100644
index 00000000000..fffda991ae4
--- /dev/null
+++ b/test/CodeGen/Mips/indirect-jump-hazard/long-branch.ll
@@ -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.
+
+@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: addiu $1, $1, %lo(($BB0_4)-($BB0_2))
+; O32-R6-PIC-NEXT: balc $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: daddiu $1, $1, %lo(.LBB0_4-.LBB0_2)
+; N64-R6-NEXT: balc .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
+
+}
diff --git a/test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll b/test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll
new file mode 100644
index 00000000000..88886e13f32
--- /dev/null
+++ b/test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll
@@ -0,0 +1,113 @@
+; 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)
+
+@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: .cfi_def_cfa_offset 24
+; O32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; 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: .cfi_def_cfa_offset 16
+; N32-NEXT: sd $ra, 8($sp) # 8-byte Folded Spill
+; 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: .cfi_def_cfa_offset 16
+; N64-NEXT: sd $ra, 8($sp) # 8-byte Folded Spill
+; 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
+}
+
diff --git a/test/CodeGen/Mips/indirect-jump-hazard/unsupported-micromips.ll b/test/CodeGen/Mips/indirect-jump-hazard/unsupported-micromips.ll
new file mode 100644
index 00000000000..99612525ae3
--- /dev/null
+++ b/test/CodeGen/Mips/indirect-jump-hazard/unsupported-micromips.ll
@@ -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
diff --git a/test/CodeGen/Mips/indirect-jump-hazard/unsupported-mips32.ll b/test/CodeGen/Mips/indirect-jump-hazard/unsupported-mips32.ll
new file mode 100644
index 00000000000..48baedf53ea
--- /dev/null
+++ b/test/CodeGen/Mips/indirect-jump-hazard/unsupported-mips32.ll
@@ -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