xref: /llvm-project/llvm/test/CodeGen/AArch64/arg_promotion.ll (revision 926173c614784149889b2c975adccf52bcece75b)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2
3; RUN: opt -S -passes=argpromotion -mtriple=aarch64-unknwon-linux-gnu < %s | FileCheck %s
4
5target triple = "aarch64-unknown-linux-gnu"
6
7; Don't promote a vector pointer argument when the pointee type size is greater
8; than 128 bits.
9
10define dso_local void @caller_8xi32(ptr noalias %src, ptr noalias %dst) #0 {
11; CHECK-LABEL: define dso_local void @caller_8xi32(
12; CHECK-NEXT:  entry:
13; CHECK-NEXT:    call fastcc void @callee_8xi32(ptr noalias [[SRC:%.*]], ptr noalias [[DST:%.*]])
14; CHECK-NEXT:    ret void
15;
16entry:
17  call fastcc void @callee_8xi32(ptr noalias %src, ptr noalias %dst)
18  ret void
19}
20
21define internal fastcc void @callee_8xi32(ptr noalias %src, ptr noalias %dst) #0 {
22; CHECK-LABEL: define internal fastcc void @callee_8xi32(
23; CHECK-NEXT:  entry:
24; CHECK-NEXT:    [[TMP0:%.*]] = load <8 x i32>, ptr [[SRC:%.*]], align 16
25; CHECK-NEXT:    store <8 x i32> [[TMP0]], ptr [[DST:%.*]], align 16
26; CHECK-NEXT:    ret void
27;
28entry:
29  %0 = load <8 x i32>, ptr %src, align 16
30  store <8 x i32> %0, ptr %dst, align 16
31  ret void
32}
33
34; Promote a vector pointer argument when the pointee type size is 128 bits or
35; less.
36
37define dso_local void @caller_4xi32(ptr noalias %src, ptr noalias %dst) #1 {
38; CHECK-LABEL: define dso_local void @caller_4xi32(
39; CHECK-NEXT:  entry:
40; CHECK-NEXT:    [[SRC_VAL:%.*]] = load <4 x i32>, ptr [[SRC:%.*]], align 16
41; CHECK-NEXT:    call fastcc void @callee_4xi32(<4 x i32> [[SRC_VAL]], ptr noalias [[DST:%.*]])
42; CHECK-NEXT:    ret void
43;
44entry:
45  call fastcc void @callee_4xi32(ptr noalias %src, ptr noalias %dst)
46  ret void
47}
48
49define internal fastcc void @callee_4xi32(ptr noalias %src, ptr noalias %dst) #1 {
50; CHECK-LABEL: define internal fastcc void @callee_4xi32(
51; CHECK-NEXT:  entry:
52; CHECK-NEXT:    store <4 x i32> [[SRC_0_VAL:%.*]], ptr [[DST:%.*]], align 16
53; CHECK-NEXT:    ret void
54;
55entry:
56  %0 = load <4 x i32>, ptr %src, align 16
57  store <4 x i32> %0, ptr %dst, align 16
58  ret void
59}
60
61; A scalar pointer argument is promoted even when the pointee type size is
62; greater than 128 bits.
63
64define dso_local void @caller_i256(ptr noalias %src, ptr noalias %dst) #0 {
65; CHECK-LABEL: define dso_local void @caller_i256(
66; CHECK-NEXT:  entry:
67; CHECK-NEXT:    [[SRC_VAL:%.*]] = load i256, ptr [[SRC:%.*]], align 16
68; CHECK-NEXT:    call fastcc void @callee_i256(i256 [[SRC_VAL]], ptr noalias [[DST:%.*]])
69; CHECK-NEXT:    ret void
70;
71entry:
72  call fastcc void @callee_i256(ptr noalias %src, ptr noalias %dst)
73  ret void
74}
75
76define internal fastcc void @callee_i256(ptr noalias %src, ptr noalias %dst) #0 {
77; CHECK-LABEL: define internal fastcc void @callee_i256(
78; CHECK-NEXT:  entry:
79; CHECK-NEXT:    store i256 [[SRC_0_VAL:%.*]], ptr [[DST:%.*]], align 16
80; CHECK-NEXT:    ret void
81;
82entry:
83  %0 = load i256, ptr %src, align 16
84  store i256 %0, ptr %dst, align 16
85  ret void
86}
87
88; A scalable vector pointer argument is not a target of ArgumentPromotionPass.
89
90define dso_local void @caller_nx4xi32(ptr noalias %src, ptr noalias %dst) #2 {
91; CHECK-LABEL: define dso_local void @caller_nx4xi32(
92; CHECK-NEXT:  entry:
93; CHECK-NEXT:    call fastcc void @callee_nx4xi32(ptr noalias [[SRC:%.*]], ptr noalias [[DST:%.*]])
94; CHECK-NEXT:    ret void
95;
96entry:
97  call fastcc void @callee_nx4xi32(ptr noalias %src, ptr noalias %dst)
98  ret void
99}
100
101define internal fastcc void @callee_nx4xi32(ptr noalias %src, ptr noalias %dst) #2 {
102; CHECK-LABEL: define internal fastcc void @callee_nx4xi32(
103; CHECK-NEXT:  entry:
104; CHECK-NEXT:    [[TMP0:%.*]] = load <vscale x 4 x i32>, ptr [[SRC:%.*]], align 16
105; CHECK-NEXT:    store <vscale x 4 x i32> [[TMP0]], ptr [[DST:%.*]], align 16
106; CHECK-NEXT:    ret void
107;
108entry:
109  %0 = load <vscale x 4 x i32>, ptr %src, align 16
110  store <vscale x 4 x i32> %0, ptr %dst, align 16
111  ret void
112}
113
114; Don't promote a structure pointer argument when the pointee vector member
115; type size is greater than 128 bits.
116
117%struct_8xi32 = type { <8 x i32>, <8 x i32> }
118
119define dso_local void @caller_struct8xi32(ptr noalias %src, ptr noalias %dst) #0 {
120; CHECK-LABEL: define dso_local void @caller_struct8xi32(
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    call fastcc void @callee_struct8xi32(ptr noalias [[SRC:%.*]], ptr noalias [[DST:%.*]])
123; CHECK-NEXT:    ret void
124;
125entry:
126  call fastcc void @callee_struct8xi32(ptr noalias %src, ptr noalias %dst)
127  ret void
128}
129
130define internal fastcc void @callee_struct8xi32(ptr noalias %src, ptr noalias %dst) #0 {
131; CHECK-LABEL: define internal fastcc void @callee_struct8xi32(
132; CHECK-NEXT:  entry:
133; CHECK-NEXT:    [[TMP0:%.*]] = load <8 x i32>, ptr [[SRC:%.*]], align 16
134; CHECK-NEXT:    store <8 x i32> [[TMP0]], ptr [[DST:%.*]], align 16
135; CHECK-NEXT:    [[SRC2:%.*]] = getelementptr inbounds [[STRUCT_8XI32:%.*]], ptr [[SRC]], i64 0, i32 1
136; CHECK-NEXT:    [[TMP1:%.*]] = load <8 x i32>, ptr [[SRC2]], align 16
137; CHECK-NEXT:    [[DST2:%.*]] = getelementptr inbounds [[STRUCT_8XI32]], ptr [[DST]], i64 0, i32 1
138; CHECK-NEXT:    store <8 x i32> [[TMP1]], ptr [[DST2]], align 16
139; CHECK-NEXT:    ret void
140;
141entry:
142  %0 = load <8 x i32>, ptr %src, align 16
143  store <8 x i32> %0, ptr %dst, align 16
144  %src2 = getelementptr inbounds %struct_8xi32, ptr %src, i64 0, i32 1
145  %1 = load <8 x i32>, ptr %src2, align 16
146  %dst2 = getelementptr inbounds %struct_8xi32, ptr %dst, i64 0, i32 1
147  store <8 x i32> %1, ptr %dst2, align 16
148  ret void
149}
150
151; Promote a structure pointer argument when the pointee vector member type size
152; is 128 bits or less.
153
154%struct_4xi32 = type { <4 x i32>, <4 x i32> }
155
156define dso_local void @caller_struct4xi32(ptr noalias %src, ptr noalias %dst) #1 {
157; CHECK-LABEL: define dso_local void @caller_struct4xi32(
158; CHECK-NEXT:  entry:
159; CHECK-NEXT:    [[SRC_VAL:%.*]] = load <4 x i32>, ptr [[SRC:%.*]], align 16
160; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr i8, ptr [[SRC]], i64 16
161; CHECK-NEXT:    [[SRC_VAL1:%.*]] = load <4 x i32>, ptr [[TMP0]], align 16
162; CHECK-NEXT:    call fastcc void @callee_struct4xi32(<4 x i32> [[SRC_VAL]], <4 x i32> [[SRC_VAL1]], ptr noalias [[DST:%.*]])
163; CHECK-NEXT:    ret void
164;
165entry:
166  call fastcc void @callee_struct4xi32(ptr noalias %src, ptr noalias %dst)
167  ret void
168}
169
170define internal fastcc void @callee_struct4xi32(ptr noalias %src, ptr noalias %dst) #1 {
171; CHECK-LABEL: define internal fastcc void @callee_struct4xi32(
172; CHECK-NEXT:  entry:
173; CHECK-NEXT:    store <4 x i32> [[SRC_0_VAL:%.*]], ptr [[DST:%.*]], align 16
174; CHECK-NEXT:    [[DST2:%.*]] = getelementptr inbounds [[STRUCT_4XI32:%.*]], ptr [[DST]], i64 0, i32 1
175; CHECK-NEXT:    store <4 x i32> [[SRC_16_VAL:%.*]], ptr [[DST2]], align 16
176; CHECK-NEXT:    ret void
177;
178entry:
179  %0 = load <4 x i32>, ptr %src, align 16
180  store <4 x i32> %0, ptr %dst, align 16
181  %src2 = getelementptr inbounds %struct_4xi32, ptr %src, i64 0, i32 1
182  %1 = load <4 x i32>, ptr %src2, align 16
183  %dst2 = getelementptr inbounds %struct_4xi32, ptr %dst, i64 0, i32 1
184  store <4 x i32> %1, ptr %dst2, align 16
185  ret void
186}
187
188attributes #0 = { noinline vscale_range(2,2) "target-features"="+v8.2a,+neon,+sve" }
189attributes #1 = { noinline vscale_range(1,1) "target-features"="+v8.2a,+neon,+sve" }
190attributes #2 = { noinline "target-features"="+v8.2a,+neon,+sve" }
191