| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 |
| ; RUN: opt < %s -mtriple=aarch64-unknown-linux-gnu -mattr=+sme -S -passes=inline | FileCheck %s |
| |
| declare i32 @llvm.vscale.i32() |
| |
| ; Define some functions that merely call llvm.vscale.i32(), which will be called |
| ; by the other functions below. If we see the call to one of these functions |
| ; being replaced by 'llvm.vscale()', then we know it has been inlined. |
| |
| define i32 @normal_callee() #0 { |
| ; CHECK-LABEL: define i32 @normal_callee |
| ; CHECK-SAME: () #[[ATTR1:[0-9]+]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @llvm.vscale.i32() |
| ret i32 %res |
| } |
| |
| define i32 @streaming_callee() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define i32 @streaming_callee |
| ; CHECK-SAME: () #[[ATTR2:[0-9]+]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @llvm.vscale.i32() |
| ret i32 %res |
| } |
| |
| define i32 @locally_streaming_callee() #0 "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @locally_streaming_callee |
| ; CHECK-SAME: () #[[ATTR3:[0-9]+]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @llvm.vscale.i32() |
| ret i32 %res |
| } |
| |
| define i32 @streaming_compatible_callee() #0 "aarch64_pstate_sm_compatible" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_callee |
| ; CHECK-SAME: () #[[ATTR4:[0-9]+]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @llvm.vscale.i32() |
| ret i32 %res |
| } |
| |
| define i32 @streaming_compatible_locally_streaming_callee() #0 "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_callee |
| ; CHECK-SAME: () #[[ATTR5:[0-9]+]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @llvm.vscale() |
| ret i32 %res |
| } |
| |
| ; Now test that inlining only happens when their streaming modes match. |
| ; Test for a number of combinations, where: |
| ; N Normal-interface (PSTATE.SM=0 on entry/exit) |
| ; S Streaming-interface (PSTATE.SM=1 on entry/exit) |
| ; SC Streaming-compatible interface |
| ; (PSTATE.SM=0 or 1, unchanged on exit) |
| ; N + B Normal-interface, streaming body |
| ; (PSTATE.SM=0 on entry/exit, but 1 within the body of the function) |
| ; SC + B Streaming-compatible-interface, streaming body |
| ; (PSTATE.SM=0 or 1 on entry, unchanged on exit, |
| ; but guaranteed to be 1 within the body of the function) |
| |
| ; [x] N -> N |
| ; [ ] N -> S |
| ; [ ] N -> SC |
| ; [ ] N -> N + B |
| ; [ ] N -> SC + B |
| define i32 @normal_caller_normal_callee_inline() #0 { |
| ; CHECK-LABEL: define i32 @normal_caller_normal_callee_inline |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @normal_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] N -> N |
| ; [x] N -> S |
| ; [ ] N -> SC |
| ; [ ] N -> N + B |
| ; [ ] N -> SC + B |
| define i32 @normal_caller_streaming_callee_dont_inline() #0 { |
| ; CHECK-LABEL: define i32 @normal_caller_streaming_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @streaming_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] N -> N |
| ; [ ] N -> S |
| ; [x] N -> SC |
| ; [ ] N -> N + B |
| ; [ ] N -> SC + B |
| define i32 @normal_caller_streaming_compatible_callee_inline() #0 { |
| ; CHECK-LABEL: define i32 @normal_caller_streaming_compatible_callee_inline |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] N -> N |
| ; [ ] N -> S |
| ; [ ] N -> SC |
| ; [x] N -> N + B |
| ; [ ] N -> SC + B |
| define i32 @normal_caller_locally_streaming_callee_dont_inline() #0 { |
| ; CHECK-LABEL: define i32 @normal_caller_locally_streaming_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @locally_streaming_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @locally_streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] N -> N |
| ; [ ] N -> S |
| ; [ ] N -> SC |
| ; [ ] N -> N + B |
| ; [x] N -> SC + B |
| define i32 @normal_caller_streaming_compatible_locally_streaming_callee_dont_inline() #0 { |
| ; CHECK-LABEL: define i32 @normal_caller_streaming_compatible_locally_streaming_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @streaming_compatible_locally_streaming_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_locally_streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [x] S -> N |
| ; [ ] S -> S |
| ; [ ] S -> SC |
| ; [ ] S -> N + B |
| ; [ ] S -> SC + B |
| define i32 @streaming_caller_normal_callee_dont_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define i32 @streaming_caller_normal_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @normal_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @normal_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] S -> N |
| ; [x] S -> S |
| ; [ ] S -> SC |
| ; [ ] S -> N + B |
| ; [ ] S -> SC + B |
| define i32 @streaming_caller_streaming_callee_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define i32 @streaming_caller_streaming_callee_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] S -> N |
| ; [ ] S -> S |
| ; [x] S -> SC |
| ; [ ] S -> N + B |
| ; [ ] S -> SC + B |
| define i32 @streaming_caller_streaming_compatible_callee_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define i32 @streaming_caller_streaming_compatible_callee_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] S -> N |
| ; [ ] S -> S |
| ; [ ] S -> SC |
| ; [x] S -> N + B |
| ; [ ] S -> SC + B |
| define i32 @streaming_caller_locally_streaming_callee_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define i32 @streaming_caller_locally_streaming_callee_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @locally_streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] S -> N |
| ; [ ] S -> S |
| ; [ ] S -> SC |
| ; [ ] S -> N + B |
| ; [x] S -> SC + B |
| define i32 @streaming_caller_streaming_compatible_locally_streaming_callee_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define i32 @streaming_caller_streaming_compatible_locally_streaming_callee_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_locally_streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [x] N + B -> N |
| ; [ ] N + B -> S |
| ; [ ] N + B -> SC |
| ; [ ] N + B -> N + B |
| ; [ ] N + B -> SC + B |
| define i32 @locally_streaming_caller_normal_callee_dont_inline() #0 "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @locally_streaming_caller_normal_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR3]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @normal_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @normal_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] N + B -> N |
| ; [x] N + B -> S |
| ; [ ] N + B -> SC |
| ; [ ] N + B -> N + B |
| ; [ ] N + B -> SC + B |
| define i32 @locally_streaming_caller_streaming_callee_inline() #0 "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @locally_streaming_caller_streaming_callee_inline |
| ; CHECK-SAME: () #[[ATTR3]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] N + B -> N |
| ; [ ] N + B -> S |
| ; [x] N + B -> SC |
| ; [ ] N + B -> N + B |
| ; [ ] N + B -> SC + B |
| define i32 @locally_streaming_caller_streaming_compatible_callee_inline() #0 "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @locally_streaming_caller_streaming_compatible_callee_inline |
| ; CHECK-SAME: () #[[ATTR3]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] N + B -> N |
| ; [ ] N + B -> S |
| ; [ ] N + B -> SC |
| ; [x] N + B -> N + B |
| ; [ ] N + B -> SC + B |
| define i32 @locally_streaming_caller_locally_streaming_callee_inline() #0 "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @locally_streaming_caller_locally_streaming_callee_inline |
| ; CHECK-SAME: () #[[ATTR3]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @locally_streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] N + B -> N |
| ; [ ] N + B -> S |
| ; [ ] N + B -> SC |
| ; [ ] N + B -> N + B |
| ; [x] N + B -> SC + B |
| define i32 @locally_streaming_caller_streaming_compatible_locally_streaming_callee_inline() #0 "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @locally_streaming_caller_streaming_compatible_locally_streaming_callee_inline |
| ; CHECK-SAME: () #[[ATTR3]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_locally_streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [x] SC -> N |
| ; [ ] SC -> S |
| ; [ ] SC -> SC |
| ; [ ] SC -> N + B |
| ; [ ] SC -> SC + B |
| define i32 @streaming_compatible_caller_normal_callee_dont_inline() #0 "aarch64_pstate_sm_compatible" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_caller_normal_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR4]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @normal_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @normal_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] SC -> N |
| ; [x] SC -> S |
| ; [ ] SC -> SC |
| ; [ ] SC -> N + B |
| ; [ ] SC -> SC + B |
| define i32 @streaming_compatible_caller_streaming_callee_dont_inline() #0 "aarch64_pstate_sm_compatible" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_caller_streaming_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR4]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @streaming_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] SC -> N |
| ; [ ] SC -> S |
| ; [x] SC -> SC |
| ; [ ] SC -> N + B |
| ; [ ] SC -> SC + B |
| define i32 @streaming_compatible_caller_streaming_compatible_callee_inline() #0 "aarch64_pstate_sm_compatible" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_caller_streaming_compatible_callee_inline |
| ; CHECK-SAME: () #[[ATTR4]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] SC -> N |
| ; [ ] SC -> S |
| ; [ ] SC -> SC |
| ; [x] SC -> N + B |
| ; [ ] SC -> SC + B |
| define i32 @streaming_compatible_caller_locally_streaming_callee_dont_inline() #0 "aarch64_pstate_sm_compatible" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_caller_locally_streaming_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR4]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @locally_streaming_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @locally_streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] SC -> N |
| ; [ ] SC -> S |
| ; [ ] SC -> SC |
| ; [ ] SC -> N + B |
| ; [x] SC -> SC + B |
| define i32 @streaming_compatible_caller_streaming_compatible_locally_streaming_callee_dont_inline() #0 "aarch64_pstate_sm_compatible" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_caller_streaming_compatible_locally_streaming_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR4]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @streaming_compatible_locally_streaming_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_locally_streaming_callee() |
| ret i32 %res |
| } |
| ; [x] SC + B -> N |
| ; [ ] SC + B -> S |
| ; [ ] SC + B -> SC |
| ; [ ] SC + B -> N + B |
| ; [ ] SC + B -> SC + B |
| define i32 @streaming_compatible_locally_streaming_caller_normal_callee_dont_inline() #0 "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_normal_callee_dont_inline |
| ; CHECK-SAME: () #[[ATTR5]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @normal_callee() |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %res = call i32 @normal_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] SC + B -> N |
| ; [x] SC + B -> S |
| ; [ ] SC + B -> SC |
| ; [ ] SC + B -> N + B |
| ; [ ] SC + B -> SC + B |
| define i32 @streaming_compatible_locally_streaming_caller_streaming_callee_inline() #0 "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_streaming_callee_inline |
| ; CHECK-SAME: () #[[ATTR5]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] SC + B -> N |
| ; [ ] SC + B -> S |
| ; [x] SC + B -> SC |
| ; [ ] SC + B -> N + B |
| ; [ ] SC + B -> SC + B |
| define i32 @streaming_compatible_locally_streaming_caller_streaming_compatible_callee_inline() #0 "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_streaming_compatible_callee_inline |
| ; CHECK-SAME: () #[[ATTR5]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] SC + B -> N |
| ; [ ] SC + B -> S |
| ; [ ] SC + B -> SC |
| ; [x] SC + B -> N + B |
| ; [ ] SC + B -> SC + B |
| define i32 @streaming_compatible_locally_streaming_caller_locally_streaming_callee_inline() #0 "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_locally_streaming_callee_inline |
| ; CHECK-SAME: () #[[ATTR5]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @locally_streaming_callee() |
| ret i32 %res |
| } |
| |
| ; [ ] SC + B -> N |
| ; [ ] SC + B -> S |
| ; [ ] SC + B -> SC |
| ; [ ] SC + B -> N + B |
| ; [x] SC + B -> SC + B |
| define i32 @streaming_compatible_locally_streaming_caller_and_callee_inline() #0 "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define i32 @streaming_compatible_locally_streaming_caller_and_callee_inline |
| ; CHECK-SAME: () #[[ATTR5]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES_I:%.*]] = call i32 @llvm.vscale.i32() |
| ; CHECK-NEXT: ret i32 [[RES_I]] |
| ; |
| entry: |
| %res = call i32 @streaming_compatible_locally_streaming_callee() |
| ret i32 %res |
| } |
| |
| define void @normal_callee_with_inlineasm() #0 { |
| ; CHECK-LABEL: define void @normal_callee_with_inlineasm |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: call void asm sideeffect " |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| call void asm sideeffect "; inlineasm", ""() |
| ret void |
| } |
| |
| define void @streaming_caller_normal_callee_with_inlineasm_dont_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define void @streaming_caller_normal_callee_with_inlineasm_dont_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: call void @normal_callee_with_inlineasm() |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| call void @normal_callee_with_inlineasm() |
| ret void |
| } |
| |
| define i64 @normal_callee_with_intrinsic_call() #0 { |
| ; CHECK-LABEL: define i64 @normal_callee_with_intrinsic_call |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i64 @llvm.aarch64.sve.cntb(i32 4) |
| ; CHECK-NEXT: ret i64 [[RES]] |
| ; |
| entry: |
| %res = call i64 @llvm.aarch64.sve.cntb(i32 4) |
| ret i64 %res |
| } |
| |
| define i64 @streaming_caller_normal_callee_with_intrinsic_call_dont_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define i64 @streaming_caller_normal_callee_with_intrinsic_call_dont_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i64 @normal_callee_with_intrinsic_call() |
| ; CHECK-NEXT: ret i64 [[RES]] |
| ; |
| entry: |
| %res = call i64 @normal_callee_with_intrinsic_call() |
| ret i64 %res |
| } |
| |
| declare i64 @llvm.aarch64.sve.cntb(i32) |
| |
| define i64 @normal_callee_call_sme_state() #0 { |
| ; CHECK-LABEL: define i64 @normal_callee_call_sme_state |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call { i64, i64 } @__arm_sme_state() |
| ; CHECK-NEXT: [[RES_0:%.*]] = extractvalue { i64, i64 } [[RES]], 0 |
| ; CHECK-NEXT: ret i64 [[RES_0]] |
| ; |
| entry: |
| %res = call {i64, i64} @__arm_sme_state() |
| %res.0 = extractvalue {i64, i64} %res, 0 |
| ret i64 %res.0 |
| } |
| |
| declare {i64, i64} @__arm_sme_state() |
| |
| define i64 @streaming_caller_normal_callee_call_sme_state_dont_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define i64 @streaming_caller_normal_callee_call_sme_state_dont_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[RES:%.*]] = call i64 @normal_callee_call_sme_state() |
| ; CHECK-NEXT: ret i64 [[RES]] |
| ; |
| entry: |
| %res = call i64 @normal_callee_call_sme_state() |
| ret i64 %res |
| } |
| |
| |
| |
| declare void @nonstreaming_body() |
| |
| define void @nonstreaming_caller_single_nonstreaming_callee() #0 { |
| ; CHECK-LABEL: define void @nonstreaming_caller_single_nonstreaming_callee |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: call void @nonstreaming_body() |
| ; CHECK-NEXT: ret void |
| ; |
| call void @nonstreaming_body() |
| ret void |
| } |
| |
| define void @nonstreaming_caller_multiple_nonstreaming_callees() #0 { |
| ; CHECK-LABEL: define void @nonstreaming_caller_multiple_nonstreaming_callees |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: call void @nonstreaming_body() |
| ; CHECK-NEXT: call void @nonstreaming_body() |
| ; CHECK-NEXT: ret void |
| ; |
| call void @nonstreaming_body() |
| call void @nonstreaming_body() |
| ret void |
| } |
| |
| ; Allow inlining, as inline it would not increase the number of streaming-mode changes. |
| define void @streaming_caller_to_nonstreaming_callee_with_single_nonstreaming_callee_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define void @streaming_caller_to_nonstreaming_callee_with_single_nonstreaming_callee_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: call void @nonstreaming_body() |
| ; CHECK-NEXT: ret void |
| ; |
| call void @nonstreaming_caller_single_nonstreaming_callee() |
| ret void |
| } |
| |
| ; Prevent inlining, as inlining it would lead to multiple streaming-mode changes. |
| define void @streaming_caller_to_nonstreaming_callee_with_multiple_nonstreaming_callees_dont_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define void @streaming_caller_to_nonstreaming_callee_with_multiple_nonstreaming_callees_dont_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: call void @streaming_caller_to_nonstreaming_callee_with_multiple_nonstreaming_callees_dont_inline() |
| ; CHECK-NEXT: ret void |
| ; |
| call void @streaming_caller_to_nonstreaming_callee_with_multiple_nonstreaming_callees_dont_inline() |
| ret void |
| } |
| |
| declare void @streaming_compatible_body() "aarch64_pstate_sm_compatible" |
| |
| define void @nonstreaming_caller_single_streaming_compatible_callee() #0 { |
| ; CHECK-LABEL: define void @nonstreaming_caller_single_streaming_compatible_callee |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: call void @streaming_compatible_body() |
| ; CHECK-NEXT: ret void |
| ; |
| call void @streaming_compatible_body() |
| ret void |
| } |
| |
| define void @nonstreaming_caller_multiple_streaming_compatible_callees() #0 { |
| ; CHECK-LABEL: define void @nonstreaming_caller_multiple_streaming_compatible_callees |
| ; CHECK-SAME: () #[[ATTR1]] { |
| ; CHECK-NEXT: call void @streaming_compatible_body() |
| ; CHECK-NEXT: call void @streaming_compatible_body() |
| ; CHECK-NEXT: ret void |
| ; |
| call void @streaming_compatible_body() |
| call void @streaming_compatible_body() |
| ret void |
| } |
| |
| ; Allow inlining, as inline would remove a streaming-mode change. |
| define void @streaming_caller_to_nonstreaming_callee_with_single_streamingcompatible_callee_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define void @streaming_caller_to_nonstreaming_callee_with_single_streamingcompatible_callee_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: call void @streaming_compatible_body() |
| ; CHECK-NEXT: ret void |
| ; |
| call void @nonstreaming_caller_single_streaming_compatible_callee() |
| ret void |
| } |
| |
| ; Allow inlining, as inline would remove several streaming-mode changes. |
| define void @streaming_caller_to_nonstreaming_callee_with_multiple_streamingcompatible_callees_inline() #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define void @streaming_caller_to_nonstreaming_callee_with_multiple_streamingcompatible_callees_inline |
| ; CHECK-SAME: () #[[ATTR2]] { |
| ; CHECK-NEXT: call void @streaming_compatible_body() |
| ; CHECK-NEXT: call void @streaming_compatible_body() |
| ; CHECK-NEXT: ret void |
| ; |
| call void @nonstreaming_caller_multiple_streaming_compatible_callees() |
| ret void |
| } |
| |
| define void @simple_streaming_function(ptr %ptr) #0 "aarch64_pstate_sm_enabled" { |
| ; CHECK-LABEL: define void @simple_streaming_function |
| ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR2]] { |
| ; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[PTR]], align 16 |
| ; CHECK-NEXT: ret void |
| ; |
| store <vscale x 4 x i32> zeroinitializer, ptr %ptr |
| ret void |
| } |
| |
| ; Don't allow inlining a streaming function into a non-streaming function. |
| define void @non_streaming_caller_streaming_callee_dont_inline(ptr %ptr) #0 { |
| ; CHECK-LABEL: define void @non_streaming_caller_streaming_callee_dont_inline |
| ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: call void @simple_streaming_function(ptr [[PTR]]) |
| ; CHECK-NEXT: ret void |
| ; |
| call void @simple_streaming_function(ptr %ptr) |
| ret void |
| } |
| |
| define void @simple_locally_streaming_function(ptr %ptr) #0 "aarch64_pstate_sm_body" { |
| ; CHECK-LABEL: define void @simple_locally_streaming_function |
| ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR3]] { |
| ; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[PTR]], align 16 |
| ; CHECK-NEXT: ret void |
| ; |
| store <vscale x 4 x i32> zeroinitializer, ptr %ptr |
| ret void |
| } |
| |
| ; Don't allow inlining a locally-streaming function into a non-streaming function. |
| define void @non_streaming_caller_locally_streaming_callee_dont_inline(ptr %ptr) #0 { |
| ; CHECK-LABEL: define void @non_streaming_caller_locally_streaming_callee_dont_inline |
| ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: call void @simple_locally_streaming_function(ptr [[PTR]]) |
| ; CHECK-NEXT: ret void |
| ; |
| call void @simple_locally_streaming_function(ptr %ptr) |
| ret void |
| } |
| |
| attributes #0 = { "target-features"="+sve,+sme" } |