1 ; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,SLH,NOGISELSLH --dump-input-on-failure
2 ; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,NOSLH,NOGISELNOSLH --dump-input-on-failure
3 ; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,SLH,GISELSLH --dump-input-on-failure
4 ; RUN sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,NOSLH,GISELNOSLH --dump-input-on-failure
5 ; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,SLH,NOGISELSLH --dump-input-on-failure
6 ; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,NOSLH,NOGISELNOSLH --dump-input-on-failure
8 define i32 @f(i8* nocapture readonly %p, i32 %i, i32 %N) local_unnamed_addr SLHATTR {
13 ; NOSLH-NOT: cmp sp, #0
14 ; NOSLH-NOT: csetm x16, ne
16 ; SLH: mov [[TMPREG:x[0-9]+]], sp
17 ; SLH: and [[TMPREG]], [[TMPREG]], x16
18 ; SLH: mov sp, [[TMPREG]]
19 ; NOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp
20 ; NOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16
21 ; NOSLH-NOT: mov sp, [[TMPREG]]
22 %call = tail call i32 @tail_callee(i32 %i)
25 ; NOSLH-NOT: cmp sp, #0
26 ; NOSLH-NOT: csetm x16, ne
27 %cmp = icmp slt i32 %call, %N
28 br i1 %cmp, label %if.then, label %return
29 ; CHECK: b.[[COND:(ge)|(lt)|(ne)|(eq)]]
31 if.then: ; preds = %entry
32 ; NOSLH-NOT: csel x16, x16, xzr, {{(lt)|(ge)|(eq)|(ne)}}
33 ; SLH-DAG: csel x16, x16, xzr, {{(lt)|(ge)|(eq)|(ne)}}
34 %idxprom = sext i32 %i to i64
35 %arrayidx = getelementptr inbounds i8, i8* %p, i64 %idxprom
36 %0 = load i8, i8* %arrayidx, align 1
37 ; CHECK-DAG: ldrb [[LOADED:w[0-9]+]],
38 %conv = zext i8 %0 to i32
41 ; SLH-DAG: csel x16, x16, xzr, [[COND]]
42 ; NOSLH-NOT: csel x16, x16, xzr, [[COND]]
43 return: ; preds = %entry, %if.then
44 %retval.0 = phi i32 [ %conv, %if.then ], [ 0, %entry ]
45 ; SLH: mov [[TMPREG:x[0-9]+]], sp
46 ; SLH: and [[TMPREG]], [[TMPREG]], x16
47 ; SLH: mov sp, [[TMPREG]]
48 ; NOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp
49 ; NOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16
50 ; NOSLH-NOT: mov sp, [[TMPREG]]
54 ; Make sure that for a tail call, taint doesn't get put into SP twice.
55 define i32 @tail_caller(i32 %a) local_unnamed_addr SLHATTR {
56 ; CHECK-LABEL: tail_caller:
57 ; NOGISELSLH: mov [[TMPREG:x[0-9]+]], sp
58 ; NOGISELSLH: and [[TMPREG]], [[TMPREG]], x16
59 ; NOGISELSLH: mov sp, [[TMPREG]]
60 ; NOGISELNOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp
61 ; NOGISELNOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16
62 ; NOGISELNOSLH-NOT: mov sp, [[TMPREG]]
63 ; GISELSLH: mov [[TMPREG:x[0-9]+]], sp
64 ; GISELSLH: and [[TMPREG]], [[TMPREG]], x16
65 ; GISELSLH: mov sp, [[TMPREG]]
66 ; GISELNOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp
67 ; GISELNOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16
68 ; GISELNOSLH-NOT: mov sp, [[TMPREG]]
69 ; GlobalISel doesn't optimize tail calls (yet?), so only check that
70 ; cross-call taint register setup code is missing if a tail call was
72 ; NOGISELSLH: b tail_callee
73 ; GISELSLH: bl tail_callee
74 ; GISELSLH: cmp sp, #0
76 %call = tail call i32 @tail_callee(i32 %a)
80 declare i32 @tail_callee(i32) local_unnamed_addr
82 ; Verify that no cb(n)z/tb(n)z instructions are produced when implementing
84 define i32 @compare_branch_zero(i32, i32) SLHATTR {
85 ; CHECK-LABEL: compare_branch_zero
86 %3 = icmp eq i32 %0, 0
87 br i1 %3, label %then, label %else
98 define i32 @test_branch_zero(i32, i32) SLHATTR {
99 ; CHECK-LABEL: test_branch_zero
101 %4 = icmp eq i32 %3, 0
102 br i1 %4, label %then, label %else
113 define i32 @landingpad(i32 %l0, i32 %l1) SLHATTR personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
114 ; CHECK-LABEL: landingpad
118 ; NOSLH-NOT: cmp sp, #0
119 ; NOSLH-NOT: csetm x16, ne
120 ; CHECK: bl _Z10throwing_fv
121 invoke void @_Z10throwing_fv()
122 to label %exit unwind label %lpad
127 %l4 = landingpad { i8*, i32 }
131 ; NOSLH-NOT: cmp sp, #0
132 ; NOSLH-NOT: csetm x16, ne
133 %l5 = extractvalue { i8*, i32 } %l4, 0
134 %l6 = tail call i8* @__cxa_begin_catch(i8* %l5)
135 %l7 = icmp sgt i32 %l0, %l1
136 br i1 %l7, label %then, label %else
137 ; GlobalISel lowers the branch to a b.ne sometimes instead of b.ge as expected..
138 ; CHECK: b.[[COND:(le)|(gt)|(ne)|(eq)]]
141 ; SLH-DAG: csel x16, x16, xzr, [[COND]]
142 %l9 = sdiv i32 %l0, %l1
146 ; SLH-DAG: csel x16, x16, xzr, {{(gt)|(le)|(eq)|(ne)}}
147 %l11 = sdiv i32 %l1, %l0
151 %l13 = phi i32 [ %l9, %then ], [ %l11, %else ]
152 tail call void @__cxa_end_catch()
156 %l15 = phi i32 [ %l13, %postif ], [ 0, %entry ]
160 declare i32 @__gxx_personality_v0(...)
161 declare void @_Z10throwing_fv() local_unnamed_addr
162 declare i8* @__cxa_begin_catch(i8*) local_unnamed_addr
163 declare void @__cxa_end_catch() local_unnamed_addr