1; RUN: opt -S -aarch64-sve-intrinsic-opts < %s | FileCheck %s
2
3target triple = "aarch64-unknown-linux-gnu"
4
5define <vscale x 16 x i1> @pred_load_v2i8(<2 x i8>* %addr) #0 {
6; CHECK-LABEL: @pred_load_v2i8(
7; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i8>* %addr to <vscale x 16 x i1>*
8; CHECK-NEXT:    [[TMP2:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[TMP1]]
9; CHECK-NEXT:    ret <vscale x 16 x i1> [[TMP2]]
10  %load = load <2 x i8>, <2 x i8>* %addr, align 4
11  %insert = tail call <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v2i8(<vscale x 2 x i8> undef, <2 x i8> %load, i64 0)
12  %ret = bitcast <vscale x 2 x i8> %insert to <vscale x 16 x i1>
13  ret <vscale x 16 x i1> %ret
14}
15
16define <vscale x 16 x i1> @pred_load_v4i8(<4 x i8>* %addr) #1 {
17; CHECK-LABEL: @pred_load_v4i8(
18; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i8>* %addr to <vscale x 16 x i1>*
19; CHECK-NEXT:    [[TMP2:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[TMP1]]
20; CHECK-NEXT:    ret <vscale x 16 x i1> [[TMP2]]
21  %load = load <4 x i8>, <4 x i8>* %addr, align 4
22  %insert = tail call <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v4i8(<vscale x 2 x i8> undef, <4 x i8> %load, i64 0)
23  %ret = bitcast <vscale x 2 x i8> %insert to <vscale x 16 x i1>
24  ret <vscale x 16 x i1> %ret
25}
26
27define <vscale x 16 x i1> @pred_load_v8i8(<8 x i8>* %addr) #2 {
28; CHECK-LABEL: @pred_load_v8i8(
29; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i8>* %addr to <vscale x 16 x i1>*
30; CHECK-NEXT:    [[TMP2:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[TMP1]]
31; CHECK-NEXT:    ret <vscale x 16 x i1> [[TMP2]]
32  %load = load <8 x i8>, <8 x i8>* %addr, align 4
33  %insert = tail call <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v8i8(<vscale x 2 x i8> undef, <8 x i8> %load, i64 0)
34  %ret = bitcast <vscale x 2 x i8> %insert to <vscale x 16 x i1>
35  ret <vscale x 16 x i1> %ret
36}
37
38; Ensure the insertion point is at the load
39define <vscale x 16 x i1> @pred_load_insertion_point(<2 x i8>* %addr) #0 {
40; CHECK-LABEL: @pred_load_insertion_point(
41; CHECK-NEXT:  entry:
42; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i8>* %addr to <vscale x 16 x i1>*
43; CHECK-NEXT:    [[TMP2:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[TMP1]]
44; CHECK-NEXT:    br label %bb1
45; CHECK:       bb1:
46; CHECK-NEXT:    ret <vscale x 16 x i1> [[TMP2]]
47entry:
48  %load = load <2 x i8>, <2 x i8>* %addr, align 4
49  br label %bb1
50
51bb1:
52  %insert = tail call <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v2i8(<vscale x 2 x i8> undef, <2 x i8> %load, i64 0)
53  %ret = bitcast <vscale x 2 x i8> %insert to <vscale x 16 x i1>
54  ret <vscale x 16 x i1> %ret
55}
56
57; Check that too small of a vscale prevents optimization
58define <vscale x 16 x i1> @pred_load_neg1(<4 x i8>* %addr) #0 {
59; CHECK-LABEL: @pred_load_neg1(
60; CHECK:         call <vscale x 2 x i8> @llvm.vector.insert
61  %load = load <4 x i8>, <4 x i8>* %addr, align 4
62  %insert = tail call <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v4i8(<vscale x 2 x i8> undef, <4 x i8> %load, i64 0)
63  %ret = bitcast <vscale x 2 x i8> %insert to <vscale x 16 x i1>
64  ret <vscale x 16 x i1> %ret
65}
66
67; Check that too large of a vscale prevents optimization
68define <vscale x 16 x i1> @pred_load_neg2(<4 x i8>* %addr) #2 {
69; CHECK-LABEL: @pred_load_neg2(
70; CHECK:         call <vscale x 2 x i8> @llvm.vector.insert
71  %load = load <4 x i8>, <4 x i8>* %addr, align 4
72  %insert = tail call <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v4i8(<vscale x 2 x i8> undef, <4 x i8> %load, i64 0)
73  %ret = bitcast <vscale x 2 x i8> %insert to <vscale x 16 x i1>
74  ret <vscale x 16 x i1> %ret
75}
76
77; Check that a non-zero index prevents optimization
78define <vscale x 16 x i1> @pred_load_neg3(<4 x i8>* %addr) #1 {
79; CHECK-LABEL: @pred_load_neg3(
80; CHECK:         call <vscale x 2 x i8> @llvm.vector.insert
81  %load = load <4 x i8>, <4 x i8>* %addr, align 4
82  %insert = tail call <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v4i8(<vscale x 2 x i8> undef, <4 x i8> %load, i64 4)
83  %ret = bitcast <vscale x 2 x i8> %insert to <vscale x 16 x i1>
84  ret <vscale x 16 x i1> %ret
85}
86
87; Check that differing vscale min/max prevents optimization
88define <vscale x 16 x i1> @pred_load_neg4(<4 x i8>* %addr) #3 {
89; CHECK-LABEL: @pred_load_neg4(
90; CHECK:         call <vscale x 2 x i8> @llvm.vector.insert
91  %load = load <4 x i8>, <4 x i8>* %addr, align 4
92  %insert = tail call <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v4i8(<vscale x 2 x i8> undef, <4 x i8> %load, i64 0)
93  %ret = bitcast <vscale x 2 x i8> %insert to <vscale x 16 x i1>
94  ret <vscale x 16 x i1> %ret
95}
96
97; Check that insertion into a non-undef vector prevents optimization
98define <vscale x 16 x i1> @pred_load_neg5(<4 x i8>* %addr, <vscale x 2 x i8> %passthru) #1 {
99; CHECK-LABEL: @pred_load_neg5(
100; CHECK:         call <vscale x 2 x i8> @llvm.vector.insert
101  %load = load <4 x i8>, <4 x i8>* %addr, align 4
102  %insert = tail call <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v4i8(<vscale x 2 x i8> %passthru, <4 x i8> %load, i64 0)
103  %ret = bitcast <vscale x 2 x i8> %insert to <vscale x 16 x i1>
104  ret <vscale x 16 x i1> %ret
105}
106
107declare <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v2i8(<vscale x 2 x i8>, <2 x i8>, i64)
108declare <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v4i8(<vscale x 2 x i8>, <4 x i8>, i64)
109declare <vscale x 2 x i8> @llvm.vector.insert.nxv2i8.v8i8(<vscale x 2 x i8>, <8 x i8>, i64)
110
111attributes #0 = { "target-features"="+sve" vscale_range(1,1) }
112attributes #1 = { "target-features"="+sve" vscale_range(2,2) }
113attributes #2 = { "target-features"="+sve" vscale_range(4,4) }
114attributes #3 = { "target-features"="+sve" vscale_range(2,4) }
115