1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2 ; RUN: opt < %s -mtriple=aarch64-unknown-linux-gnu -mattr=+sme -S -passes=inline | FileCheck %s
4 declare i32 @llvm.vscale.i32()
6 ; Define some functions that merely call llvm.vscale.i32(), which will be called
7 ; by the other functions below. If we see the call to one of these functions
8 ; being replaced by 'llvm.vscale()', then we know it has been inlined.
10 define i32 @normal_callee() {
11 ; CHECK-LABEL: define i32 @normal_callee
12 ; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
14 ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32()
15 ; CHECK-NEXT: ret i32 [[RES]]
18 %res = call i32 @llvm.vscale.i32()
22 define i32 @streaming_callee() "aarch64_pstate_sm_enabled" {
23 ; CHECK-LABEL: define i32 @streaming_callee
24 ; CHECK-SAME: () #[[ATTR2:[0-9]+]] {
26 ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32()
27 ; CHECK-NEXT: ret i32 [[RES]]
30 %res = call i32 @llvm.vscale.i32()
34 define i32 @locally_streaming_callee() "aarch64_pstate_sm_body" {
35 ; CHECK-LABEL: define i32 @locally_streaming_callee
36 ; CHECK-SAME: () #[[ATTR3:[0-9]+]] {
38 ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32()
39 ; CHECK-NEXT: ret i32 [[RES]]
42 %res = call i32 @llvm.vscale.i32()
46 define i32 @streaming_compatible_callee() "aarch64_pstate_sm_compatible" {
47 ; CHECK-LABEL: define i32 @streaming_compatible_callee
48 ; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
50 ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32()
51 ; CHECK-NEXT: ret i32 [[RES]]
54 %res = call i32 @llvm.vscale.i32()
58 define i32 @streaming_compatible_locally_streaming_callee() "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" {
59 ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_callee
60 ; CHECK-SAME: () #[[ATTR4:[0-9]+]] {
62 ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32()
63 ; CHECK-NEXT: ret i32 [[RES]]
66 %res = call i32 @llvm.vscale()
70 ; Now test that inlining only happens when their streaming modes match.
71 ; Test for a number of combinations, where:
72 ; N Normal-interface (PSTATE.SM=0 on entry/exit)
73 ; S Streaming-interface (PSTATE.SM=1 on entry/exit)
74 ; SC Streaming-compatible interface
75 ; (PSTATE.SM=0 or 1, unchanged on exit)
76 ; N + B Normal-interface, streaming body
77 ; (PSTATE.SM=0 on entry/exit, but 1 within the body of the function)
78 ; SC + B Streaming-compatible-interface, streaming body
79 ; (PSTATE.SM=0 or 1 on entry, unchanged on exit,
80 ; but guaranteed to be 1 within the body of the function)
87 define i32 @normal_caller_normal_callee_inline() {
88 ; CHECK-LABEL: define i32 @normal_caller_normal_callee_inline
89 ; CHECK-SAME: () #[[ATTR1]] {
91 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
92 ; CHECK-NEXT: ret i32 [[RES_I]]
95 %res = call i32 @normal_callee()
104 define i32 @normal_caller_streaming_callee_dont_inline() {
105 ; CHECK-LABEL: define i32 @normal_caller_streaming_callee_dont_inline
106 ; CHECK-SAME: () #[[ATTR1]] {
108 ; CHECK-NEXT: [[RES:%.*]] = call i32 @streaming_callee()
109 ; CHECK-NEXT: ret i32 [[RES]]
112 %res = call i32 @streaming_callee()
121 define i32 @normal_caller_streaming_compatible_callee_inline() {
122 ; CHECK-LABEL: define i32 @normal_caller_streaming_compatible_callee_inline
123 ; CHECK-SAME: () #[[ATTR1]] {
125 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
126 ; CHECK-NEXT: ret i32 [[RES_I]]
129 %res = call i32 @streaming_compatible_callee()
138 define i32 @normal_caller_locally_streaming_callee_dont_inline() {
139 ; CHECK-LABEL: define i32 @normal_caller_locally_streaming_callee_dont_inline
140 ; CHECK-SAME: () #[[ATTR1]] {
142 ; CHECK-NEXT: [[RES:%.*]] = call i32 @locally_streaming_callee()
143 ; CHECK-NEXT: ret i32 [[RES]]
146 %res = call i32 @locally_streaming_callee()
155 define i32 @normal_caller_streaming_compatible_locally_streaming_callee_dont_inline() {
156 ; CHECK-LABEL: define i32 @normal_caller_streaming_compatible_locally_streaming_callee_dont_inline
157 ; CHECK-SAME: () #[[ATTR1]] {
159 ; CHECK-NEXT: [[RES:%.*]] = call i32 @streaming_compatible_locally_streaming_callee()
160 ; CHECK-NEXT: ret i32 [[RES]]
163 %res = call i32 @streaming_compatible_locally_streaming_callee()
172 define i32 @streaming_caller_normal_callee_dont_inline() "aarch64_pstate_sm_enabled" {
173 ; CHECK-LABEL: define i32 @streaming_caller_normal_callee_dont_inline
174 ; CHECK-SAME: () #[[ATTR2]] {
176 ; CHECK-NEXT: [[RES:%.*]] = call i32 @normal_callee()
177 ; CHECK-NEXT: ret i32 [[RES]]
180 %res = call i32 @normal_callee()
189 define i32 @streaming_caller_streaming_callee_inline() "aarch64_pstate_sm_enabled" {
190 ; CHECK-LABEL: define i32 @streaming_caller_streaming_callee_inline
191 ; CHECK-SAME: () #[[ATTR2]] {
193 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
194 ; CHECK-NEXT: ret i32 [[RES_I]]
197 %res = call i32 @streaming_callee()
206 define i32 @streaming_caller_streaming_compatible_callee_inline() "aarch64_pstate_sm_enabled" {
207 ; CHECK-LABEL: define i32 @streaming_caller_streaming_compatible_callee_inline
208 ; CHECK-SAME: () #[[ATTR2]] {
210 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
211 ; CHECK-NEXT: ret i32 [[RES_I]]
214 %res = call i32 @streaming_compatible_callee()
223 define i32 @streaming_caller_locally_streaming_callee_inline() "aarch64_pstate_sm_enabled" {
224 ; CHECK-LABEL: define i32 @streaming_caller_locally_streaming_callee_inline
225 ; CHECK-SAME: () #[[ATTR2]] {
227 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
228 ; CHECK-NEXT: ret i32 [[RES_I]]
231 %res = call i32 @locally_streaming_callee()
240 define i32 @streaming_caller_streaming_compatible_locally_streaming_callee_inline() "aarch64_pstate_sm_enabled" {
241 ; CHECK-LABEL: define i32 @streaming_caller_streaming_compatible_locally_streaming_callee_inline
242 ; CHECK-SAME: () #[[ATTR2]] {
244 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
245 ; CHECK-NEXT: ret i32 [[RES_I]]
248 %res = call i32 @streaming_compatible_locally_streaming_callee()
256 ; [ ] N + B -> SC + B
257 define i32 @locally_streaming_caller_normal_callee_dont_inline() "aarch64_pstate_sm_body" {
258 ; CHECK-LABEL: define i32 @locally_streaming_caller_normal_callee_dont_inline
259 ; CHECK-SAME: () #[[ATTR3]] {
261 ; CHECK-NEXT: [[RES:%.*]] = call i32 @normal_callee()
262 ; CHECK-NEXT: ret i32 [[RES]]
265 %res = call i32 @normal_callee()
273 ; [ ] N + B -> SC + B
274 define i32 @locally_streaming_caller_streaming_callee_inline() "aarch64_pstate_sm_body" {
275 ; CHECK-LABEL: define i32 @locally_streaming_caller_streaming_callee_inline
276 ; CHECK-SAME: () #[[ATTR3]] {
278 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
279 ; CHECK-NEXT: ret i32 [[RES_I]]
282 %res = call i32 @streaming_callee()
290 ; [ ] N + B -> SC + B
291 define i32 @locally_streaming_caller_streaming_compatible_callee_inline() "aarch64_pstate_sm_body" {
292 ; CHECK-LABEL: define i32 @locally_streaming_caller_streaming_compatible_callee_inline
293 ; CHECK-SAME: () #[[ATTR3]] {
295 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
296 ; CHECK-NEXT: ret i32 [[RES_I]]
299 %res = call i32 @streaming_compatible_callee()
307 ; [ ] N + B -> SC + B
308 define i32 @locally_streaming_caller_locally_streaming_callee_inline() "aarch64_pstate_sm_body" {
309 ; CHECK-LABEL: define i32 @locally_streaming_caller_locally_streaming_callee_inline
310 ; CHECK-SAME: () #[[ATTR3]] {
312 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
313 ; CHECK-NEXT: ret i32 [[RES_I]]
316 %res = call i32 @locally_streaming_callee()
324 ; [x] N + B -> SC + B
325 define i32 @locally_streaming_caller_streaming_compatible_locally_streaming_callee_inline() "aarch64_pstate_sm_body" {
326 ; CHECK-LABEL: define i32 @locally_streaming_caller_streaming_compatible_locally_streaming_callee_inline
327 ; CHECK-SAME: () #[[ATTR3]] {
329 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
330 ; CHECK-NEXT: ret i32 [[RES_I]]
333 %res = call i32 @streaming_compatible_locally_streaming_callee()
342 define i32 @streaming_compatible_caller_normal_callee_dont_inline() "aarch64_pstate_sm_compatible" {
343 ; CHECK-LABEL: define i32 @streaming_compatible_caller_normal_callee_dont_inline
344 ; CHECK-SAME: () #[[ATTR0]] {
346 ; CHECK-NEXT: [[RES:%.*]] = call i32 @normal_callee()
347 ; CHECK-NEXT: ret i32 [[RES]]
350 %res = call i32 @normal_callee()
359 define i32 @streaming_compatible_caller_streaming_callee_dont_inline() "aarch64_pstate_sm_compatible" {
360 ; CHECK-LABEL: define i32 @streaming_compatible_caller_streaming_callee_dont_inline
361 ; CHECK-SAME: () #[[ATTR0]] {
363 ; CHECK-NEXT: [[RES:%.*]] = call i32 @streaming_callee()
364 ; CHECK-NEXT: ret i32 [[RES]]
367 %res = call i32 @streaming_callee()
376 define i32 @streaming_compatible_caller_streaming_compatible_callee_inline() "aarch64_pstate_sm_compatible" {
377 ; CHECK-LABEL: define i32 @streaming_compatible_caller_streaming_compatible_callee_inline
378 ; CHECK-SAME: () #[[ATTR0]] {
380 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
381 ; CHECK-NEXT: ret i32 [[RES_I]]
384 %res = call i32 @streaming_compatible_callee()
393 define i32 @streaming_compatible_caller_locally_streaming_callee_dont_inline() "aarch64_pstate_sm_compatible" {
394 ; CHECK-LABEL: define i32 @streaming_compatible_caller_locally_streaming_callee_dont_inline
395 ; CHECK-SAME: () #[[ATTR0]] {
397 ; CHECK-NEXT: [[RES:%.*]] = call i32 @locally_streaming_callee()
398 ; CHECK-NEXT: ret i32 [[RES]]
401 %res = call i32 @locally_streaming_callee()
410 define i32 @streaming_compatible_caller_streaming_compatible_locally_streaming_callee_dont_inline() "aarch64_pstate_sm_compatible" {
411 ; CHECK-LABEL: define i32 @streaming_compatible_caller_streaming_compatible_locally_streaming_callee_dont_inline
412 ; CHECK-SAME: () #[[ATTR0]] {
414 ; CHECK-NEXT: [[RES:%.*]] = call i32 @streaming_compatible_locally_streaming_callee()
415 ; CHECK-NEXT: ret i32 [[RES]]
418 %res = call i32 @streaming_compatible_locally_streaming_callee()
424 ; [ ] SC + B -> N + B
425 ; [ ] SC + B -> SC + B
426 define i32 @streaming_compatible_locally_streaming_caller_normal_callee_dont_inline() "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" {
427 ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_normal_callee_dont_inline
428 ; CHECK-SAME: () #[[ATTR4]] {
430 ; CHECK-NEXT: [[RES:%.*]] = call i32 @normal_callee()
431 ; CHECK-NEXT: ret i32 [[RES]]
434 %res = call i32 @normal_callee()
441 ; [ ] SC + B -> N + B
442 ; [ ] SC + B -> SC + B
443 define i32 @streaming_compatible_locally_streaming_caller_streaming_callee_inline() "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" {
444 ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_streaming_callee_inline
445 ; CHECK-SAME: () #[[ATTR4]] {
447 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
448 ; CHECK-NEXT: ret i32 [[RES_I]]
451 %res = call i32 @streaming_callee()
458 ; [ ] SC + B -> N + B
459 ; [ ] SC + B -> SC + B
460 define i32 @streaming_compatible_locally_streaming_caller_streaming_compatible_callee_inline() "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" {
461 ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_streaming_compatible_callee_inline
462 ; CHECK-SAME: () #[[ATTR4]] {
464 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
465 ; CHECK-NEXT: ret i32 [[RES_I]]
468 %res = call i32 @streaming_compatible_callee()
475 ; [x] SC + B -> N + B
476 ; [ ] SC + B -> SC + B
477 define i32 @streaming_compatible_locally_streaming_caller_locally_streaming_callee_inline() "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" {
478 ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_locally_streaming_callee_inline
479 ; CHECK-SAME: () #[[ATTR4]] {
481 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
482 ; CHECK-NEXT: ret i32 [[RES_I]]
485 %res = call i32 @locally_streaming_callee()
492 ; [ ] SC + B -> N + B
493 ; [x] SC + B -> SC + B
494 define i32 @streaming_compatible_locally_streaming_caller_and_callee_inline() "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" {
495 ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_and_callee_inline
496 ; CHECK-SAME: () #[[ATTR4]] {
498 ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32()
499 ; CHECK-NEXT: ret i32 [[RES_I]]
502 %res = call i32 @streaming_compatible_locally_streaming_callee()
506 define void @normal_callee_with_inlineasm() {
507 ; CHECK-LABEL: define void @normal_callee_with_inlineasm
508 ; CHECK-SAME: () #[[ATTR1]] {
510 ; CHECK-NEXT: call void asm sideeffect "
511 ; CHECK-NEXT: ret void
514 call void asm sideeffect "; inlineasm", ""()
518 define void @streaming_caller_normal_callee_with_inlineasm_dont_inline() "aarch64_pstate_sm_enabled" {
519 ; CHECK-LABEL: define void @streaming_caller_normal_callee_with_inlineasm_dont_inline
520 ; CHECK-SAME: () #[[ATTR2]] {
522 ; CHECK-NEXT: call void @normal_callee_with_inlineasm()
523 ; CHECK-NEXT: ret void
526 call void @normal_callee_with_inlineasm()
530 define i64 @normal_callee_with_intrinsic_call() {
531 ; CHECK-LABEL: define i64 @normal_callee_with_intrinsic_call
532 ; CHECK-SAME: () #[[ATTR1]] {
534 ; CHECK-NEXT: [[RES:%.*]] = call i64 @llvm.aarch64.sve.cntb(i32 4)
535 ; CHECK-NEXT: ret i64 [[RES]]
538 %res = call i64 @llvm.aarch64.sve.cntb(i32 4)
542 define i64 @streaming_caller_normal_callee_with_intrinsic_call_dont_inline() "aarch64_pstate_sm_enabled" {
543 ; CHECK-LABEL: define i64 @streaming_caller_normal_callee_with_intrinsic_call_dont_inline
544 ; CHECK-SAME: () #[[ATTR2]] {
546 ; CHECK-NEXT: [[RES:%.*]] = call i64 @normal_callee_with_intrinsic_call()
547 ; CHECK-NEXT: ret i64 [[RES]]
550 %res = call i64 @normal_callee_with_intrinsic_call()
554 declare i64 @llvm.aarch64.sve.cntb(i32)
556 define i64 @normal_callee_call_sme_state() {
557 ; CHECK-LABEL: define i64 @normal_callee_call_sme_state
558 ; CHECK-SAME: () #[[ATTR1]] {
560 ; CHECK-NEXT: [[RES:%.*]] = call { i64, i64 } @__arm_sme_state()
561 ; CHECK-NEXT: [[RES_0:%.*]] = extractvalue { i64, i64 } [[RES]], 0
562 ; CHECK-NEXT: ret i64 [[RES_0]]
565 %res = call {i64, i64} @__arm_sme_state()
566 %res.0 = extractvalue {i64, i64} %res, 0
570 declare {i64, i64} @__arm_sme_state()
572 define i64 @streaming_caller_normal_callee_call_sme_state_dont_inline() "aarch64_pstate_sm_enabled" {
573 ; CHECK-LABEL: define i64 @streaming_caller_normal_callee_call_sme_state_dont_inline
574 ; CHECK-SAME: () #[[ATTR2]] {
576 ; CHECK-NEXT: [[RES:%.*]] = call i64 @normal_callee_call_sme_state()
577 ; CHECK-NEXT: ret i64 [[RES]]
580 %res = call i64 @normal_callee_call_sme_state()
586 declare void @streaming_body() "aarch64_pstate_sm_enabled"
588 define void @streaming_caller_single_streaming_callee() "aarch64_pstate_sm_enabled" {
589 ; CHECK-LABEL: define void @streaming_caller_single_streaming_callee
590 ; CHECK-SAME: () #[[ATTR2]] {
591 ; CHECK-NEXT: call void @streaming_body()
592 ; CHECK-NEXT: ret void
594 call void @streaming_body()
598 define void @streaming_caller_multiple_streaming_callees() "aarch64_pstate_sm_enabled" {
599 ; CHECK-LABEL: define void @streaming_caller_multiple_streaming_callees
600 ; CHECK-SAME: () #[[ATTR2]] {
601 ; CHECK-NEXT: call void @streaming_body()
602 ; CHECK-NEXT: call void @streaming_body()
603 ; CHECK-NEXT: ret void
605 call void @streaming_body()
606 call void @streaming_body()
610 ; Allow inlining, as inline it would not increase the number of streaming-mode changes.
611 define void @streaming_caller_single_streaming_callee_inline() {
612 ; CHECK-LABEL: define void @streaming_caller_single_streaming_callee_inline
613 ; CHECK-SAME: () #[[ATTR1]] {
614 ; CHECK-NEXT: call void @streaming_body()
615 ; CHECK-NEXT: ret void
617 call void @streaming_caller_single_streaming_callee()
621 ; Prevent inlining, as inline it would lead to multiple streaming-mode changes.
622 define void @streaming_caller_multiple_streaming_callees_dont_inline() {
623 ; CHECK-LABEL: define void @streaming_caller_multiple_streaming_callees_dont_inline
624 ; CHECK-SAME: () #[[ATTR1]] {
625 ; CHECK-NEXT: call void @streaming_caller_multiple_streaming_callees()
626 ; CHECK-NEXT: ret void
628 call void @streaming_caller_multiple_streaming_callees()
632 declare void @streaming_compatible_body() "aarch64_pstate_sm_compatible"
634 define void @streaming_caller_single_streaming_compatible_callee() "aarch64_pstate_sm_enabled" {
635 ; CHECK-LABEL: define void @streaming_caller_single_streaming_compatible_callee
636 ; CHECK-SAME: () #[[ATTR2]] {
637 ; CHECK-NEXT: call void @streaming_compatible_body()
638 ; CHECK-NEXT: ret void
640 call void @streaming_compatible_body()
644 define void @streaming_caller_multiple_streaming_compatible_callees() "aarch64_pstate_sm_enabled" {
645 ; CHECK-LABEL: define void @streaming_caller_multiple_streaming_compatible_callees
646 ; CHECK-SAME: () #[[ATTR2]] {
647 ; CHECK-NEXT: call void @streaming_compatible_body()
648 ; CHECK-NEXT: call void @streaming_compatible_body()
649 ; CHECK-NEXT: ret void
651 call void @streaming_compatible_body()
652 call void @streaming_compatible_body()
656 ; Allow inlining, as inline would remove a streaming-mode change.
657 define void @streaming_caller_single_streaming_compatible_callee_inline() {
658 ; CHECK-LABEL: define void @streaming_caller_single_streaming_compatible_callee_inline
659 ; CHECK-SAME: () #[[ATTR1]] {
660 ; CHECK-NEXT: call void @streaming_compatible_body()
661 ; CHECK-NEXT: ret void
663 call void @streaming_caller_single_streaming_compatible_callee()
667 ; Allow inlining, as inline would remove several stremaing-mode changes.
668 define void @streaming_caller_multiple_streaming_compatible_callees_inline() {
669 ; CHECK-LABEL: define void @streaming_caller_multiple_streaming_compatible_callees_inline
670 ; CHECK-SAME: () #[[ATTR1]] {
671 ; CHECK-NEXT: call void @streaming_compatible_body()
672 ; CHECK-NEXT: call void @streaming_compatible_body()
673 ; CHECK-NEXT: ret void
675 call void @streaming_caller_multiple_streaming_compatible_callees()