1; RUN: llc -mtriple aarch64 -mattr=+sve -asm-verbose=0 < %s 2>%t | FileCheck %s
2; RUN: opt -mtriple=aarch64 -codegenprepare -S < %s | llc -mtriple=aarch64 -mattr=+sve -asm-verbose=0 | FileCheck %s
3; RUN: FileCheck --check-prefix=WARN --allow-empty %s <%t
4
5; If this check fails please read test/CodeGen/AArch64/README for instructions on how to resolve it.
6; WARN-NOT: warning
7
8;
9; RDVL
10;
11
12; CHECK-LABEL: rdvl_i8:
13; CHECK:       rdvl x0, #1
14; CHECK-NEXT:  ret
15define i8 @rdvl_i8() nounwind {
16  %vscale = call i8 @llvm.vscale.i8()
17  %1 = mul nsw i8 %vscale, 16
18  ret i8 %1
19}
20
21; CHECK-LABEL: rdvl_i16:
22; CHECK:       rdvl x0, #1
23; CHECK-NEXT:  ret
24define i16 @rdvl_i16() nounwind {
25  %vscale = call i16 @llvm.vscale.i16()
26  %1 = mul nsw i16 %vscale, 16
27  ret i16 %1
28}
29
30; CHECK-LABEL: rdvl_i32:
31; CHECK:       rdvl x0, #1
32; CHECK-NEXT:  ret
33define i32 @rdvl_i32() nounwind {
34  %vscale = call i32 @llvm.vscale.i32()
35  %1 = mul nsw i32 %vscale, 16
36  ret i32 %1
37}
38
39; CHECK-LABEL: rdvl_i64:
40; CHECK:       rdvl x0, #1
41; CHECK-NEXT:  ret
42define i64 @rdvl_i64() nounwind {
43  %vscale = call i64 @llvm.vscale.i64()
44  %1 = mul nsw i64 %vscale, 16
45  ret i64 %1
46}
47
48; CHECK-LABEL: rdvl_const:
49; CHECK:       rdvl x0, #1
50; CHECK-NEXT:  ret
51define i32 @rdvl_const() nounwind {
52  ret i32 mul nsw (i32 ptrtoint (<vscale x 1 x i8>* getelementptr (<vscale x 1 x i8>, <vscale x 1 x i8>* null, i64 1) to i32), i32 16)
53}
54
55define i32 @vscale_1() nounwind {
56; CHECK-LABEL: vscale_1:
57; CHECK:       rdvl [[TMP:x[0-9]+]], #1
58; CHECK-NEXT:  lsr  x0, [[TMP]], #4
59; CHECK-NEXT:  ret
60  %vscale = call i32 @llvm.vscale.i32()
61  ret i32 %vscale
62}
63
64define i32 @vscale_neg1() nounwind {
65; CHECK-LABEL: vscale_neg1:
66; CHECK:       rdvl [[TMP:x[0-9]+]], #-1
67; CHECK-NEXT:  asr  x0, [[TMP]], #4
68; CHECK-NEXT:  ret
69  %vscale = call i32 @llvm.vscale.i32()
70  %neg = mul nsw i32 -1, %vscale
71  ret i32 %neg
72}
73
74; CHECK-LABEL: rdvl_3:
75; CHECK:       rdvl [[VL_B:x[0-9]+]], #1
76; CHECK-NEXT:  lsr  [[VL_Q:x[0-9]+]], [[VL_B]], #4
77; CHECK-NEXT:  mov  w[[MUL:[0-9]+]], #3
78; CHECK-NEXT:  mul  x0, [[VL_Q]], x[[MUL]]
79; CHECK-NEXT:  ret
80define i32 @rdvl_3() nounwind {
81  %vscale = call i32 @llvm.vscale.i32()
82  %1 = mul nsw i32 %vscale, 3
83  ret i32 %1
84}
85
86
87; CHECK-LABEL: rdvl_min:
88; CHECK:       rdvl x0, #-32
89; CHECK-NEXT:  ret
90define i32 @rdvl_min() nounwind {
91  %vscale = call i32 @llvm.vscale.i32()
92  %1 = mul nsw i32 %vscale, -512
93  ret i32 %1
94}
95
96; CHECK-LABEL: rdvl_max:
97; CHECK:       rdvl x0, #31
98; CHECK-NEXT:  ret
99define i32 @rdvl_max() nounwind {
100  %vscale = call i32 @llvm.vscale.i32()
101  %1 = mul nsw i32 %vscale, 496
102  ret i32 %1
103}
104
105;
106; CNTH
107;
108
109; CHECK-LABEL: cnth:
110; CHECK:       cnth x0{{$}}
111; CHECK-NEXT:  ret
112define i32 @cnth() nounwind {
113  %vscale = call i32 @llvm.vscale.i32()
114  %1 = shl nsw i32 %vscale, 3
115  ret i32 %1
116}
117
118; CHECK-LABEL: cnth_max:
119; CHECK:       cnth x0, all, mul #15
120; CHECK-NEXT:  ret
121define i32 @cnth_max() nounwind {
122  %vscale = call i32 @llvm.vscale.i32()
123  %1 = mul nsw i32 %vscale, 120
124  ret i32 %1
125}
126
127; CHECK-LABEL: cnth_neg:
128; CHECK:       cnth [[CNT:x[0-9]+]]
129; CHECK:       neg x0, [[CNT]]
130; CHECK-NEXT:  ret
131define i32 @cnth_neg() nounwind {
132  %vscale = call i32 @llvm.vscale.i32()
133  %1 = mul nsw i32 %vscale, -8
134  ret i32 %1
135}
136
137;
138; CNTW
139;
140
141; CHECK-LABEL: cntw:
142; CHECK:       cntw x0{{$}}
143; CHECK-NEXT:  ret
144define i32 @cntw() nounwind {
145  %vscale = call i32 @llvm.vscale.i32()
146  %1 = shl nsw i32 %vscale, 2
147  ret i32 %1
148}
149
150; CHECK-LABEL: cntw_max:
151; CHECK:       cntw x0, all, mul #15
152; CHECK-NEXT:  ret
153define i32 @cntw_max() nounwind {
154  %vscale = call i32 @llvm.vscale.i32()
155  %1 = mul nsw i32 %vscale, 60
156  ret i32 %1
157}
158
159; CHECK-LABEL: cntw_neg:
160; CHECK:       cntw [[CNT:x[0-9]+]]
161; CHECK:       neg x0, [[CNT]]
162; CHECK-NEXT:  ret
163define i32 @cntw_neg() nounwind {
164  %vscale = call i32 @llvm.vscale.i32()
165  %1 = mul nsw i32 %vscale, -4
166  ret i32 %1
167}
168
169;
170; CNTD
171;
172
173; CHECK-LABEL: cntd:
174; CHECK:       cntd x0{{$}}
175; CHECK-NEXT:  ret
176define i32 @cntd() nounwind {
177  %vscale = call i32 @llvm.vscale.i32()
178  %1 = shl nsw i32 %vscale, 1
179  ret i32 %1
180}
181
182; CHECK-LABEL: cntd_max:
183; CHECK:       cntd x0, all, mul #15
184; CHECK-NEXT:  ret
185define i32 @cntd_max() nounwind {
186  %vscale = call i32 @llvm.vscale.i32()
187  %1 = mul nsw i32 %vscale, 30
188  ret i32 %1
189}
190
191; CHECK-LABEL: cntd_neg:
192; CHECK:       cntd [[CNT:x[0-9]+]]
193; CHECK:       neg x0, [[CNT]]
194; CHECK-NEXT:  ret
195define i32 @cntd_neg() nounwind {
196  %vscale = call i32 @llvm.vscale.i32()
197  %1 = mul nsw i32 %vscale, -2
198  ret i32 %1
199}
200
201declare i8 @llvm.vscale.i8()
202declare i16 @llvm.vscale.i16()
203declare i32 @llvm.vscale.i32()
204declare i64 @llvm.vscale.i64()
205