summaryrefslogtreecommitdiff
path: root/test/CodeGen/ARM/Windows
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGen/ARM/Windows')
-rw-r--r--test/CodeGen/ARM/Windows/builtin_longjmp.ll15
-rw-r--r--test/CodeGen/ARM/Windows/chkstk-movw-movt-isel.ll2
-rw-r--r--test/CodeGen/ARM/Windows/chkstk.ll4
-rw-r--r--test/CodeGen/ARM/Windows/dbzchk.ll192
-rw-r--r--test/CodeGen/ARM/Windows/division.ll23
-rw-r--r--test/CodeGen/ARM/Windows/dllexport.ll75
-rw-r--r--test/CodeGen/ARM/Windows/long-calls.ll4
-rw-r--r--test/CodeGen/ARM/Windows/no-aeabi.ll2
-rw-r--r--test/CodeGen/ARM/Windows/overflow.ll77
-rw-r--r--test/CodeGen/ARM/Windows/tls.ll157
10 files changed, 464 insertions, 87 deletions
diff --git a/test/CodeGen/ARM/Windows/builtin_longjmp.ll b/test/CodeGen/ARM/Windows/builtin_longjmp.ll
new file mode 100644
index 0000000000000..52b6f301bb77f
--- /dev/null
+++ b/test/CodeGen/ARM/Windows/builtin_longjmp.ll
@@ -0,0 +1,15 @@
+; RUN: llc -mtriple thumbv7--windows-itanium -filetype asm -o - %s | FileCheck %s
+
+declare void @llvm.eh.sjlj.longjmp(i8*)
+
+define arm_aapcs_vfpcc void @test___builtin_longjump(i8* %b) {
+entry:
+ tail call void @llvm.eh.sjlj.longjmp(i8* %b)
+ unreachable
+}
+
+; CHECK: push.w {r11, lr}
+; CHECK: ldr.w r11, [r0]
+; CHECK: ldr.w sp, [r0, #8]
+; CHECK: ldr.w pc, [r0, #4]
+
diff --git a/test/CodeGen/ARM/Windows/chkstk-movw-movt-isel.ll b/test/CodeGen/ARM/Windows/chkstk-movw-movt-isel.ll
index a314259e499ea..d303e9da8604e 100644
--- a/test/CodeGen/ARM/Windows/chkstk-movw-movt-isel.ll
+++ b/test/CodeGen/ARM/Windows/chkstk-movw-movt-isel.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mtriple thumbv7--windows-itanium -code-model large -filetype obj -o - %s \
+; RUN: llc -mtriple thumbv7--windows-itanium -code-model large -verify-machineinstrs -filetype obj -o - %s \
; RUN: | llvm-objdump -no-show-raw-insn -d - | FileCheck %s
; ModuleID = 'reduced.c'
diff --git a/test/CodeGen/ARM/Windows/chkstk.ll b/test/CodeGen/ARM/Windows/chkstk.ll
index cb787e14b5bad..330c1f4585009 100644
--- a/test/CodeGen/ARM/Windows/chkstk.ll
+++ b/test/CodeGen/ARM/Windows/chkstk.ll
@@ -1,7 +1,7 @@
-; RUN: llc -mtriple=thumbv7-windows -mcpu=cortex-a9 %s -o - \
+; RUN: llc -mtriple=thumbv7-windows -mcpu=cortex-a9 -verify-machineinstrs %s -o - \
; RUN: | FileCheck -check-prefix CHECK-DEFAULT-CODE-MODEL %s
-; RUN: llc -mtriple=thumbv7-windows -mcpu=cortex-a9 -code-model=large %s -o - \
+; RUN: llc -mtriple=thumbv7-windows -mcpu=cortex-a9 -code-model=large -verify-machineinstrs %s -o - \
; RUN: | FileCheck -check-prefix CHECK-LARGE-CODE-MODEL %s
define arm_aapcs_vfpcc void @check_watermark() {
diff --git a/test/CodeGen/ARM/Windows/dbzchk.ll b/test/CodeGen/ARM/Windows/dbzchk.ll
new file mode 100644
index 0000000000000..599a7cf094c43
--- /dev/null
+++ b/test/CodeGen/ARM/Windows/dbzchk.ll
@@ -0,0 +1,192 @@
+; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -o /dev/null %s 2>&1 | FileCheck %s -check-prefix CHECK-DIV
+
+; int f(int n, int d) {
+; if (n / d)
+; return 1;
+; return 0;
+; }
+
+define arm_aapcs_vfpcc i32 @f(i32 %n, i32 %d) {
+entry:
+ %retval = alloca i32, align 4
+ %n.addr = alloca i32, align 4
+ %d.addr = alloca i32, align 4
+ store i32 %n, i32* %n.addr, align 4
+ store i32 %d, i32* %d.addr, align 4
+ %0 = load i32, i32* %n.addr, align 4
+ %1 = load i32, i32* %d.addr, align 4
+ %div = sdiv i32 %0, %1
+ %tobool = icmp ne i32 %div, 0
+ br i1 %tobool, label %if.then, label %if.end
+
+if.then:
+ store i32 1, i32* %retval, align 4
+ br label %return
+
+if.end:
+ store i32 0, i32* %retval, align 4
+ br label %return
+
+return:
+ %2 = load i32, i32* %retval, align 4
+ ret i32 %2
+}
+
+; CHECK-DIV-DAG: BB#0
+; CHECK-DIV-DAG: Successors according to CFG: BB#5({{.*}}) BB#4
+; CHECK-DIV-DAG: BB#1
+; CHECK-DIV-DAG: Successors according to CFG: BB#3
+; CHECK-DIV-DAG: BB#2
+; CHECK-DIV-DAG: Successors according to CFG: BB#3
+; CHECK-DIV-DAG: BB#3
+; CHECK-DIV-DAG: BB#4
+; CHECK-DIV-DAG: Successors according to CFG: BB#1({{.*}}) BB#2
+; CHECK-DIV-DAG: BB#5
+
+; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -o /dev/null %s 2>&1 | FileCheck %s -check-prefix CHECK-MOD
+
+; int r;
+; int g(int l, int m) {
+; if (m <= 0)
+; return 0;
+; return (r = l % m);
+; }
+
+@r = common global i32 0, align 4
+
+define arm_aapcs_vfpcc i32 @g(i32 %l, i32 %m) {
+entry:
+ %cmp = icmp eq i32 %m, 0
+ br i1 %cmp, label %return, label %if.end
+
+if.end:
+ %rem = urem i32 %l, %m
+ store i32 %rem, i32* @r, align 4
+ br label %return
+
+return:
+ %retval.0 = phi i32 [ %rem, %if.end ], [ 0, %entry ]
+ ret i32 %retval.0
+}
+
+; CHECK-MOD-DAG: BB#0
+; CHECK-MOD-DAG: Successors according to CFG: BB#2({{.*}}) BB#1
+; CHECK-MOD-DAG: BB#1
+; CHECK-MOD-DAG: Successors according to CFG: BB#4({{.*}}) BB#3
+; CHECK-MOD-DAG: BB#2
+; CHECK-MOD-DAG: BB#3
+; CHECK-MOD-DAG: Successors according to CFG: BB#2
+; CHECK-MOD-DAG: BB#4
+
+; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -filetype asm -o /dev/null %s 2>&1 | FileCheck %s -check-prefix CHECK-CFG
+; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-CFG-ASM
+
+; unsigned c;
+; extern unsigned long g(void);
+; int f(unsigned u, signed char b) {
+; if (b)
+; c = g() % u;
+; return c;
+; }
+
+@c = common global i32 0, align 4
+
+declare arm_aapcs_vfpcc i32 @i()
+
+define arm_aapcs_vfpcc i32 @h(i32 %u, i8 signext %b) #0 {
+entry:
+ %tobool = icmp eq i8 %b, 0
+ br i1 %tobool, label %entry.if.end_crit_edge, label %if.then
+
+entry.if.end_crit_edge:
+ %.pre = load i32, i32* @c, align 4
+ br label %if.end
+
+if.then:
+ %call = tail call arm_aapcs_vfpcc i32 @i()
+ %rem = urem i32 %call, %u
+ store i32 %rem, i32* @c, align 4
+ br label %if.end
+
+if.end:
+ %0 = phi i32 [ %.pre, %entry.if.end_crit_edge ], [ %rem, %if.then ]
+ ret i32 %0
+}
+
+attributes #0 = { optsize }
+
+; CHECK-CFG-DAG: BB#0
+; CHECK-CFG-DAG: t2Bcc <BB#2>
+; CHECK-CFG-DAG: t2B <BB#1>
+
+; CHECK-CFG-DAG: BB#1
+; CHECK-CFG-DAG: t2B <BB#3>
+
+; CHECK-CFG-DAG: BB#2
+; CHECK-CFG-DAG: tCBZ %vreg{{[0-9]}}, <BB#5>
+; CHECK-CFG-DAG: t2B <BB#4>
+
+; CHECK-CFG-DAG: BB#4
+
+; CHECK-CFG-DAG: BB#3
+; CHECK-CFG-DAG: tBX_RET
+
+; CHECK-CFG-DAG: BB#5
+; CHECK-CFG-DAG: t2UDF 249
+
+; CHECK-CFG-ASM-LABEL: h:
+; CHECK-CFG-ASM: cbz r{{[0-9]}}, .LBB2_2
+; CHECK-CFG-ASM: b .LBB2_4
+; CHECK-CFG-ASM-LABEL: .LBB2_2:
+; CHECK-CFG-ASM-NEXT: udf.w #249
+; CHECK-CFG-ASM-LABEL: .LBB2_4:
+; CHECK-CFG-ASM: bl __rt_udiv
+; CHECK-CFG-ASM: pop.w {{{.*}}, r11, pc}
+
+; RUN: llc -O0 -mtriple thumbv7--windows-itanium -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-WIN__DBZCHK
+
+; long k(void);
+; int l(void);
+; int j(int i) {
+; if (l() == -1)
+; return 0;
+; return k() % i;
+; }
+
+declare arm_aapcs_vfpcc i32 @k()
+declare arm_aapcs_vfpcc i32 @l()
+
+define arm_aapcs_vfpcc i32 @j(i32 %i) {
+entry:
+ %retval = alloca i32, align 4
+ %i.addr = alloca i32, align 4
+ store i32 %i, i32* %i.addr, align 4
+ %call = call arm_aapcs_vfpcc i32 @l()
+ %cmp = icmp eq i32 %call, -1
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+ store i32 0, i32* %retval, align 4
+ br label %return
+
+if.end:
+ %call1 = call arm_aapcs_vfpcc i32 @k()
+ %0 = load i32, i32* %i.addr, align 4
+ %rem = srem i32 %call1, %0
+ store i32 %rem, i32* %retval, align 4
+ br label %return
+
+return:
+ %1 = load i32, i32* %retval, align 4
+ ret i32 %1
+}
+
+; CHECK-WIN__DBZCHK-LABEL: j:
+; CHECK-WIN__DBZCHK: cbz r{{[0-7]}}, .LBB
+; CHECK-WIN__DBZCHK-NOT: cbz r8, .LBB
+; CHECK-WIN__DBZCHK-NOT: cbz r9, .LBB
+; CHECK-WIN__DBZCHK-NOT: cbz r10, .LBB
+; CHECK-WIN__DBZCHK-NOT: cbz r11, .LBB
+; CHECK-WIN__DBZCHK-NOT: cbz ip, .LBB
+; CHECK-WIN__DBZCHK-NOT: cbz lr, .LBB
+
diff --git a/test/CodeGen/ARM/Windows/division.ll b/test/CodeGen/ARM/Windows/division.ll
index b3ef9c6d278b6..f4704ea7ff4b7 100644
--- a/test/CodeGen/ARM/Windows/division.ll
+++ b/test/CodeGen/ARM/Windows/division.ll
@@ -7,8 +7,11 @@ entry:
ret i32 %div
}
-; CHECK-LABEL: sdiv32
-; CHECK: b __rt_sdiv
+; CHECK-LABEL: sdiv32:
+; CHECK: cbz r0
+; CHECK: b
+; CHECK: udf.w #249
+; CHECK: bl __rt_sdiv
define arm_aapcs_vfpcc i32 @udiv32(i32 %divisor, i32 %divident) {
entry:
@@ -17,7 +20,10 @@ entry:
}
; CHECK-LABEL: udiv32:
-; CHECK: b __rt_udiv
+; CHECK: cbz r0
+; CHECK: b
+; CHECK: udf.w #249
+; CHECK: bl __rt_udiv
define arm_aapcs_vfpcc i64 @sdiv64(i64 %divisor, i64 %divident) {
entry:
@@ -25,7 +31,11 @@ entry:
ret i64 %div
}
-; CHECK-LABEL: sdiv64
+; CHECK-LABEL: sdiv64:
+; CHECK: orr.w r4, r0, r1
+; CHECK-NEXT: cbz r4
+; CHECK: b
+; CHECK: udf.w #249
; CHECK: bl __rt_sdiv64
define arm_aapcs_vfpcc i64 @udiv64(i64 %divisor, i64 %divident) {
@@ -35,4 +45,9 @@ entry:
}
; CHECK-LABEL: udiv64:
+; CHECK: orr.w r4, r0, r1
+; CHECK-NEXT: cbz r4
+; CHECK: b
+; CHECK: udf.w #249
; CHECK: bl __rt_udiv64
+
diff --git a/test/CodeGen/ARM/Windows/dllexport.ll b/test/CodeGen/ARM/Windows/dllexport.ll
new file mode 100644
index 0000000000000..27496208862e1
--- /dev/null
+++ b/test/CodeGen/ARM/Windows/dllexport.ll
@@ -0,0 +1,75 @@
+; RUN: llc -mtriple thumbv7--windows-itanium -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-GNU
+; RUN: llc -mtriple thumbv7--windows-gnu -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-GNU
+; RUN: llc -mtriple thumbv7--windows-msvc -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MSVC
+
+define void @f() {
+ ret void
+}
+
+define dllexport void @g() {
+ ret void
+}
+
+define dllexport void @h() unnamed_addr {
+ ret void
+}
+
+declare dllexport void @i()
+
+define linkonce_odr dllexport void @j() {
+ ret void
+}
+
+define linkonce_odr dllexport void @k() alwaysinline {
+ ret void
+}
+
+define weak_odr dllexport void @l() {
+ ret void
+}
+
+@m = dllexport global i32 0, align 4
+@n = dllexport unnamed_addr constant i32 0
+@o = common dllexport global i32 0, align 4
+@p = weak_odr dllexport global i32 0, align 4
+@q = weak_odr dllexport unnamed_addr constant i32 0
+
+@r = dllexport alias void (), void () * @f
+@s = dllexport alias void (), void () * @g
+@t = dllexport alias void (), void () * @f
+@u = weak_odr dllexport alias void (), void () * @g
+
+; CHECK: .section .drectve
+; CHECK-GNU-NOT: -export:f
+; CHECK-GNU: -export:g
+; CHECK-GNU-SAME: -export:h
+; CHECK-GNU-NOT: -export:i
+; CHECK-GNU-SAME: -export:j
+; CHECK-GNU-SAME: -export:k
+; CHECK-GNU-SAME: -export:l
+; CHECK-GNU-SAME: -export:m,data
+; CHECK-GNU-SAME: -export:n,data
+; CHECK-GNU-SAME: -export:o,data
+; CHECK-GNU-SAME: -export:p,data
+; CHECK-GNU-SAME: -export:q,data
+; CHECK-GNU-SAME: -export:r
+; CHECK-GNU-SAME: -export:s
+; CHECK-GNU-SAME: -export:t
+; CHECK-GNU-SAME: -export:u
+; CHECK-MSVC-NOT: /EXPORT:f
+; CHECK-MSVC: /EXPORT:g
+; CHECK-MSVC-SAME: /EXPORT:h
+; CHECK-MSVC-NOT: /EXPORT:i
+; CHECK-MSVC-SAME: /EXPORT:j
+; CHECK-MSVC-SAME: /EXPORT:k
+; CHECK-MSVC-SAME: /EXPORT:l
+; CHECK-MSVC-SAME: /EXPORT:m,DATA
+; CHECK-MSVC-SAME: /EXPORT:n,DATA
+; CHECK-MSVC-SAME: /EXPORT:o,DATA
+; CHECK-MSVC-SAME: /EXPORT:p,DATA
+; CHECK-MSVC-SAME: /EXPORT:q,DATA
+; CHECK-MSVC-SAME: /EXPORT:r
+; CHECK-MSVC-SAME: /EXPORT:s
+; CHECK-MSVC-SAME: /EXPORT:t
+; CHECK-MSVC-SAME: /EXPORT:u
+
diff --git a/test/CodeGen/ARM/Windows/long-calls.ll b/test/CodeGen/ARM/Windows/long-calls.ll
index 4e5bdce146f01..29e6f783ae5fb 100644
--- a/test/CodeGen/ARM/Windows/long-calls.ll
+++ b/test/CodeGen/ARM/Windows/long-calls.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mtriple=thumbv7-windows -mcpu=cortex-a9 -mattr=+long-calls -o - %s \
+; RUN: llc -mtriple=thumbv7-windows -mcpu=cortex-a9 -relocation-model pic -mattr=+long-calls -o - %s \
; RUN: | FileCheck %s
declare arm_aapcs_vfpcc void @callee()
@@ -12,7 +12,7 @@ entry:
; CHECK-LABEL: caller
; CHECK: ldr [[REG:r[0-9]+]], [[CPI:LCPI[_0-9]+]]
; CHECK: bx [[REG]]
-; CHECK: .align 2
+; CHECK: .p2align 2
; CHECK: [[CPI]]:
; CHECK: .long callee
diff --git a/test/CodeGen/ARM/Windows/no-aeabi.ll b/test/CodeGen/ARM/Windows/no-aeabi.ll
index 3971b9ccf5803..a4103b0a676e5 100644
--- a/test/CodeGen/ARM/Windows/no-aeabi.ll
+++ b/test/CodeGen/ARM/Windows/no-aeabi.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mtriple=thumbv7-windows-itanium -mcpu=cortex-a9 -o - %s | FileCheck %s
+; RUN: llc -mtriple=thumbv7-windows-itanium -mcpu=cortex-a9 -verify-machineinstrs -o - %s | FileCheck %s
declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
diff --git a/test/CodeGen/ARM/Windows/overflow.ll b/test/CodeGen/ARM/Windows/overflow.ll
deleted file mode 100644
index 5f74f25ac2242..0000000000000
--- a/test/CodeGen/ARM/Windows/overflow.ll
+++ /dev/null
@@ -1,77 +0,0 @@
-; RUN: llc -mtriple thumbv7-windows-gnu -filetype asm -o - %s
-
-define i32 @divsoverflow32(i32 %a, i32 %b) {
- %1 = alloca i32, align 4
- %2 = alloca i32, align 4
- %3 = load i32, i32* %1, align 4
- %4 = load i32, i32* %2, align 4
- %5 = sub nsw i32 0, %4
- %6 = sdiv i32 -2147483647, %3
- %7 = icmp sgt i32 %5, %6
- br i1 %7, label %8, label %9
- call void (...) @abort_simpl32()
- unreachable
- %10 = load i32, i32* %1, align 4
- %11 = load i32, i32* %2, align 4
- %12 = mul nsw i32 %10, %11
- ret i32 %12
-}
-
-declare void @abort_simpl32(...)
-
-define i64 @divsoverflow64(i64 %a, i64 %b) {
- %1 = alloca i64, align 8
- %2 = alloca i64, align 8
- %3 = load i64, i64* %1, align 8
- %4 = load i64, i64* %2, align 8
- %5 = sub nsw i64 0, %4
- %6 = sdiv i64 -9223372036854775808, %3
- %7 = icmp sgt i64 %5, %6
- br i1 %7, label %8, label %9
- call void (...) @abort_simpl64()
- unreachable
- %10 = load i64, i64* %1, align 8
- %11 = load i64, i64* %2, align 8
- %12 = mul nsw i64 %10, %11
- ret i64 %12
-}
-
-declare void @abort_simpl64(...)
-
-define i32 @divuoverflow32(i32 %a, i32 %b) {
- %1 = alloca i32, align 4
- %2 = alloca i32, align 4
- %3 = load i32, i32* %1, align 4
- %4 = load i32, i32* %2, align 4
- %5 = sub nsw i32 0, %4
- %6 = udiv i32 4294967296, %3
- %7 = icmp sgt i32 %5, %6
- br i1 %7, label %8, label %9
- call void (...) @abort_uimpl32()
- unreachable
- %10 = load i32, i32* %1, align 4
- %11 = load i32, i32* %2, align 4
- %12 = mul nsw i32 %10, %11
- ret i32 %12
-}
-
-declare void @abort_uimpl32(...)
-
-define i64 @divuoverflow64(i64 %a, i64 %b) {
- %1 = alloca i64, align 8
- %2 = alloca i64, align 8
- %3 = load i64, i64* %1, align 8
- %4 = load i64, i64* %2, align 8
- %5 = sub nsw i64 0, %4
- %6 = udiv i64 18446744073709551616, %3
- %7 = icmp sgt i64 %5, %6
- br i1 %7, label %8, label %9
- call void (...) @abort_uimpl64()
- unreachable
- %10 = load i64, i64* %1, align 8
- %11 = load i64, i64* %2, align 8
- %12 = mul nsw i64 %10, %11
- ret i64 %12
-}
-
-declare void @abort_uimpl64(...)
diff --git a/test/CodeGen/ARM/Windows/tls.ll b/test/CodeGen/ARM/Windows/tls.ll
new file mode 100644
index 0000000000000..689f4e291872c
--- /dev/null
+++ b/test/CodeGen/ARM/Windows/tls.ll
@@ -0,0 +1,157 @@
+; RUN: llc -mtriple thumbv7--windows-itanium %s -o - | FileCheck %s
+
+@i = thread_local global i32 0
+@j = external thread_local global i32
+@k = internal thread_local global i32 0
+@l = hidden thread_local global i32 0
+@m = external hidden thread_local global i32
+@n = thread_local global i16 0
+@o = thread_local global i8 0
+
+define i32 @f() {
+ %1 = load i32, i32* @i
+ ret i32 %1
+}
+
+; CHECK: mrc p15, #0, [[TEB:r[0-9]]], c13, c0, #2
+
+; CHECK: movw [[TLS_INDEX:r[0-9]]], :lower16:_tls_index
+; CHECK-NEXT: movt [[TLS_INDEX]], :upper16:_tls_index
+; CHECK-NEXT: ldr [[INDEX:r[0-9]]], {{\[}}[[TLS_INDEX]]]
+
+; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
+; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
+
+; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
+
+; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
+
+; CHECK: [[CPI]]:
+; CHECK-NEXT: .long i(SECREL32)
+
+define i32 @e() {
+ %1 = load i32, i32* @j
+ ret i32 %1
+}
+
+; CHECK: mrc p15, #0, [[TEB:r[0-9]]], c13, c0, #2
+
+; CHECK: movw [[TLS_INDEX:r[0-9]]], :lower16:_tls_index
+; CHECK-NEXT: movt [[TLS_INDEX]], :upper16:_tls_index
+; CHECK-NEXT: ldr [[INDEX:r[0-9]]], {{\[}}[[TLS_INDEX]]]
+
+; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
+; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
+
+; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
+
+; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
+
+; CHECK: [[CPI]]:
+; CHECK-NEXT: .long j(SECREL32)
+
+define i32 @d() {
+ %1 = load i32, i32* @k
+ ret i32 %1
+}
+
+; CHECK: mrc p15, #0, [[TEB:r[0-9]]], c13, c0, #2
+
+; CHECK: movw [[TLS_INDEX:r[0-9]]], :lower16:_tls_index
+; CHECK-NEXT: movt [[TLS_INDEX]], :upper16:_tls_index
+; CHECK-NEXT: ldr [[INDEX:r[0-9]]], {{\[}}[[TLS_INDEX]]]
+
+; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
+; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
+
+; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
+
+; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
+
+; CHECK: [[CPI]]:
+; CHECK-NEXT: .long k(SECREL32)
+
+define i32 @c() {
+ %1 = load i32, i32* @l
+ ret i32 %1
+}
+
+; CHECK: mrc p15, #0, [[TEB:r[0-9]]], c13, c0, #2
+
+; CHECK: movw [[TLS_INDEX:r[0-9]]], :lower16:_tls_index
+; CHECK-NEXT: movt [[TLS_INDEX]], :upper16:_tls_index
+; CHECK-NEXT: ldr [[INDEX:r[0-9]]], {{\[}}[[TLS_INDEX]]]
+
+; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
+; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
+
+; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
+
+; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
+
+; CHECK: [[CPI]]:
+; CHECK-NEXT: .long l(SECREL32)
+
+define i32 @b() {
+ %1 = load i32, i32* @m
+ ret i32 %1
+}
+
+; CHECK: mrc p15, #0, [[TEB:r[0-9]]], c13, c0, #2
+
+; CHECK: movw [[TLS_INDEX:r[0-9]]], :lower16:_tls_index
+; CHECK-NEXT: movt [[TLS_INDEX]], :upper16:_tls_index
+; CHECK-NEXT: ldr [[INDEX:r[0-9]]], {{\[}}[[TLS_INDEX]]]
+
+; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
+; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
+
+; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
+
+; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
+
+; CHECK: [[CPI]]:
+; CHECK: .long m(SECREL32)
+
+define i16 @a() {
+ %1 = load i16, i16* @n
+ ret i16 %1
+}
+
+; CHECK: mrc p15, #0, [[TEB:r[0-9]]], c13, c0, #2
+
+; CHECK: movw [[TLS_INDEX:r[0-9]]], :lower16:_tls_index
+; CHECK-NEXT: movt [[TLS_INDEX]], :upper16:_tls_index
+; CHECK-NEXT: ldr [[INDEX:r[0-9]]], {{\[}}[[TLS_INDEX]]]
+
+; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
+; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
+
+; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
+
+; CHECK-NEXT: ldrh r0, {{\[}}[[TLS]], [[SLOT]]]
+
+; CHECK: [[CPI]]:
+; CHECK: .long n(SECREL32)
+
+define i8 @Z() {
+ %1 = load i8, i8* @o
+ ret i8 %1
+}
+
+; CHECK: mrc p15, #0, [[TEB:r[0-9]]], c13, c0, #2
+
+; CHECK: movw [[TLS_INDEX:r[0-9]]], :lower16:_tls_index
+; CHECK-NEXT: movt [[TLS_INDEX]], :upper16:_tls_index
+; CHECK-NEXT: ldr [[INDEX:r[0-9]]], {{\[}}[[TLS_INDEX]]]
+
+; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
+; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
+
+; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
+
+; CHECK-NEXT: ldrb r0, {{\[}}[[TLS]], [[SLOT]]]
+
+; CHECK: [[CPI]]:
+; CHECK-NEXT: .long o(SECREL32)
+