xref: /llvm-project/llvm/test/Transforms/InstCombine/broadcast.ll (revision 9d4557920f1008b64300928c4696bf22e923f71f)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4define <4 x float> @good1(float %arg) {
5; CHECK-LABEL: @good1(
6; CHECK-NEXT:    [[T:%.*]] = insertelement <4 x float> poison, float [[ARG:%.*]], i64 0
7; CHECK-NEXT:    [[T6:%.*]] = shufflevector <4 x float> [[T]], <4 x float> poison, <4 x i32> zeroinitializer
8; CHECK-NEXT:    ret <4 x float> [[T6]]
9;
10  %t = insertelement <4 x float> undef, float %arg, i32 0
11  %t4 = insertelement <4 x float> %t, float %arg, i32 1
12  %t5 = insertelement <4 x float> %t4, float %arg, i32 2
13  %t6 = insertelement <4 x float> %t5, float %arg, i32 3
14  ret <4 x float> %t6
15}
16
17define <4 x float> @good2(float %arg) {
18; CHECK-LABEL: @good2(
19; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <4 x float> poison, float [[ARG:%.*]], i64 0
20; CHECK-NEXT:    [[T6:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <4 x i32> zeroinitializer
21; CHECK-NEXT:    ret <4 x float> [[T6]]
22;
23  %t = insertelement <4 x float> undef, float %arg, i32 1
24  %t4 = insertelement <4 x float> %t, float %arg, i32 2
25  %t5 = insertelement <4 x float> %t4, float %arg, i32 0
26  %t6 = insertelement <4 x float> %t5, float %arg, i32 3
27  ret <4 x float> %t6
28}
29
30define <4 x float> @good3(float %arg) {
31; CHECK-LABEL: @good3(
32; CHECK-NEXT:    [[T:%.*]] = insertelement <4 x float> poison, float [[ARG:%.*]], i64 0
33; CHECK-NEXT:    [[T6:%.*]] = shufflevector <4 x float> [[T]], <4 x float> poison, <4 x i32> zeroinitializer
34; CHECK-NEXT:    ret <4 x float> [[T6]]
35;
36  %t = insertelement <4 x float> zeroinitializer, float %arg, i32 0
37  %t4 = insertelement <4 x float> %t, float %arg, i32 1
38  %t5 = insertelement <4 x float> %t4, float %arg, i32 2
39  %t6 = insertelement <4 x float> %t5, float %arg, i32 3
40  ret <4 x float> %t6
41}
42
43define <4 x float> @good4(float %arg) {
44; CHECK-LABEL: @good4(
45; CHECK-NEXT:    [[T:%.*]] = insertelement <4 x float> poison, float [[ARG:%.*]], i64 0
46; CHECK-NEXT:    [[TMP1:%.*]] = fadd <4 x float> [[T]], [[T]]
47; CHECK-NEXT:    [[T7:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <4 x i32> zeroinitializer
48; CHECK-NEXT:    ret <4 x float> [[T7]]
49;
50  %t = insertelement <4 x float> zeroinitializer, float %arg, i32 0
51  %t4 = insertelement <4 x float> %t, float %arg, i32 1
52  %t5 = insertelement <4 x float> %t4, float %arg, i32 2
53  %t6 = insertelement <4 x float> %t5, float %arg, i32 3
54  %t7 = fadd <4 x float> %t6, %t6
55  ret <4 x float> %t7
56}
57
58define <4 x float> @good5(float %v) {
59; CHECK-LABEL: @good5(
60; CHECK-NEXT:    [[INS1:%.*]] = insertelement <4 x float> <float poison, float undef, float undef, float undef>, float [[V:%.*]], i64 0
61; CHECK-NEXT:    [[A1:%.*]] = fadd <4 x float> [[INS1]], [[INS1]]
62; CHECK-NEXT:    [[INS4:%.*]] = shufflevector <4 x float> [[INS1]], <4 x float> poison, <4 x i32> zeroinitializer
63; CHECK-NEXT:    [[RES:%.*]] = fadd <4 x float> [[A1]], [[INS4]]
64; CHECK-NEXT:    ret <4 x float> [[RES]]
65;
66  %ins1 = insertelement <4 x float> undef, float %v, i32 0
67  %a1 = fadd <4 x float> %ins1, %ins1
68  %ins2 = insertelement<4 x float> %ins1, float %v, i32 1
69  %ins3 = insertelement<4 x float> %ins2, float %v, i32 2
70  %ins4 = insertelement<4 x float> %ins3, float %v, i32 3
71  %res = fadd <4 x float> %a1, %ins4
72  ret <4 x float> %res
73}
74
75; The insert is changed to allow the canonical shuffle-splat pattern from element 0.
76
77define <4 x float> @splat_undef1(float %arg) {
78; CHECK-LABEL: @splat_undef1(
79; CHECK-NEXT:    [[T4:%.*]] = insertelement <4 x float> <float undef, float poison, float poison, float poison>, float [[ARG:%.*]], i64 1
80; CHECK-NEXT:    [[T5:%.*]] = insertelement <4 x float> [[T4]], float [[ARG]], i64 2
81; CHECK-NEXT:    [[T6:%.*]] = insertelement <4 x float> [[T5]], float [[ARG]], i64 3
82; CHECK-NEXT:    ret <4 x float> [[T6]]
83;
84  %t = insertelement <4 x float> undef, float %arg, i32 1
85  %t4 = insertelement <4 x float> %t, float %arg, i32 1
86  %t5 = insertelement <4 x float> %t4, float %arg, i32 2
87  %t6 = insertelement <4 x float> %t5, float %arg, i32 3
88  ret <4 x float> %t6
89}
90
91; Re-uses the existing first insertelement.
92
93define <4 x float> @splat_undef2(float %arg) {
94; CHECK-LABEL: @splat_undef2(
95; CHECK-NEXT:    [[T:%.*]] = insertelement <4 x float> <float poison, float undef, float poison, float poison>, float [[ARG:%.*]], i64 0
96; CHECK-NEXT:    [[T5:%.*]] = insertelement <4 x float> [[T]], float [[ARG]], i64 2
97; CHECK-NEXT:    [[T6:%.*]] = insertelement <4 x float> [[T5]], float [[ARG]], i64 3
98; CHECK-NEXT:    ret <4 x float> [[T6]]
99;
100  %t = insertelement <4 x float> undef, float %arg, i32 0
101  %t5 = insertelement <4 x float> %t, float %arg, i32 2
102  %t6 = insertelement <4 x float> %t5, float %arg, i32 3
103  ret <4 x float> %t6
104}
105
106define <4 x float> @bad3(float %arg, float %arg2) {
107; CHECK-LABEL: @bad3(
108; CHECK-NEXT:    [[T:%.*]] = insertelement <4 x float> poison, float [[ARG:%.*]], i64 0
109; CHECK-NEXT:    [[T4:%.*]] = insertelement <4 x float> [[T]], float [[ARG2:%.*]], i64 1
110; CHECK-NEXT:    [[T5:%.*]] = insertelement <4 x float> [[T4]], float [[ARG]], i64 2
111; CHECK-NEXT:    [[T6:%.*]] = insertelement <4 x float> [[T5]], float [[ARG]], i64 3
112; CHECK-NEXT:    ret <4 x float> [[T6]]
113;
114  %t = insertelement <4 x float> undef, float %arg, i32 0
115  %t4 = insertelement <4 x float> %t, float %arg2, i32 1
116  %t5 = insertelement <4 x float> %t4, float %arg, i32 2
117  %t6 = insertelement <4 x float> %t5, float %arg, i32 3
118  ret <4 x float> %t6
119}
120
121define <1 x float> @bad4(float %arg) {
122; CHECK-LABEL: @bad4(
123; CHECK-NEXT:    [[T:%.*]] = insertelement <1 x float> poison, float [[ARG:%.*]], i64 0
124; CHECK-NEXT:    ret <1 x float> [[T]]
125;
126  %t = insertelement <1 x float> undef, float %arg, i32 0
127  ret <1 x float> %t
128}
129
130; Multiple undef elements are ok.
131; TODO: Multiple uses triggers the transform at %t4, but we should sink/scalarize/CSE the splats?
132
133define <4 x float> @splat_undef3(float %arg) {
134; CHECK-LABEL: @splat_undef3(
135; CHECK-NEXT:    [[T:%.*]] = insertelement <4 x float> <float poison, float poison, float undef, float undef>, float [[ARG:%.*]], i64 0
136; CHECK-NEXT:    [[T4:%.*]] = insertelement <4 x float> [[T]], float [[ARG]], i64 1
137; CHECK-NEXT:    [[T5:%.*]] = insertelement <4 x float> [[T4]], float [[ARG]], i64 2
138; CHECK-NEXT:    [[T6:%.*]] = insertelement <4 x float> [[T5]], float [[ARG]], i64 3
139; CHECK-NEXT:    [[T7:%.*]] = fadd <4 x float> [[T6]], [[T4]]
140; CHECK-NEXT:    ret <4 x float> [[T7]]
141;
142  %t = insertelement <4 x float> undef, float %arg, i32 0
143  %t4 = insertelement <4 x float> %t, float %arg, i32 1
144  %t5 = insertelement <4 x float> %t4, float %arg, i32 2
145  %t6 = insertelement <4 x float> %t5, float %arg, i32 3
146  %t7 = fadd <4 x float> %t6, %t4
147  ret <4 x float> %t7
148}
149
150define <4 x float> @bad6(float %arg, i32 %k) {
151; CHECK-LABEL: @bad6(
152; CHECK-NEXT:    [[T:%.*]] = insertelement <4 x float> <float poison, float poison, float undef, float poison>, float [[ARG:%.*]], i64 0
153; CHECK-NEXT:    [[T4:%.*]] = insertelement <4 x float> [[T]], float [[ARG]], i64 1
154; CHECK-NEXT:    [[T5:%.*]] = insertelement <4 x float> [[T4]], float [[ARG]], i32 [[K:%.*]]
155; CHECK-NEXT:    [[T6:%.*]] = insertelement <4 x float> [[T5]], float [[ARG]], i64 3
156; CHECK-NEXT:    ret <4 x float> [[T6]]
157;
158  %t = insertelement <4 x float> undef, float %arg, i32 0
159  %t4 = insertelement <4 x float> %t, float %arg, i32 1
160  %t5 = insertelement <4 x float> %t4, float %arg, i32 %k
161  %t6 = insertelement <4 x float> %t5, float %arg, i32 3
162  ret <4 x float> %t6
163}
164
165define <4 x float> @bad7(float %v) {
166; CHECK-LABEL: @bad7(
167; CHECK-NEXT:    [[INS1:%.*]] = insertelement <4 x float> <float undef, float poison, float undef, float undef>, float [[V:%.*]], i64 1
168; CHECK-NEXT:    [[A1:%.*]] = fadd <4 x float> [[INS1]], [[INS1]]
169; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <4 x float> [[INS1]], float [[V]], i64 0
170; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <4 x float> [[TMP1]], float [[V]], i64 2
171; CHECK-NEXT:    [[INS4:%.*]] = insertelement <4 x float> [[TMP2]], float [[V]], i64 3
172; CHECK-NEXT:    [[RES:%.*]] = fadd <4 x float> [[A1]], [[INS4]]
173; CHECK-NEXT:    ret <4 x float> [[RES]]
174;
175  %ins1 = insertelement <4 x float> undef, float %v, i32 1
176  %a1 = fadd <4 x float> %ins1, %ins1
177  %ins2 = insertelement<4 x float> %ins1, float %v, i32 2
178  %ins3 = insertelement<4 x float> %ins2, float %v, i32 3
179  %ins4 = insertelement<4 x float> %ins3, float %v, i32 0
180  %res = fadd <4 x float> %a1, %ins4
181  ret <4 x float> %res
182}
183