xref: /llvm-project/llvm/test/CodeGen/AArch64/cond-br-tuning.ll (revision 78f2eb8d0f9cf5e8a79b64f6d64deeb487502e38)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -debugify-and-strip-all-safe < %s -O3 -mtriple=aarch64 -verify-machineinstrs | FileCheck %s
3
4target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
5target triple = "aarch64"
6
7; CMN is an alias of ADDS.
8
9define void @test_add_cbz(i32 %a, i32 %b, ptr %ptr) {
10; CHECK-LABEL: test_add_cbz:
11; CHECK:       // %bb.0: // %common.ret
12; CHECK-NEXT:    cmn w0, w1
13; CHECK-NEXT:    cset w8, eq
14; CHECK-NEXT:    str w8, [x2]
15; CHECK-NEXT:    ret
16  %c = add nsw i32 %a, %b
17  %d = icmp ne i32 %c, 0
18  br i1 %d, label %L1, label %L2
19L1:
20  store i32 0, ptr %ptr, align 4
21  ret void
22L2:
23  store i32 1, ptr %ptr, align 4
24  ret void
25}
26
27define void @test_add_cbz_multiple_use(i32 %a, i32 %b, ptr %ptr) {
28; CHECK-LABEL: test_add_cbz_multiple_use:
29; CHECK:       // %bb.0: // %common.ret
30; CHECK-NEXT:    adds w8, w0, w1
31; CHECK-NEXT:    mov w9, #10 // =0xa
32; CHECK-NEXT:    csel w8, w9, w8, ne
33; CHECK-NEXT:    str w8, [x2]
34; CHECK-NEXT:    ret
35  %c = add nsw i32 %a, %b
36  %d = icmp ne i32 %c, 0
37  br i1 %d, label %L1, label %L2
38L1:
39  store i32 10, ptr %ptr, align 4
40  ret void
41L2:
42  store i32 %c, ptr %ptr, align 4
43  ret void
44}
45
46define void @test_add_cbz_64(i64 %a, i64 %b, ptr %ptr) {
47; CHECK-LABEL: test_add_cbz_64:
48; CHECK:       // %bb.0: // %common.ret
49; CHECK-NEXT:    cmn x0, x1
50; CHECK-NEXT:    cset w8, eq
51; CHECK-NEXT:    str x8, [x2]
52; CHECK-NEXT:    ret
53  %c = add nsw i64 %a, %b
54  %d = icmp ne i64 %c, 0
55  br i1 %d, label %L1, label %L2
56L1:
57  store i64 0, ptr %ptr, align 4
58  ret void
59L2:
60  store i64 1, ptr %ptr, align 4
61  ret void
62}
63
64define void @test_and_cbz(i32 %a, ptr %ptr) {
65; CHECK-LABEL: test_and_cbz:
66; CHECK:       // %bb.0: // %common.ret
67; CHECK-NEXT:    tst w0, #0x6
68; CHECK-NEXT:    cset w8, eq
69; CHECK-NEXT:    str w8, [x1]
70; CHECK-NEXT:    ret
71  %c = and i32 %a, 6
72  %d = icmp ne i32 %c, 0
73  br i1 %d, label %L1, label %L2
74L1:
75  store i32 0, ptr %ptr, align 4
76  ret void
77L2:
78  store i32 1, ptr %ptr, align 4
79  ret void
80}
81
82define void @test_bic_cbnz(i32 %a, i32 %b, ptr %ptr) {
83; CHECK-LABEL: test_bic_cbnz:
84; CHECK:       // %bb.0: // %common.ret
85; CHECK-NEXT:    bics wzr, w1, w0
86; CHECK-NEXT:    cset w8, ne
87; CHECK-NEXT:    str w8, [x2]
88; CHECK-NEXT:    ret
89  %c = and i32 %a, %b
90  %d = icmp eq i32 %c, %b
91  br i1 %d, label %L1, label %L2
92L1:
93  store i32 0, ptr %ptr, align 4
94  ret void
95L2:
96  store i32 1, ptr %ptr, align 4
97  ret void
98}
99
100define void @test_add_tbz(i32 %a, i32 %b, ptr %ptr) {
101; CHECK-LABEL: test_add_tbz:
102; CHECK:       // %bb.0: // %entry
103; CHECK-NEXT:    adds w8, w0, w1
104; CHECK-NEXT:    b.pl .LBB5_2
105; CHECK-NEXT:  // %bb.1: // %L1
106; CHECK-NEXT:    str w8, [x2]
107; CHECK-NEXT:  .LBB5_2: // %L2
108; CHECK-NEXT:    ret
109entry:
110  %add = add nsw i32 %a, %b
111  %cmp36 = icmp sge i32 %add, 0
112  br i1 %cmp36, label %L2, label %L1
113L1:
114  store i32 %add, ptr %ptr, align 8
115  br label %L2
116L2:
117  ret void
118}
119
120define void @test_subs_tbz(i32 %a, i32 %b, ptr %ptr) {
121; CHECK-LABEL: test_subs_tbz:
122; CHECK:       // %bb.0: // %entry
123; CHECK-NEXT:    subs w8, w0, w1
124; CHECK-NEXT:    b.pl .LBB6_2
125; CHECK-NEXT:  // %bb.1: // %L1
126; CHECK-NEXT:    str w8, [x2]
127; CHECK-NEXT:  .LBB6_2: // %L2
128; CHECK-NEXT:    ret
129entry:
130  %sub = sub nsw i32 %a, %b
131  %cmp36 = icmp sge i32 %sub, 0
132  br i1 %cmp36, label %L2, label %L1
133L1:
134  store i32 %sub, ptr %ptr, align 8
135  br label %L2
136L2:
137  ret void
138}
139
140define void @test_add_tbnz(i32 %a, i32 %b, ptr %ptr) {
141; CHECK-LABEL: test_add_tbnz:
142; CHECK:       // %bb.0: // %entry
143; CHECK-NEXT:    adds w8, w0, w1
144; CHECK-NEXT:    b.mi .LBB7_2
145; CHECK-NEXT:  // %bb.1: // %L1
146; CHECK-NEXT:    str w8, [x2]
147; CHECK-NEXT:  .LBB7_2: // %L2
148; CHECK-NEXT:    ret
149entry:
150  %add = add nsw i32 %a, %b
151  %cmp36 = icmp slt i32 %add, 0
152  br i1 %cmp36, label %L2, label %L1
153L1:
154  store i32 %add, ptr %ptr, align 8
155  br label %L2
156L2:
157  ret void
158}
159
160define void @test_subs_tbnz(i32 %a, i32 %b, ptr %ptr) {
161; CHECK-LABEL: test_subs_tbnz:
162; CHECK:       // %bb.0: // %entry
163; CHECK-NEXT:    subs w8, w0, w1
164; CHECK-NEXT:    b.mi .LBB8_2
165; CHECK-NEXT:  // %bb.1: // %L1
166; CHECK-NEXT:    str w8, [x2]
167; CHECK-NEXT:  .LBB8_2: // %L2
168; CHECK-NEXT:    ret
169entry:
170  %sub = sub nsw i32 %a, %b
171  %cmp36 = icmp slt i32 %sub, 0
172  br i1 %cmp36, label %L2, label %L1
173L1:
174  store i32 %sub, ptr %ptr, align 8
175  br label %L2
176L2:
177  ret void
178}
179
180declare void @foo()
181declare void @bar(i32)
182
183; Don't transform since the call will clobber the NZCV bits.
184define void @test_call_clobber(i32 %unused, i32 %a) uwtable {
185; CHECK-LABEL: test_call_clobber:
186; CHECK:       // %bb.0: // %entry
187; CHECK-NEXT:    stp x30, x19, [sp, #-16]! // 16-byte Folded Spill
188; CHECK-NEXT:    .cfi_def_cfa_offset 16
189; CHECK-NEXT:    .cfi_offset w19, -8
190; CHECK-NEXT:    .cfi_offset w30, -16
191; CHECK-NEXT:    .cfi_remember_state
192; CHECK-NEXT:    and w19, w1, #0x6
193; CHECK-NEXT:    mov w0, w19
194; CHECK-NEXT:    bl bar
195; CHECK-NEXT:    cbnz w19, .LBB9_2
196; CHECK-NEXT:  // %bb.1: // %if.end
197; CHECK-NEXT:    ldp x30, x19, [sp], #16 // 16-byte Folded Reload
198; CHECK-NEXT:    .cfi_def_cfa_offset 0
199; CHECK-NEXT:    .cfi_restore w19
200; CHECK-NEXT:    .cfi_restore w30
201; CHECK-NEXT:    ret
202; CHECK-NEXT:  .LBB9_2: // %if.then
203; CHECK-NEXT:    .cfi_restore_state
204; CHECK-NEXT:    bl foo
205entry:
206  %c = and i32 %a, 6
207  call void @bar(i32 %c)
208  %tobool = icmp eq i32 %c, 0
209  br i1 %tobool, label %if.end, label %if.then
210
211if.then:
212  tail call void @foo()
213  unreachable
214
215if.end:
216  ret void
217}
218