1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; llvm.experimental.vector.insert canonicalizes to shufflevector in the fixed case. In the
5; scalable case, we lower to the INSERT_SUBVECTOR ISD node.
6
7declare <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 %idx)
8declare <8 x i32> @llvm.experimental.vector.insert.v8i32.v3i32(<8 x i32> %vec, <3 x i32> %subvec, i64 %idx)
9declare <8 x i32> @llvm.experimental.vector.insert.v8i32.v4i32(<8 x i32> %vec, <4 x i32> %subvec, i64 %idx)
10declare <8 x i32> @llvm.experimental.vector.insert.v8i32.v8i32(<8 x i32> %vec, <8 x i32> %subvec, i64 %idx)
11declare <vscale x 4 x i32> @llvm.experimental.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> %vec, <4 x i32> %subvec, i64 %idx)
12
13; ============================================================================ ;
14; Trivial cases
15; ============================================================================ ;
16
17; An insert that entirely overwrites an <n x ty> with another <n x ty> is a
18; nop.
19define <8 x i32> @trivial_nop(<8 x i32> %vec, <8 x i32> %subvec) {
20; CHECK-LABEL: @trivial_nop(
21; CHECK-NEXT:    ret <8 x i32> [[SUBVEC:%.*]]
22;
23  %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v8i32(<8 x i32> %vec, <8 x i32> %subvec, i64 0)
24  ret <8 x i32> %1
25}
26
27; ============================================================================ ;
28; Valid canonicalizations
29; ============================================================================ ;
30
31define <8 x i32> @valid_insertion_a(<8 x i32> %vec, <2 x i32> %subvec) {
32; CHECK-LABEL: @valid_insertion_a(
33; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <2 x i32> [[SUBVEC:%.*]], <2 x i32> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
34; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> [[VEC:%.*]], <8 x i32> <i32 0, i32 1, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
35; CHECK-NEXT:    ret <8 x i32> [[TMP2]]
36;
37  %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 0)
38  ret <8 x i32> %1
39}
40
41define <8 x i32> @valid_insertion_b(<8 x i32> %vec, <2 x i32> %subvec) {
42; CHECK-LABEL: @valid_insertion_b(
43; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <2 x i32> [[SUBVEC:%.*]], <2 x i32> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
44; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 8, i32 9, i32 4, i32 5, i32 6, i32 7>
45; CHECK-NEXT:    ret <8 x i32> [[TMP2]]
46;
47  %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 2)
48  ret <8 x i32> %1
49}
50
51define <8 x i32> @valid_insertion_c(<8 x i32> %vec, <2 x i32> %subvec) {
52; CHECK-LABEL: @valid_insertion_c(
53; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <2 x i32> [[SUBVEC:%.*]], <2 x i32> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
54; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 6, i32 7>
55; CHECK-NEXT:    ret <8 x i32> [[TMP2]]
56;
57  %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 4)
58  ret <8 x i32> %1
59}
60
61define <8 x i32> @valid_insertion_d(<8 x i32> %vec, <2 x i32> %subvec) {
62; CHECK-LABEL: @valid_insertion_d(
63; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <2 x i32> [[SUBVEC:%.*]], <2 x i32> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
64; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 8, i32 9>
65; CHECK-NEXT:    ret <8 x i32> [[TMP2]]
66;
67  %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v2i32(<8 x i32> %vec, <2 x i32> %subvec, i64 6)
68  ret <8 x i32> %1
69}
70
71define <8 x i32> @valid_insertion_e(<8 x i32> %vec, <4 x i32> %subvec) {
72; CHECK-LABEL: @valid_insertion_e(
73; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[SUBVEC:%.*]], <4 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
74; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> [[VEC:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
75; CHECK-NEXT:    ret <8 x i32> [[TMP2]]
76;
77  %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v4i32(<8 x i32> %vec, <4 x i32> %subvec, i64 0)
78  ret <8 x i32> %1
79}
80
81define <8 x i32> @valid_insertion_f(<8 x i32> %vec, <4 x i32> %subvec) {
82; CHECK-LABEL: @valid_insertion_f(
83; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[SUBVEC:%.*]], <4 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
84; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
85; CHECK-NEXT:    ret <8 x i32> [[TMP2]]
86;
87  %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v4i32(<8 x i32> %vec, <4 x i32> %subvec, i64 4)
88  ret <8 x i32> %1
89}
90
91define <8 x i32> @valid_insertion_g(<8 x i32> %vec, <3 x i32> %subvec) {
92; CHECK-LABEL: @valid_insertion_g(
93; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <3 x i32> [[SUBVEC:%.*]], <3 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
94; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> [[VEC:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 11, i32 12, i32 13, i32 14, i32 15>
95; CHECK-NEXT:    ret <8 x i32> [[TMP2]]
96;
97  %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v3i32(<8 x i32> %vec, <3 x i32> %subvec, i64 0)
98  ret <8 x i32> %1
99}
100
101define <8 x i32> @valid_insertion_h(<8 x i32> %vec, <3 x i32> %subvec) {
102; CHECK-LABEL: @valid_insertion_h(
103; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <3 x i32> [[SUBVEC:%.*]], <3 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
104; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 8, i32 9, i32 10, i32 6, i32 7>
105; CHECK-NEXT:    ret <8 x i32> [[TMP2]]
106;
107  %1 = call <8 x i32> @llvm.experimental.vector.insert.v8i32.v3i32(<8 x i32> %vec, <3 x i32> %subvec, i64 3)
108  ret <8 x i32> %1
109}
110
111; ============================================================================ ;
112; Scalable cases
113; ============================================================================ ;
114
115; Scalable insertions should not be canonicalized. This will be lowered to the
116; INSERT_SUBVECTOR ISD node later.
117define <vscale x 4 x i32> @scalable_insert(<vscale x 4 x i32> %vec, <4 x i32> %subvec) {
118; CHECK-LABEL: @scalable_insert(
119; CHECK-NEXT:    [[TMP1:%.*]] = call <vscale x 4 x i32> @llvm.experimental.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> [[VEC:%.*]], <4 x i32> [[SUBVEC:%.*]], i64 0)
120; CHECK-NEXT:    ret <vscale x 4 x i32> [[TMP1]]
121;
122  %1 = call <vscale x 4 x i32> @llvm.experimental.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> %vec, <4 x i32> %subvec, i64 0)
123  ret <vscale x 4 x i32> %1
124}
125