1; RUN: llc -mtriple=aarch64--linux-gnu -mattr=+sve --asm-verbose=false < %s 2>%t |FileCheck %s
2; RUN: FileCheck --check-prefix=WARN --allow-empty %s <%t
3
4; If this check fails please read test/CodeGen/AArch64/README for instructions on how to resolve it.
5; WARN-NOT: warning
6
7declare i32 @llvm.vscale.i32()
8declare i64 @llvm.vscale.i64()
9
10; Fold (add (vscale * C0), (vscale * C1)) to (vscale * (C0 + C1)).
11define i64 @combine_add_vscale_i64() nounwind {
12; CHECK-LABEL: combine_add_vscale_i64:
13; CHECK-NOT:   add
14; CHECK-NEXT:  cntd  x0
15; CHECK-NEXT:  ret
16 %vscale = call i64 @llvm.vscale.i64()
17 %add = add i64 %vscale, %vscale
18 ret i64 %add
19}
20
21define i32 @combine_add_vscale_i32() nounwind {
22; CHECK-LABEL: combine_add_vscale_i32:
23; CHECK-NOT:   add
24; CHECK-NEXT:  cntd  x0
25; CHECK-NEXT:  ret
26 %vscale = call i32 @llvm.vscale.i32()
27 %add = add i32 %vscale, %vscale
28 ret i32 %add
29}
30
31; Fold (mul (vscale * C0), C1) to (vscale * (C0 * C1)).
32; In this test, C0 = 1, C1 = 32.
33define i64 @combine_mul_vscale_i64() nounwind {
34; CHECK-LABEL: combine_mul_vscale_i64:
35; CHECK-NOT:   mul
36; CHECK-NEXT:  rdvl  x0, #2
37; CHECK-NEXT:  ret
38 %vscale = call i64 @llvm.vscale.i64()
39 %mul = mul i64 %vscale, 32
40 ret i64 %mul
41}
42
43define i32 @combine_mul_vscale_i32() nounwind {
44; CHECK-LABEL: combine_mul_vscale_i32:
45; CHECK-NOT:   mul
46; CHECK-NEXT:  rdvl  x0, #3
47; CHECK-NEXT:  ret
48 %vscale = call i32 @llvm.vscale.i32()
49 %mul = mul i32 %vscale, 48
50 ret i32 %mul
51}
52
53; Canonicalize (sub X, (vscale * C)) to (add X,  (vscale * -C))
54define i64 @combine_sub_vscale_i64(i64 %in) nounwind {
55; CHECK-LABEL: combine_sub_vscale_i64:
56; CHECK-NOT:   sub
57; CHECK-NEXT:  rdvl  x8, #-1
58; CHECK-NEXT:  asr   x8, x8, #4
59; CHECK-NEXT:  add   x0, x0, x8
60; CHECK-NEXT:  ret
61 %vscale = call i64 @llvm.vscale.i64()
62 %sub = sub i64 %in,  %vscale
63 ret i64 %sub
64}
65
66define i32 @combine_sub_vscale_i32(i32 %in) nounwind {
67; CHECK-LABEL: combine_sub_vscale_i32:
68; CHECK-NOT:   sub
69; CHECK-NEXT:  rdvl  x8, #-1
70; CHECK-NEXT:  asr   x8, x8, #4
71; CHECK-NEXT:  add   w0, w0, w8
72; CHECK-NEXT:  ret
73 %vscale = call i32 @llvm.vscale.i32()
74 %sub = sub i32 %in, %vscale
75 ret i32 %sub
76}
77
78; Fold (shl (vscale * C0), C1) to (vscale * (C0 << C1)).
79; C0 = 1 , C1 = 4
80; At IR level,  %shl = 2^4 * VSCALE.
81; At Assembly level, the output of RDVL is also 2^4 * VSCALE.
82; Hence, the immediate for RDVL is #1.
83define i64 @combine_shl_vscale_i64() nounwind {
84; CHECK-LABEL: combine_shl_vscale_i64:
85; CHECK-NOT:   shl
86; CHECK-NEXT:  rdvl  x0, #1
87; CHECK-NEXT:  ret
88 %vscale = call i64 @llvm.vscale.i64()
89 %shl = shl i64 %vscale, 4
90 ret i64 %shl
91}
92
93define i32 @combine_shl_vscale_i32() nounwind {
94; CHECK-LABEL: combine_shl_vscale_i32:
95; CHECK-NOT:   shl
96; CHECK-NEXT:  rdvl  x0, #1
97; CHECK-NEXT:  ret
98 %vscale = call i32 @llvm.vscale.i32()
99 %shl = shl i32 %vscale, 4
100 ret i32 %shl
101}
102