summaryrefslogtreecommitdiffstats
path: root/llvm/test/CodeGen/ARM
diff options
context:
space:
mode:
authorOliver Stannard <oliver.stannard@arm.com>2016-08-08 15:28:31 +0000
committerOliver Stannard <oliver.stannard@arm.com>2016-08-08 15:28:31 +0000
commit8331aaee8fb9172ddf0cb45c4b04cb76fe224da4 (patch)
treec5549f749c7cf270e5e3b0c5cfc25490a0fad3d3 /llvm/test/CodeGen/ARM
parent219feac45643d92784186bcee627d940775b596b (diff)
downloadbcm5719-llvm-8331aaee8fb9172ddf0cb45c4b04cb76fe224da4.tar.gz
bcm5719-llvm-8331aaee8fb9172ddf0cb45c4b04cb76fe224da4.zip
[ARM] Add support for embedded position-independent code
This patch adds support for some new relocation models to the ARM backend: * Read-only position independence (ROPI): Code and read-only data is accessed PC-relative. The offsets between all code and RO data sections are known at static link time. This does not affect read-write data. * Read-write position independence (RWPI): Read-write data is accessed relative to the static base register (r9). The offsets between all writeable data sections are known at static link time. This does not affect read-only data. These two modes are independent (they specify how different objects should be addressed), so they can be used individually or together. They are otherwise the same as the "static" relocation model, and are not compatible with SysV-style PIC using a global offset table. These modes are normally used by bare-metal systems or systems with small real-time operating systems. They are designed to avoid the need for a dynamic linker, the only initialisation required is setting r9 to an appropriate value for RWPI code. I have only added support to SelectionDAG, not FastISel, because FastISel is currently disabled for bare-metal targets where these modes would be used. Differential Revision: https://reviews.llvm.org/D23195 llvm-svn: 278015
Diffstat (limited to 'llvm/test/CodeGen/ARM')
-rw-r--r--llvm/test/CodeGen/ARM/arm-position-independence-jump-table.ll114
-rw-r--r--llvm/test/CodeGen/ARM/arm-position-independence.ll309
-rw-r--r--llvm/test/CodeGen/ARM/build-attributes.ll12
3 files changed, 435 insertions, 0 deletions
diff --git a/llvm/test/CodeGen/ARM/arm-position-independence-jump-table.ll b/llvm/test/CodeGen/ARM/arm-position-independence-jump-table.ll
new file mode 100644
index 00000000000..507f399c1f7
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/arm-position-independence-jump-table.ll
@@ -0,0 +1,114 @@
+; Test for generation of jump table for ropi/rwpi
+
+; RUN: llc -relocation-model=static -mtriple=armv7a--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM --check-prefix=ARM_ABS
+; RUN: llc -relocation-model=ropi -mtriple=armv7a--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM --check-prefix=ARM_PC
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=armv7a--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM --check-prefix=ARM_PC
+
+; RUN: llc -relocation-model=static -mtriple=thumbv7m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2
+; RUN: llc -relocation-model=ropi -mtriple=thumbv7m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=thumbv7m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2
+
+; RUN: llc -relocation-model=static -mtriple=thumbv6m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1 --check-prefix=THUMB1_ABS
+; RUN: llc -relocation-model=ropi -mtriple=thumbv6m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1 --check-prefix=THUMB1_PC
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=thumbv6m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1 --check-prefix=THUMB1_PC
+
+
+declare void @exit0()
+declare void @exit1()
+declare void @exit2()
+declare void @exit3()
+declare void @exit4()
+define void @jump_table(i32 %val) {
+entry:
+ switch i32 %val, label %default [ i32 1, label %lab1
+ i32 2, label %lab2
+ i32 3, label %lab3
+ i32 4, label %lab4 ]
+
+default:
+ tail call void @exit0()
+ ret void
+
+lab1:
+ tail call void @exit1()
+ ret void
+
+lab2:
+ tail call void @exit2()
+ ret void
+
+lab3:
+ tail call void @exit3()
+ ret void
+
+lab4:
+ tail call void @exit4()
+ ret void
+
+; CHECK-LABEL: jump_table:
+
+; ARM: lsl r[[R_TAB_IDX:[0-9]+]], r{{[0-9]+}}, #2
+; ARM: adr r[[R_TAB_BASE:[0-9]+]], [[LJTI:\.LJTI[0-9]+_[0-9]+]]
+; ARM_ABS: ldr pc, [r[[R_TAB_IDX]], r[[R_TAB_BASE]]]
+; ARM_PC: ldr r[[R_OFFSET:[0-9]+]], [r[[R_TAB_IDX]], r[[R_TAB_BASE]]]
+; ARM_PC: add pc, r[[R_OFFSET]], r[[R_TAB_BASE]]
+; ARM: [[LJTI]]
+; ARM_ABS: .long [[LBB1:\.LBB[0-9]+_[0-9]+]]
+; ARM_ABS: .long [[LBB2:\.LBB[0-9]+_[0-9]+]]
+; ARM_ABS: .long [[LBB3:\.LBB[0-9]+_[0-9]+]]
+; ARM_ABS: .long [[LBB4:\.LBB[0-9]+_[0-9]+]]
+; ARM_PC: .long [[LBB1:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; ARM_PC: .long [[LBB2:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; ARM_PC: .long [[LBB3:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; ARM_PC: .long [[LBB4:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; ARM: [[LBB1]]
+; ARM-NEXT: b exit1
+; ARM: [[LBB2]]
+; ARM-NEXT: b exit2
+; ARM: [[LBB3]]
+; ARM-NEXT: b exit3
+; ARM: [[LBB4]]
+; ARM-NEXT: b exit4
+
+; THUMB2: [[LCPI:\.LCPI[0-9]+_[0-9]+]]:
+; THUMB2: tbb [pc, r{{[0-9]+}}]
+; THUMB2: .byte ([[LBB1:\.LBB[0-9]+_[0-9]+]]-([[LCPI]]+4))/2
+; THUMB2: .byte ([[LBB2:\.LBB[0-9]+_[0-9]+]]-([[LCPI]]+4))/2
+; THUMB2: .byte ([[LBB3:\.LBB[0-9]+_[0-9]+]]-([[LCPI]]+4))/2
+; THUMB2: .byte ([[LBB4:\.LBB[0-9]+_[0-9]+]]-([[LCPI]]+4))/2
+; THUMB2: [[LBB1]]
+; THUMB2-NEXT: b exit1
+; THUMB2: [[LBB2]]
+; THUMB2-NEXT: b exit2
+; THUMB2: [[LBB3]]
+; THUMB2-NEXT: b exit3
+; THUMB2: [[LBB4]]
+; THUMB2-NEXT: b exit4
+
+; THUMB1: lsls r[[R_TAB_INDEX:[0-9]+]], r{{[0-9]+}}, #2
+; THUMB1: adr r[[R_TAB_BASE:[0-9]+]], [[LJTI:\.LJTI[0-9]+_[0-9]+]]
+; THUMB1: ldr r[[R_BB_ADDR:[0-9]+]], [r[[R_TAB_INDEX]], r[[R_TAB_BASE]]]
+; THUMB1_PC: adds r[[R_BB_ADDR]], r[[R_BB_ADDR]], r[[R_TAB_BASE]]
+; THUMB1: mov pc, r[[R_BB_ADDR]]
+; THUMB1: [[LJTI]]
+; THUMB1_ABS: .long [[LBB1:\.LBB[0-9]+_[0-9]+]]+1
+; THUMB1_ABS: .long [[LBB2:\.LBB[0-9]+_[0-9]+]]+1
+; THUMB1_ABS: .long [[LBB3:\.LBB[0-9]+_[0-9]+]]+1
+; THUMB1_ABS: .long [[LBB4:\.LBB[0-9]+_[0-9]+]]+1
+; THUMB1_PC: .long [[LBB1:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; THUMB1_PC: .long [[LBB2:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; THUMB1_PC: .long [[LBB3:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; THUMB1_PC: .long [[LBB4:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; THUMB1: [[LBB1]]
+; THUMB1-NEXT: bl exit1
+; THUMB1-NEXT: pop
+; THUMB1: [[LBB2]]
+; THUMB1-NEXT: bl exit2
+; THUMB1-NEXT: pop
+; THUMB1: [[LBB3]]
+; THUMB1-NEXT: bl exit3
+; THUMB1-NEXT: pop
+; THUMB1: [[LBB4]]
+; THUMB1-NEXT: bl exit4
+; THUMB1-NEXT: pop
+}
diff --git a/llvm/test/CodeGen/ARM/arm-position-independence.ll b/llvm/test/CodeGen/ARM/arm-position-independence.ll
new file mode 100644
index 00000000000..02a63984ad6
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/arm-position-independence.ll
@@ -0,0 +1,309 @@
+; RUN: llc -relocation-model=static -mtriple=armv7a--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM_RO_ABS --check-prefix=ARM_RW_ABS
+; RUN: llc -relocation-model=ropi -mtriple=armv7a--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM_RO_PC --check-prefix=ARM_RW_ABS
+; RUN: llc -relocation-model=rwpi -mtriple=armv7a--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM_RO_ABS --check-prefix=ARM_RW_SB
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=armv7a--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM_RO_PC --check-prefix=ARM_RW_SB
+
+; RUN: llc -relocation-model=static -mtriple=thumbv7m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2_RO_ABS --check-prefix=THUMB2_RW_ABS
+; RUN: llc -relocation-model=ropi -mtriple=thumbv7m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2_RO_PC --check-prefix=THUMB2_RW_ABS
+; RUN: llc -relocation-model=rwpi -mtriple=thumbv7m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2_RO_ABS --check-prefix=THUMB2_RW_SB
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=thumbv7m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2_RO_PC --check-prefix=THUMB2_RW_SB
+
+; RUN: llc -relocation-model=static -mtriple=thumbv6m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1_RO_ABS --check-prefix=THUMB1_RW_ABS
+; RUN: llc -relocation-model=ropi -mtriple=thumbv6m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1_RO_PC --check-prefix=THUMB1_RW_ABS
+; RUN: llc -relocation-model=rwpi -mtriple=thumbv6m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1_RO_ABS --check-prefix=THUMB1_RW_SB
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=thumbv6m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1_RO_PC --check-prefix=THUMB1_RW_SB
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+
+@a = external global i32, align 4
+@b = external constant i32, align 4
+
+define i32 @read() {
+entry:
+ %0 = load i32, i32* @a, align 4
+ ret i32 %0
+; CHECK-LABEL: read:
+
+; ARM_RW_ABS: movw r[[REG:[0-9]]], :lower16:a
+; ARM_RW_ABS: movt r[[REG]], :upper16:a
+; ARM_RW_ABS: ldr r0, [r[[REG]]]
+
+; ARM_RW_SB: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; ARM_RW_SB: ldr r0, [r9, r[[REG]]]
+
+; THUMB2_RW_ABS: movw r[[REG:[0-9]]], :lower16:a
+; THUMB2_RW_ABS: movt r[[REG]], :upper16:a
+; THUMB2_RW_ABS: ldr r0, [r[[REG]]]
+
+; THUMB2_RW_SB: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB2_RW_SB: ldr.w r0, [r9, r[[REG]]]
+
+; THUMB1_RW_ABS: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_ABS: ldr r0, [r[[REG]]]
+
+; THUMB1_RW_SB: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_SB: mov r[[REG_SB:[0-9]+]], r9
+; THUMB1_RW_SB: ldr r0, [r[[REG_SB]], r[[REG]]]
+
+; CHECK: {{(bx lr|pop)}}
+
+; ARM_RW_SB: [[LCPI]]
+; ARM_RW_SB: .long a(sbrel)
+
+; THUMB2_RW_SB: [[LCPI]]
+; THUMB2_RW_SB: .long a(sbrel)
+
+; THUMB1_RW_ABS: [[LCPI]]
+; THUMB1_RW_ABS-NEXT: .long a
+
+; THUMB1_RW_SB: [[LCPI]]
+; THUMB1_RW_SB: .long a(sbrel)
+}
+
+define void @write(i32 %v) {
+entry:
+ store i32 %v, i32* @a, align 4
+ ret void
+; CHECK-LABEL: write:
+
+; ARM_RW_ABS: movw r[[REG:[0-9]]], :lower16:a
+; ARM_RW_ABS: movt r[[REG]], :upper16:a
+; ARM_RW_ABS: str r0, [r[[REG:[0-9]]]]
+
+; ARM_RW_SB: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; ARM_RW_SB: str r0, [r9, r[[REG]]]
+
+; THUMB2_RW_ABS: movw r[[REG:[0-9]]], :lower16:a
+; THUMB2_RW_ABS: movt r[[REG]], :upper16:a
+; THUMB2_RW_ABS: str r0, [r[[REG]]]
+
+; THUMB2_RW_SB: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB2_RW_SB: str.w r0, [r9, r[[REG]]]
+
+; THUMB1_RW_ABS: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_ABS: str r0, [r[[REG]]]
+
+; THUMB1_RW_SB: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_SB: mov r[[REG_SB:[0-9]+]], r9
+; THUMB1_RW_SB: str r0, [r[[REG_SB]], r[[REG]]]
+
+; CHECK: {{(bx lr|pop)}}
+
+; ARM_RW_SB: [[LCPI]]
+; ARM_RW_SB: .long a(sbrel)
+
+; THUMB2_RW_SB: [[LCPI]]
+; THUMB2_RW_SB: .long a(sbrel)
+
+; THUMB1_RW_ABS: [[LCPI]]
+; THUMB1_RW_ABS-NEXT: .long a
+
+; THUMB1_RW_SB: [[LCPI]]
+; THUMB1_RW_SB: .long a(sbrel)
+}
+
+define i32 @read_const() {
+entry:
+ %0 = load i32, i32* @b, align 4
+ ret i32 %0
+; CHECK-LABEL: read_const:
+
+; ARM_RO_ABS: movw r[[reg:[0-9]]], :lower16:b
+; ARM_RO_ABS: movt r[[reg]], :upper16:b
+; ARM_RO_ABS: ldr r0, [r[[reg]]]
+
+; ARM_RO_PC: movw r[[REG:[0-9]]], :lower16:(b-([[LPC:.LPC[0-9]+_[0-9]+]]+8))
+; ARM_RO_PC: movt r[[REG]], :upper16:(b-([[LPC]]+8))
+; ARM_RO_PC: [[LPC]]:
+; ARM_RO_PC-NEXT: ldr r0, [pc, r[[REG]]]
+
+; THUMB2_RO_ABS: movw r[[REG:[0-9]]], :lower16:b
+; THUMB2_RO_ABS: movt r[[REG]], :upper16:b
+; THUMB2_RO_ABS: ldr r0, [r[[REG]]]
+
+; THUMB2_RO_PC: movw r[[REG:[0-9]]], :lower16:(b-([[LPC:.LPC[0-9]+_[0-9]+]]+4))
+; THUMB2_RO_PC: movt r[[REG]], :upper16:(b-([[LPC]]+4))
+; THUMB2_RO_PC: [[LPC]]:
+; THUMB2_RO_PC-NEXT: add r[[REG]], pc
+; THUMB2_RO_PC: ldr r0, [r[[REG]]]
+
+; THUMB1_RO_ABS: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_ABS: ldr r0, [r[[REG]]]
+
+; THUMB1_RO_PC: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB1_RO_PC-NEXT: add r[[REG]], pc
+; THUMB1_RO_PC: ldr r0, [r[[REG]]]
+
+; CHECK: {{(bx lr|pop)}}
+
+; THUMB1_RO_ABS: [[LCPI]]
+; THUMB1_RO_ABS-NEXT: .long b
+
+; THUMB1_RO_PC: [[LCPI]]
+; THUMB1_RO_PC-NEXT: .long b-([[LPC]]+4)
+}
+
+define i32* @take_addr() {
+entry:
+ ret i32* @a
+; CHECK-LABEL: take_addr:
+
+; ARM_RW_ABS: movw r[[REG:[0-9]]], :lower16:a
+; ARM_RW_ABS: movt r[[REG]], :upper16:a
+
+; ARM_RW_SB: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; ARM_RW_SB: add r0, r9, r[[REG]]
+
+; THUMB2_RW_ABS: movw r[[REG:[0-9]]], :lower16:a
+; THUMB2_RW_ABS: movt r[[REG]], :upper16:a
+
+; THUMB2_RW_SB: ldr r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB2_RW_SB: add r0, r9
+
+; THUMB1_RW_ABS: ldr r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB1_RW_SB: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_SB: mov r[[REG_SB:[0-9]+]], r9
+; THUMB1_RW_SB: adds r[[REG]], r[[REG_SB]], r[[REG]]
+
+; CHECK: {{(bx lr|pop)}}
+
+; ARM_RW_SB: [[LCPI]]
+; ARM_RW_SB: .long a(sbrel)
+
+; THUMB2_RW_SB: [[LCPI]]
+; THUMB2_RW_SB: .long a(sbrel)
+
+; THUMB1_RW_ABS: [[LCPI]]
+; THUMB1_RW_ABS-NEXT: .long a
+
+; THUMB1_RW_SB: [[LCPI]]
+; THUMB1_RW_SB: .long a(sbrel)
+}
+
+define i32* @take_addr_const() {
+entry:
+ ret i32* @b
+; CHECK-LABEL: take_addr_const:
+
+; ARM_RO_ABS: movw r[[REG:[0-9]]], :lower16:b
+; ARM_RO_ABS: movt r[[REG]], :upper16:b
+
+; ARM_RO_PC: movw r[[REG:[0-9]]], :lower16:(b-([[LPC:.LPC[0-9]+_[0-9]+]]+8))
+; ARM_RO_PC: movt r[[REG]], :upper16:(b-([[LPC]]+8))
+; ARM_RO_PC: [[LPC]]:
+; ARM_RO_PC-NEXT: add r0, pc, r[[REG:[0-9]]]
+
+; THUMB2_RO_ABS: movw r[[REG:[0-9]]], :lower16:b
+; THUMB2_RO_ABS: movt r[[REG]], :upper16:b
+
+; THUMB2_RO_PC: movw r0, :lower16:(b-([[LPC:.LPC[0-9]+_[0-9]+]]+4))
+; THUMB2_RO_PC: movt r0, :upper16:(b-([[LPC]]+4))
+; THUMB2_RO_PC: [[LPC]]:
+; THUMB2_RO_PC-NEXT: add r0, pc
+
+; THUMB1_RO_ABS: ldr r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB1_RO_PC: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB1_RO_PC-NEXT: add r[[REG]], pc
+
+; CHECK: {{(bx lr|pop)}}
+
+; THUMB1_RO_ABS: [[LCPI]]
+; THUMB1_RO_ABS-NEXT: .long b
+
+; THUMB1_RO_PC: [[LCPI]]
+; THUMB1_RO_PC-NEXT: .long b-([[LPC]]+4)
+}
+
+define i8* @take_addr_func() {
+entry:
+ ret i8* bitcast (i8* ()* @take_addr_func to i8*)
+; CHECK-LABEL: take_addr_func:
+
+; ARM_RO_ABS: movw r[[REG:[0-9]]], :lower16:take_addr_func
+; ARM_RO_ABS: movt r[[REG]], :upper16:take_addr_func
+
+; ARM_RO_PC: movw r[[REG:[0-9]]], :lower16:(take_addr_func-([[LPC:.LPC[0-9]+_[0-9]+]]+8))
+; ARM_RO_PC: movt r[[REG]], :upper16:(take_addr_func-([[LPC]]+8))
+; ARM_RO_PC: [[LPC]]:
+; ARM_RO_PC-NEXT: add r0, pc, r[[REG:[0-9]]]
+
+; THUMB2_RO_ABS: movw r[[REG:[0-9]]], :lower16:take_addr_func
+; THUMB2_RO_ABS: movt r[[REG]], :upper16:take_addr_func
+
+; THUMB2_RO_PC: movw r0, :lower16:(take_addr_func-([[LPC:.LPC[0-9]+_[0-9]+]]+4))
+; THUMB2_RO_PC: movt r0, :upper16:(take_addr_func-([[LPC]]+4))
+; THUMB2_RO_PC: [[LPC]]:
+; THUMB2_RO_PC-NEXT: add r0, pc
+
+; THUMB1_RO_ABS: ldr r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB1_RO_PC: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB1_RO_PC-NEXT: add r[[REG]], pc
+
+; CHECK: {{(bx lr|pop)}}
+
+; THUMB1_RO_ABS: [[LCPI]]
+; THUMB1_RO_ABS-NEXT: .long take_addr_func
+
+; THUMB1_RO_PC: [[LCPI]]
+; THUMB1_RO_PC-NEXT: .long take_addr_func-([[LPC]]+4)
+}
+
+define i8* @block_addr() {
+entry:
+ br label %lab1
+
+lab1:
+ ret i8* blockaddress(@block_addr, %lab1)
+
+; CHECK-LABEL: block_addr:
+
+; ARM_RO_ABS: [[LTMP:.Ltmp[0-9]+]]:
+; ARM_RO_ABS: ldr r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; ARM_RO_PC: [[LTMP:.Ltmp[0-9]+]]:
+; ARM_RO_PC: ldr r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; ARM_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; ARM_RO_PC: add r0, pc, r[[REG]]
+
+; THUMB2_RO_ABS: [[LTMP:.Ltmp[0-9]+]]:
+; THUMB2_RO_ABS: ldr r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB2_RO_PC: [[LTMP:.Ltmp[0-9]+]]:
+; THUMB2_RO_PC: ldr r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB2_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB2_RO_PC: add r0, pc
+
+; THUMB1_RO_ABS: [[LTMP:.Ltmp[0-9]+]]:
+; THUMB1_RO_ABS: ldr r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB1_RO_PC: [[LTMP:.Ltmp[0-9]+]]:
+; THUMB1_RO_PC: ldr r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB1_RO_PC: add r0, pc
+
+; CHECK: bx lr
+
+; ARM_RO_ABS: [[LCPI]]
+; ARM_RO_ABS-NEXT: .long [[LTMP]]
+
+; ARM_RO_PC: [[LCPI]]
+; ARM_RO_PC-NEXT: .long [[LTMP]]-([[LPC]]+8)
+
+; THUMB2_RO_ABS: [[LCPI]]
+; THUMB2_RO_ABS-NEXT: .long [[LTMP]]
+
+; THUMB2_RO_PC: [[LCPI]]
+; THUMB2_RO_PC-NEXT: .long [[LTMP]]-([[LPC]]+4)
+
+; THUMB1_RO_ABS: [[LCPI]]
+; THUMB1_RO_ABS-NEXT: .long [[LTMP]]
+
+; THUMB1_RO_PC: [[LCPI]]
+; THUMB1_RO_PC-NEXT: .long [[LTMP]]-([[LPC]]+4)
+}
diff --git a/llvm/test/CodeGen/ARM/build-attributes.ll b/llvm/test/CodeGen/ARM/build-attributes.ll
index 990db8a00c4..53b8fc39a7c 100644
--- a/llvm/test/CodeGen/ARM/build-attributes.ll
+++ b/llvm/test/CodeGen/ARM/build-attributes.ll
@@ -147,6 +147,9 @@
; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align | FileCheck %s --check-prefix=RELOC-OTHER
; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align | FileCheck %s --check-prefix=PCS-R9-USE
; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+reserve-r9,+strict-align | FileCheck %s --check-prefix=PCS-R9-RESERVE
+; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align -relocation-model=ropi | FileCheck %s --check-prefix=RELOC-ROPI
+; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align -relocation-model=rwpi | FileCheck %s --check-prefix=RELOC-RWPI
+; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align -relocation-model=ropi-rwpi | FileCheck %s --check-prefix=RELOC-ROPI-RWPI
; ARMv8.1a (AArch32)
; RUN: llc < %s -mtriple=armv8.1a-none-linux-gnueabi | FileCheck %s --check-prefix=NO-STRICT-ALIGN
@@ -1522,6 +1525,15 @@
; RELOC-PIC: .eabi_attribute 16, 1
; RELOC-PIC: .eabi_attribute 17, 2
; RELOC-OTHER: .eabi_attribute 17, 1
+; RELOC-ROPI-NOT: .eabi_attribute 15,
+; RELOC-ROPI: .eabi_attribute 16, 1
+; RELOC-ROPI: .eabi_attribute 17, 1
+; RELOC-RWPI: .eabi_attribute 15, 2
+; RELOC-RWPI-NOT: .eabi_attribute 16,
+; RELOC-RWPI: .eabi_attribute 17, 1
+; RELOC-ROPI-RWPI: .eabi_attribute 15, 2
+; RELOC-ROPI-RWPI: .eabi_attribute 16, 1
+; RELOC-ROPI-RWPI: .eabi_attribute 17, 1
; PCS-R9-USE: .eabi_attribute 14, 0
; PCS-R9-RESERVE: .eabi_attribute 14, 3
OpenPOWER on IntegriCloud