1; RUN: split-file %s %t
2; RUN: cat %t/main.ll %t/a.ll > %t/a2.ll
3; RUN: cat %t/main.ll %t/b.ll > %t/b2.ll
4; RUN: cat %t/main.ll %t/c.ll > %t/c2.ll
5; RUN: cat %t/main.ll %t/d.ll > %t/d2.ll
6; RUN: cat %t/main.ll %t/e.ll > %t/e2.ll
7; RUN: cat %t/main.ll %t/f.ll > %t/f2.ll
8; RUN: cat %t/main.ll %t/g.ll > %t/g2.ll
9; RUN: cat %t/main.ll %t/h.ll > %t/h2.ll
10; RUN: cat %t/main.ll %t/i.ll > %t/i2.ll
11; RUN: cat %t/main.ll %t/j.ll > %t/j2.ll
12; RUN: llc %t/a2.ll -verify-machineinstrs -o - | \
13; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NO-OFFSET %s
14; RUN: llc %t/b2.ll -verify-machineinstrs -o - | \
15; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-POSITIVE-OFFSET %s
16; RUN: llc %t/c2.ll -verify-machineinstrs -o - | \
17; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NEGATIVE-OFFSET %s
18; RUN: llc %t/d2.ll -verify-machineinstrs -o - | \
19; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NPOT-OFFSET %s
20; RUN: llc %t/e2.ll -verify-machineinstrs -o - | \
21; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NPOT-NEG-OFFSET %s
22; RUN: llc %t/f2.ll -verify-machineinstrs -o - | \
23; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-257-OFFSET %s
24; RUN: llc %t/g2.ll -verify-machineinstrs -o - | \
25; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-MINUS-257-OFFSET %s
26
27; XFAIL
28; RUN: not --crash llc %t/h2.ll -o - 2>&1 | \
29; RUN: FileCheck --check-prefix=CHECK-BAD-OFFSET %s
30; RUN: not --crash llc %t/i2.ll -o - 2>&1 | \
31; RUN: FileCheck --check-prefix=CHECK-BAD-OFFSET %s
32; RUN: not --crash llc %t/j2.ll -o - 2>&1 | \
33; RUN: FileCheck --check-prefix=CHECK-BAD-OFFSET %s
34
35;--- main.ll
36
37target triple = "aarch64-unknown-linux-gnu"
38
39; Verify that we `mrs` from `SP_EL0` twice, rather than load from
40; __stack_chk_guard.
41define dso_local void @foo(i64 %t) local_unnamed_addr #0 {
42; CHECK-LABEL:   foo:
43; CHECK:         // %bb.0: // %entry
44; CHECK-NEXT:    stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
45; CHECK-NEXT:    .cfi_def_cfa_offset 16
46; CHECK-NEXT:    mov x29, sp
47; CHECK-NEXT:    .cfi_def_cfa w29, 16
48; CHECK-NEXT:    .cfi_offset w30, -8
49; CHECK-NEXT:    .cfi_offset w29, -16
50; CHECK-NEXT:    .cfi_remember_state
51; CHECK-NEXT:    sub sp, sp, #16
52; CHECK-NEXT:    mrs x8, SP_EL0
53; CHECK-NEXT:    lsl x9, x0, #2
54; CHECK-NO-OFFSET:       ldr x8, [x8]
55; CHECK-POSITIVE-OFFSET: ldr x8, [x8, #8]
56; CHECK-NEGATIVE-OFFSET: ldur x8, [x8, #-8]
57; CHECK-NPOT-OFFSET:     ldur x8, [x8, #1]
58; CHECK-NPOT-NEG-OFFSET: ldur x8, [x8, #-1]
59; CHECK-257-OFFSET:      add x8, x8, #257
60; CHECK-MINUS-257-OFFSET:      sub x8, x8, #257
61; CHECK-NEXT:    add x9, x9, #15
62; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
63; CHECK-257-OFFSET-NEXT: ldr x8, [x8]
64; CHECK-MINUS-257-OFFSET-NEXT: ldr x8, [x8]
65; CHECK-NEXT:    stur x8, [x29, #-8]
66; CHECK-NEXT:    mov x8, sp
67; CHECK-NEXT:    sub x0, x8, x9
68; CHECK-NEXT:    mov sp, x0
69; CHECK-NEXT:    bl baz
70; CHECK-NEXT:    mrs x8, SP_EL0
71; CHECK-NO-OFFSET:       ldr x8, [x8]
72; CHECK-POSITIVE-OFFSET: ldr x8, [x8, #8]
73; CHECK-NEGATIVE-OFFSET: ldur x8, [x8, #-8]
74; CHECK-NPOT-OFFSET:     ldur x8, [x8, #1]
75; CHECK-NPOT-NEG-OFFSET: ldur x8, [x8, #-1]
76; CHECK-257-OFFSET:      add x8, x8, #257
77; CHECK-257-OFFSET-NEXT: ldr x8, [x8]
78; CHECK-MINUS-257-OFFSET:      sub x8, x8, #257
79; CHECK-MINUS-257-OFFSET-NEXT: ldr x8, [x8]
80; CHECK-NEXT:    ldur x9, [x29, #-8]
81; CHECK-NEXT:    cmp x8, x9
82; CHECK-NEXT:    b.ne .LBB0_2
83; CHECK-NEXT:  // %bb.1: // %entry
84; CHECK-NEXT:    mov sp, x29
85; CHECK-NEXT:    .cfi_def_cfa wsp, 16
86; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
87; CHECK-NEXT:   .cfi_def_cfa_offset 0
88; CHECK-NEXT:   .cfi_restore w30
89; CHECK-NEXT:   .cfi_restore w29
90; CHECK-NEXT:    ret
91; CHECK-NEXT:  .LBB0_2: // %entry
92; CHECK-NEXT:   .cfi_restore_state
93; CHECK-NEXT:    bl __stack_chk_fail
94; CHECK-NOT: __stack_chk_guard
95entry:
96  %vla = alloca i32, i64 %t, align 4
97  call void @baz(i32* nonnull %vla)
98  ret void
99}
100
101declare void @baz(i32*)
102
103; CHECK-BAD-OFFSET: LLVM ERROR: Unable to encode Stack Protector Guard Offset
104
105attributes #0 = { sspstrong uwtable }
106!llvm.module.flags = !{!1, !2, !3}
107
108!1 = !{i32 2, !"stack-protector-guard", !"sysreg"}
109!2 = !{i32 2, !"stack-protector-guard-reg", !"sp_el0"}
110
111;--- a.ll
112!3 = !{i32 2, !"stack-protector-guard-offset", i32 0}
113;--- b.ll
114!3 = !{i32 2, !"stack-protector-guard-offset", i32 8}
115;--- c.ll
116!3 = !{i32 2, !"stack-protector-guard-offset", i32 -8}
117;--- d.ll
118!3 = !{i32 2, !"stack-protector-guard-offset", i32 1}
119;--- e.ll
120!3 = !{i32 2, !"stack-protector-guard-offset", i32 -1}
121;--- f.ll
122!3 = !{i32 2, !"stack-protector-guard-offset", i32 257}
123;--- g.ll
124!3 = !{i32 2, !"stack-protector-guard-offset", i32 -257}
125;--- h.ll
126!3 = !{i32 2, !"stack-protector-guard-offset", i32 32761}
127;--- i.ll
128!3 = !{i32 2, !"stack-protector-guard-offset", i32 -4096}
129;--- j.ll
130!3 = !{i32 2, !"stack-protector-guard-offset", i32 4097}
131