summaryrefslogtreecommitdiffstats
path: root/llvm/test
diff options
context:
space:
mode:
authorDavid Tellenbach <david.tellenbach@me.com>2019-12-05 02:20:59 +0100
committerDavid Tellenbach <david.tellenbach@me.com>2019-12-05 02:20:59 +0100
commitcec2d5c17457722113580251c8a045fa9aca9b1b (patch)
tree1124f091c79eef1eb183e440c74caa6a815c93fc /llvm/test
parent28f5ad5801d408b35afc437fb3c430104ee3ce3e (diff)
downloadbcm5719-llvm-cec2d5c17457722113580251c8a045fa9aca9b1b.tar.gz
bcm5719-llvm-cec2d5c17457722113580251c8a045fa9aca9b1b.zip
Reland [AArch64][MachineOutliner] Return address signing for outlined functions
Summary: Reland after fixing an ASan failure by stopping outlining early if the constraints for return address signing removed too many outlining candidates. During AArch64 frame lowering instructions to enable return address signing are inserted into functions if needed. Functions generated during machine outlining don't run through target frame lowering and hence are missing such instructions. This patch introduces the following changes: 1. If not all functions that potentially participate in function outlining agree on their return address signing scope and their return address signing key, outlining is disabled for these functions. 2. If not all functions that potentially participate in function outlining agree on their support for v8.3A features, outlining is disabled for these functions. 3. If an outlining candidate would outline instructions that modify sp in a way that invalidates return address signing, outlining is disabled for that particular candidate. 4. If all candidate functions agree on the signing scope, signing key and their support for v8.3 features, the outlined function behaves as if it had the same scope and key attributes and as if it would provide the same v8.3A support as the original functions. Reviewers: ostannard, paquette Reviewed By: ostannard Subscribers: kristof.beyls, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D70635
Diffstat (limited to 'llvm/test')
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-cfi.ll80
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-diff-scope-same-key.ll68
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-non-leaf.ll72
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-regsave.mir127
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-diff-key.ll69
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-same-key-a.ll64
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-same-key-b.ll70
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.mir204
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-subtarget.ll87
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-thunk.ll63
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-v8-3.ll83
11 files changed, 987 insertions, 0 deletions
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-cfi.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-cfi.ll
new file mode 100644
index 00000000000..820d08bd94b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-cfi.ll
@@ -0,0 +1,80 @@
+; RUN: llc -verify-machineinstrs -enable-machine-outliner -mtriple \
+; RUN: aarch64-arm-none-eabi %s -o - | FileCheck %s
+
+; Function a's outlining candidate contains a sp modifying add without a
+; corresponsing sub, so we shouldn't outline it.
+define void @a() "sign-return-address"="all" "sign-return-address-key"="b_key" {
+; CHECK-LABEL: a: // @a
+; CHECK: // %bb.0:
+; CHECK-NEXT: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK-NOT: bl OUTLINED_FUNCTION_{{[0-9]+}}
+; CHECK: autibsp
+; CECK-NEXT: ret
+ ret void
+}
+
+define void @b() "sign-return-address"="all" "sign-return-address-key"="b_key" nounwind {
+; CHECK-LABEL: b: // @b
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: pacibsp
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: bl [[OUTLINED_FUNC:OUTLINED_FUNCTION_[0-9]+]]
+; CHECK: autibsp
+; CHECK-NEXT: ret
+ ret void
+}
+
+define void @c() "sign-return-address"="all" "sign-return-address-key"="b_key" nounwind {
+; CHECK-LABEL: c: // @c
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: pacibsp
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: bl [[OUTLINED_FUNC]]
+; CHECK: autibsp
+; CHECK-NEXT: ret
+ ret void
+}
+
+; CHECK: [[OUTLINED_FUNC]]
+; CHECK: // %bb.0:
+; CHECK-NEXT: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+; CHECK: autibsp
+; CHECK-NEXT: ret
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-diff-scope-same-key.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-diff-scope-same-key.ll
new file mode 100644
index 00000000000..d8acaa9cbfd
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-diff-scope-same-key.ll
@@ -0,0 +1,68 @@
+; RUN: llc -verify-machineinstrs -enable-machine-outliner -mtriple \
+; RUN: aarch64-arm-none-eabi %s -o - | FileCheck %s
+
+define void @a() "sign-return-address"="all" {
+; CHECK-LABEL: a: // @a
+; CHECK: paciasp
+; CHECK-NEXT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autiasp
+ ret void
+; CHECK: .cfi_endproc
+}
+
+define void @b() "sign-return-address"="non-leaf" {
+; CHECK-LABEL: b: // @b
+; CHECK-NOT: paciasp
+; CHECK-NOT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK-NOT: autiasp
+ ret void
+; CHECK: .cfi_endproc
+}
+
+define void @c() "sign-return-address"="all" {
+; CHECK-LABEL: c: // @c
+; CHECK: paciasp
+; CHECK-NEXT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autiasp
+ ret void
+; CHECK: .cfi_endproc
+}
+
+; CHECK-NOT: OUTLINED_FUNCTION_{{[0-9]+}}:
+; CHECK-NOT: // -- Begin function
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-non-leaf.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-non-leaf.ll
new file mode 100644
index 00000000000..c7cea17e7cf
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-non-leaf.ll
@@ -0,0 +1,72 @@
+; RUN: llc -verify-machineinstrs -enable-machine-outliner -mtriple \
+; RUN: aarch64-arm-none-eabi %s -o - | FileCheck %s
+
+define i64 @a(i64 %x) "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" {
+; CHECK-LABEL: a: // @a
+; CHECK: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+ call void asm sideeffect "mov x30, $0", "r,~{lr}"(i64 %x) #1
+ ret i64 %x
+}
+
+define i64 @b(i64 %x) "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" {
+; CHECK-LABEL: b: // @b
+; CHECK: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+ call void asm sideeffect "mov x30, $0", "r,~{lr}"(i64 %x) #1
+ ret i64 %x
+}
+
+define i64 @c(i64 %x) "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" {
+; CHECK-LABEL: c: // @c
+; CHECK: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+ call void asm sideeffect "mov x30, $0", "r,~{lr}"(i64 %x) #1
+ ret i64 %x
+}
+
+; Outlined function is leaf-function => don't sign it
+; CHECK-LABEL: OUTLINED_FUNCTION_0:
+; CHECK-NOT: .cfi_b_key_frame
+; CHECK-NOT: paci{{[a,b]}}sp
+; CHECK-NOT: .cfi_negate_ra_state
+; CHECK-NOT: auti{{[a,b]}}sp
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-regsave.mir b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-regsave.mir
new file mode 100644
index 00000000000..e65adce5c1b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-regsave.mir
@@ -0,0 +1,127 @@
+# RUN: llc -mtriple=aarch64-arm-none-eabi -run-pass=prologepilog \
+# RUN: -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s
+
+# Check that we save LR to a callee-saved register when possible.
+# foo() should use a callee-saved register. However, bar() should not.
+--- |
+
+ define void @foo() #0 {
+ ret void
+ }
+
+ define void @bar() #0 {
+ ret void
+ }
+
+ attributes #0 = { nounwind "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" minsize noinline noredzone "no-frame-pointer-elim"="true" }
+...
+---
+# CHECK-LABEL: name: foo
+# CHECK: bb.0:
+# CHECK: frame-setup EMITBKEY
+# CHECK-NEXT: frame-setup PACIBSP
+# CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
+# CHECK: bb.1:
+# CHECK: BL @[[OUTLINED_FUNCTION:OUTLINED_FUNCTION_[0-9]+]]
+# CHECK: bb.2:
+# CHECK: BL @[[OUTLINED_FUNCTION]]
+# CHECK: bb.3:
+# CHECK: BL @[[OUTLINED_FUNCTION]]
+# CHECK: bb.4:
+# CHECK: BL @[[OUTLINED_FUNCTION]]
+# CHECK: bb.5:
+# CHECK: frame-destroy AUTIBSP
+# CHECK-NEXT: RET
+name: foo
+tracksRegLiveness: true
+fixedStack:
+body: |
+ bb.0:
+ $x25 = ORRXri $xzr, 1
+ $lr = ORRXri $xzr, 1
+ bb.1:
+ liveins: $lr, $w9
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 2
+ bb.2:
+ liveins: $lr, $w9
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 2
+ bb.3:
+ liveins: $lr, $w9
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 2
+ bb.4:
+ liveins: $lr, $w9
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 2
+ bb.5:
+ liveins: $w9
+ RET undef $lr
+
+...
+---
+# CHECK: name: bar
+# CHECK: bb.0:
+# CHECK-NOT: OUTLINED_FUNCTION_
+# CHECK: bb.1:
+# CHECK-NOT: OUTLINED_FUNCTION_
+# CHECK: bb.2:
+# CHECK-NOT: OUTLINED_FUNCTION_
+# CHECK: bb.3:
+# CHECK-NOT: OUTLINED_FUNCTION_
+# CHECK: RET
+name: bar
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $lr, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x19, $x20, $x21, $x22, $x23, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w12 = ORRWri $wzr, 2
+ bb.1:
+ liveins: $lr, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x19, $x20, $x21, $x22, $x23, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w12 = ORRWri $wzr, 2
+ bb.2:
+ liveins: $lr, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x19, $x20, $x21, $x22, $x23, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w10 = ORRWri $wzr, 1
+ $w12 = ORRWri $wzr, 2
+ bb.3:
+ liveins: $lr, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x19, $x20, $x21, $x22, $x23, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28
+ RET undef $lr
+
+# CHECK: name: [[OUTLINED_FUNCTION]]
+# CHECK: body:
+# CHECK-NEXT: bb.0:
+# CHECK-NOT: frame-setup EMITBKEY
+# CHECK-NOT: frame-setup PACI{{[A,B]]}}SP
+# CHECK-NOT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
+# CHECK-NOT: frame-destroy AUTI{{[A,B]]}}SP
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-diff-key.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-diff-key.ll
new file mode 100644
index 00000000000..4348d737430
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-diff-key.ll
@@ -0,0 +1,69 @@
+; RUN: llc -verify-machineinstrs -enable-machine-outliner -mtriple \
+; RUN: aarch64-arm-none-eabi %s -o - | FileCheck %s
+
+define void @a() "sign-return-address"="all" {
+; CHECK-LABEL: a: // @a
+; CHECK: paciasp
+; CHECK-NEXT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autiasp
+ ret void
+; CHECK: .cfi_endproc
+}
+
+define void @b() "sign-return-address"="all" "sign-return-address-key"="b_key" {
+; CHECK-LABEL: b: // @b
+; CHECK: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK-NOT: autiasp
+ ret void
+; CHECK: .cfi_endproc
+}
+
+define void @c() "sign-return-address"="all" {
+; CHECK-LABEL: c: // @c
+; CHECK: paciasp
+; CHECK-NEXT: .cfi_negate_ra_state
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autiasp
+ ret void
+; CHECK: .cfi_endproc
+}
+
+; CHECK-NOT: OUTLINED_FUNCTION_0:
+; CHECK-NOT: // -- Begin function
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-same-key-a.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-same-key-a.ll
new file mode 100644
index 00000000000..f5e229a20ef
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-same-key-a.ll
@@ -0,0 +1,64 @@
+; RUN: llc -verify-machineinstrs -enable-machine-outliner -mtriple \
+; RUN: aarch64-arm-none-eabi %s -o - | FileCheck %s
+
+define void @a() "sign-return-address"="all" "sign-return-address-key"="a_key" nounwind {
+; CHECK-LABEL: a: // @a
+; CHECK: paciasp
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autiasp
+ ret void
+}
+
+define void @b() "sign-return-address"="all" nounwind {
+; CHECK-LABEL: b: // @b
+; CHECK: paciasp
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autiasp
+ ret void
+}
+
+define void @c() "sign-return-address"="all" nounwind {
+; CHECK-LABEL: c: // @c
+; CHECK: paciasp
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autiasp
+ ret void
+}
+
+; CHECK-LABEL: OUTLINED_FUNCTION_0:
+; CHECK: paciasp
+; CHECK: autiasp
+; CHECK-NEXT: ret
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-same-key-b.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-same-key-b.ll
new file mode 100644
index 00000000000..c1940b44d2d
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-same-key-b.ll
@@ -0,0 +1,70 @@
+; RUN: llc -verify-machineinstrs -enable-machine-outliner -mtriple \
+; RUN: aarch64-arm-none-eabi %s -o - | FileCheck %s
+
+define void @a() "sign-return-address"="all" "sign-return-address-key"="b_key" nounwind {
+; CHECK-LABEL: a: // @a
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: pacibsp
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autibsp
+ ret void
+}
+
+define void @b() "sign-return-address"="all" "sign-return-address-key"="b_key" nounwind {
+; CHECK-LABEL: b: // @b
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: pacibsp
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autibsp
+ ret void
+}
+
+define void @c() "sign-return-address"="all" "sign-return-address-key"="b_key" nounwind {
+; CHECK-LABEL: c: // @c
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: pacibsp
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autibsp
+ ret void
+}
+
+; CHECK-LABEL: OUTLINED_FUNCTION_0:
+; CHECK: // %bb.0:
+; CHECK-NEXT: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+; CHECK: autibsp
+; CHECK-NEXT: ret
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.mir b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.mir
new file mode 100644
index 00000000000..2645a6553ff
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.mir
@@ -0,0 +1,204 @@
+# RUN: llc -verify-machineinstrs -run-pass=machine-outliner %s -o - | FileCheck %s
+
+--- |
+ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+ target triple = "aarch64-arm-linux-gnu"
+
+ @v = common dso_local global i32* null, align 8
+
+ ; Function Attrs: nounwind
+ define dso_local void @legal0() #0 {
+ %1 = alloca i32, align 4
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+ define dso_local void @legal1() #0 {
+ %1 = alloca i32, align 4
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+ define dso_local void @illegal0() #0 {
+ %1 = alloca i32, align 4
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ ret void
+ }
+
+ ; Function Attrs: nounwind
+ define dso_local void @illegal1() #0 {
+ %1 = alloca i32, align 4
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ store volatile i32* %1, i32** @v, align 8
+ ret void
+ }
+
+ attributes #0 = { nounwind "sign-return-address"="all" "sign-return-address-key"="a_key" noinline noredzone "no-frame-pointer-elim"="true" }
+
+...
+---
+name: legal0
+tracksRegLiveness: true
+body: |
+ bb.0 (%ir-block.0):
+ liveins: $lr
+ frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
+ frame-setup CFI_INSTRUCTION negate_ra_sign_state
+ $sp = frame-setup SUBXri $sp, 16, 0
+ renamable $x8 = ADRP target-flags(aarch64-page) @v
+ $x9 = ADDXri $sp, 12, 0
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui killed renamable $x9, killed renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ $sp = frame-destroy ADDXri $sp, 16, 0
+ frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
+ RET undef $lr
+
+# CHECK-LABEL: name: legal0
+# CHECK: body: |
+# CHECK-NEXT: bb.0 (%ir-block.0):
+# CHECK-NEXT: liveins: $lr
+# CHECK: frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
+# CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
+# CHECK: BL @[[OUTLINED_FUNC:OUTLINED_FUNCTION_[0-9]+]]
+# CHECK: frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
+# CHECK-NEXT: RET undef $lr
+
+...
+---
+name: legal1
+tracksRegLiveness: true
+body: |
+ bb.0 (%ir-block.0):
+ liveins: $lr
+ frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
+ frame-setup CFI_INSTRUCTION negate_ra_sign_state
+ $sp = frame-setup SUBXri $sp, 16, 0
+ renamable $x8 = ADRP target-flags(aarch64-page) @v
+ $x9 = ADDXri $sp, 12, 0
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui killed renamable $x9, killed renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ $sp = frame-destroy ADDXri $sp, 16, 0
+ frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
+ RET undef $lr
+
+# CHECK-LABEL: name: legal1
+# CHECK: body: |
+# CHECK-NEXT: bb.0 (%ir-block.0):
+# CHECK-NEXT: liveins: $lr
+# CHECK: frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
+# CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
+# CHECK: BL @[[OUTLINED_FUNC]]
+# CHECK: frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
+# CHECK-NEXT: RET undef $lr
+
+...
+---
+name: illegal0
+tracksRegLiveness: true
+body: |
+ bb.0 (%ir-block.0):
+ liveins: $lr
+ frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
+ frame-setup CFI_INSTRUCTION negate_ra_sign_state
+ $sp = frame-setup SUBXri $sp, 16, 0
+ renamable $x8 = ADRP target-flags(aarch64-page) @v
+ $x9 = ADDXri $sp, 12, 0
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui killed renamable $x9, killed renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ $sp = frame-destroy ADDXri $sp, 12, 0
+ frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
+ RET undef $lr
+
+...
+---
+name: illegal1
+tracksRegLiveness: true
+body: |
+ bb.0 (%ir-block.0):
+ liveins: $lr
+ frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
+ frame-setup CFI_INSTRUCTION negate_ra_sign_state
+ $sp = frame-setup SUBXri $sp, 16, 0
+ renamable $x8 = ADRP target-flags(aarch64-page) @v
+ $x9 = ADDXri $sp, 12, 0
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui renamable $x9, renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ STRXui killed renamable $x9, killed renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) @v :: (volatile store 8 into @v)
+ $sp = frame-destroy ADDXri $sp, 12, 0
+ frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
+ RET undef $lr
+
+# CHECK-LABEL: name: illegal0
+# CHECK: body: |
+# CHECK-NEXT: bb.0 (%ir-block.0):
+# CHECK-NEXT: liveins: $lr
+# CHECK: frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
+# CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
+# CHECK-NOT: BL @OUTLINED_FUNCTION_{{.*}}
+# CHECK: frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
+# CHECK-NEXT: RET undef $lr
+
+# CHECK-LABEL: name: illegal1
+# CHECK: body: |
+# CHECK-NEXT: bb.0 (%ir-block.0):
+# CHECK-NEXT: liveins: $lr
+# CHECK: frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp
+# CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
+# CHECK-NOT: BL @OUTLINED_FUNCTION_{{.*}}
+# CHECK: frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp
+# CHECK-NEXT: RET undef $lr
+
+# Outlined function that contains only legal sp modifications
+# CHECK: name: [[OUTLINED_FUNC]]
+# CHECK: body: |
+# CHECK-NEXT: bb.0:
+# CHECK-NEXT: frame-setup PACIASP implicit-def $lr, implicit $lr, implicit $sp
+# CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
+# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
+# CHECK: $sp = frame-destroy ADDXri $sp, 16, 0
+# CHECK-NEXT: frame-destroy AUTIASP implicit-def $lr, implicit $lr, implicit $sp
+# CHECK-NEXT: RET undef $lr
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-subtarget.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-subtarget.ll
new file mode 100644
index 00000000000..c2bb291506a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-subtarget.ll
@@ -0,0 +1,87 @@
+; RUN: llc -verify-machineinstrs -enable-machine-outliner -mtriple \
+; RUN: aarch64-arm-linux-gnu %s -o - | FileCheck %s
+
+; Check that functions that should sign their return addresses don't get
+; outlined if not all of the function either support v8.3a features or all of
+; the functions don't!!
+
+define void @a() #0 {
+; CHECK-LABEL: a: // @a
+; CHECK: // %bb.0:
+; CHECK-NEXT: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+; CHECK-NOT: OUTLINED_FUNCTION_
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: retab
+; CHECK-NOT: auti[a,b]sp
+ ret void
+}
+
+define void @b() #0 {
+; CHECK-LABEL: b: // @b
+; CHECK: // %bb.0:
+; CHECK-NEXT: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+; CHECK-NOT: OUTLINED_FUNCTION_
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: retab
+; CHECK-NOT: auti[a,b]sp
+ ret void
+}
+
+define void @c() #1 {
+; CHECK-LABEL: c: // @c
+; CHECK: // %bb.0:
+; CHECK-NEXT: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK-NEXT: .cfi_negate_ra_state
+; CHECK-NOT: OUTLINED_FUNCTION_
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: autibsp
+; CHECK-NOT: ret{{[a,b]}}
+ ret void
+}
+
+attributes #0 = { "sign-return-address"="all"
+ "sign-return-address-key"="b_key"
+ "target-features"="+v8.3a" }
+
+attributes #1 = { "sign-return-address"="all"
+ "sign-return-address-key"="b_key" }
+
+; CHECK-NOT: OUTLINED_FUNCTION_
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-thunk.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-thunk.ll
new file mode 100644
index 00000000000..d76dc5ef8a8
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-thunk.ll
@@ -0,0 +1,63 @@
+; RUN: llc -mtriple aarch64-arm-linux-gnu --enable-machine-outliner \
+; RUN: -verify-machineinstrs %s -o - | FileCheck %s
+
+declare i32 @thunk_called_fn(i32, i32, i32, i32)
+
+define i32 @a() #0 {
+; CHECK-LABEL: a: // @a
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: paciasp
+; CHECK: autiasp
+; CHECK-NEXT: ret
+entry:
+ %call = tail call i32 @thunk_called_fn(i32 1, i32 2, i32 3, i32 4)
+ %cx = add i32 %call, 8
+ ret i32 %cx
+}
+
+define i32 @b() #0 {
+; CHECK-LABEL: b: // @b
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: paciasp
+; CHECK-NEXT: .cfi_negate_ra_state
+; CHECK: autiasp
+; CHECK-NEXT: ret
+entry:
+ %call = tail call i32 @thunk_called_fn(i32 1, i32 2, i32 3, i32 4)
+ %cx = add i32 %call, 88
+ ret i32 %cx
+}
+
+define hidden i32 @c(i32 (i32, i32, i32, i32)* %fptr) #0 {
+; CHECK-LABEL: c: // @c
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: paciasp
+; CHECK-NEXT: .cfi_negate_ra_state
+; CHECK: autiasp
+; CHECK-NEXT: ret
+entry:
+ %call = tail call i32 %fptr(i32 1, i32 2, i32 3, i32 4)
+ %add = add nsw i32 %call, 8
+ ret i32 %add
+}
+
+define hidden i32 @d(i32 (i32, i32, i32, i32)* %fptr) #0 {
+; CHECK-LABEL: d: // @d
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: paciasp
+; CHECK-NEXT: .cfi_negate_ra_state
+; CHECK: autiasp
+; CHECK-NEXT: ret
+entry:
+ %call = tail call i32 %fptr(i32 1, i32 2, i32 3, i32 4)
+ %add = add nsw i32 %call, 88
+ ret i32 %add
+}
+
+attributes #0 = { "sign-return-address"="non-leaf" }
+
+; CHECK-NOT: [[OUTLINED_FUNCTION_{{.*}}]]
+; CHECK-NOT: .cfi_b_key_frame
+; CHECK-NOT: paci{{[a,b]}}sp
+; CHECK-NOT: .cfi_negate_ra_state
+; CHECK-NOT: auti{{[a,b]}}sp
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-v8-3.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-v8-3.ll
new file mode 100644
index 00000000000..05f4dc2e8c2
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-v8-3.ll
@@ -0,0 +1,83 @@
+; RUN: llc -verify-machineinstrs -enable-machine-outliner -mtriple \
+; RUN: aarch64-arm-linux-gnu %s -o - | FileCheck %s
+
+; Check that outlined functions use the dedicated RETAA/RETAB instructions
+; to sign their return address if available.
+
+define void @a() #0 {
+; CHECK-LABEL: a: // @a
+; CHECK: // %bb.0:
+; CHECK-NEXT: pacibsp
+; CHECK: bl [[OUTLINED_FUNC:OUTLINED_FUNCTION_[0-9]+]]
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: retab
+; CHECK-NOT: auti[a,b]sp
+ ret void
+}
+
+define void @b() #0 {
+; CHECK-LABEL: b: // @b
+; CHECK: // %bb.0:
+; CHECK-NEXT: pacibsp
+; CHECK: bl OUTLINED_FUNC
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: retab
+; CHECK-NOT: auti[a,b]sp
+ ret void
+}
+
+define void @c() #0 {
+; CHECK-LABEL: c: // @c
+; CHECK: // %bb.0:
+; CHECK-NEXT: pacibsp
+; CHECK: bl OUTLINED_FUNC
+ %1 = alloca i32, align 4
+ %2 = alloca i32, align 4
+ %3 = alloca i32, align 4
+ %4 = alloca i32, align 4
+ %5 = alloca i32, align 4
+ %6 = alloca i32, align 4
+ store i32 1, i32* %1, align 4
+ store i32 2, i32* %2, align 4
+ store i32 3, i32* %3, align 4
+ store i32 4, i32* %4, align 4
+ store i32 5, i32* %5, align 4
+ store i32 6, i32* %6, align 4
+; CHECK: retab
+; CHECK-NOT: auti[a,b]sp
+ ret void
+}
+
+attributes #0 = { "sign-return-address"="all"
+ "sign-return-address-key"="b_key"
+ "target-features"="+v8.3a"
+ nounwind }
+
+; CHECK: OUTLINED_FUNC
+; CHECK: // %bb.0:
+; CHECK-NEXT: .cfi_b_key_frame
+; CHECK-NEXT: pacibsp
+; CHECK: retab
+; CHECK-NOT: auti[a,b]sp
OpenPOWER on IntegriCloud