xref: /aosp_15_r20/external/mesa3d/src/compiler/nir/tests/opt_shrink_vectors_tests.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 Pavel Ondračka
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "nir_test.h"
25 
26 class nir_opt_shrink_vectors_test : public nir_test {
27 protected:
28    nir_opt_shrink_vectors_test();
29 
30    nir_def *in_def;
31    nir_variable *out_var;
32 };
33 
nir_opt_shrink_vectors_test()34 nir_opt_shrink_vectors_test::nir_opt_shrink_vectors_test()
35    : nir_test::nir_test("nir_opt_shrink_vectors_test")
36 {
37    nir_variable *var = nir_variable_create(b->shader, nir_var_shader_in, glsl_vec_type(2), "in");
38    in_def = nir_load_var(b, var);
39 
40    out_var = nir_variable_create(b->shader, nir_var_shader_out, glsl_vec_type(1), "out");
41 }
42 
translate_swizzle(char swz)43 static unsigned translate_swizzle(char swz)
44 {
45    const char *swizzles_dict = "xyzw";
46    const char *extended_swizzles_dict = "abcdefghijklmnop";
47 
48    const char *ptr = strchr(swizzles_dict, swz);
49    if (ptr)
50       return ptr - swizzles_dict;
51    else
52       return strchr(extended_swizzles_dict, swz) - extended_swizzles_dict;
53 }
54 
set_swizzle(nir_alu_src * src,const char * swizzle)55 static void set_swizzle(nir_alu_src * src, const char * swizzle)
56 {
57    unsigned i = 0;
58    while (swizzle[i]) {
59       src->swizzle[i] = translate_swizzle(swizzle[i]);
60       i++;
61    }
62 }
63 
check_swizzle(nir_alu_src * src,const char * swizzle)64 static void check_swizzle(nir_alu_src * src, const char * swizzle)
65 {
66    unsigned i = 0;
67    while (swizzle[i]) {
68       ASSERT_TRUE(src->swizzle[i] == translate_swizzle(swizzle[i]));
69       i++;
70    }
71 }
72 
TEST_F(nir_opt_shrink_vectors_test,opt_shrink_vectors_load_const_trailing_component_only)73 TEST_F(nir_opt_shrink_vectors_test, opt_shrink_vectors_load_const_trailing_component_only)
74 {
75    /* Test that opt_shrink_vectors correctly removes unused trailing channels
76     * of load_const.
77     *
78     * vec4 32 ssa_1 = load_const (1.0, 2.0, 3.0, 4.0)
79     * vec1 32 ssa_2 = fmov ssa_1.x
80     *
81     * to
82     *
83     * vec1 32 ssa_1 = load_const (1.0)
84     * vec1 32 ssa_2 = fmov ssa_1.x
85     */
86 
87    nir_def *imm_vec = nir_imm_vec4(b, 1.0, 2.0, 3.0, 4.0);
88 
89    nir_def *alu_result = nir_build_alu1(b, nir_op_mov, imm_vec);
90    nir_alu_instr *alu_instr = nir_instr_as_alu(alu_result->parent_instr);
91    set_swizzle(&alu_instr->src[0], "x");
92    alu_result->num_components = 1;
93 
94    nir_store_var(b, out_var, alu_result, 1);
95 
96    ASSERT_TRUE(nir_opt_shrink_vectors(b->shader, true));
97 
98    nir_validate_shader(b->shader, NULL);
99 
100    ASSERT_TRUE(imm_vec->num_components == 1);
101    nir_load_const_instr * imm_vec_instr = nir_instr_as_load_const(imm_vec->parent_instr);
102    ASSERT_TRUE(nir_const_value_as_float(imm_vec_instr->value[0], 32) == 1.0);
103 
104    ASSERT_FALSE(nir_opt_shrink_vectors(b->shader, true));
105 }
106 
TEST_F(nir_opt_shrink_vectors_test,opt_shrink_vectors_alu_trailing_component_only)107 TEST_F(nir_opt_shrink_vectors_test, opt_shrink_vectors_alu_trailing_component_only)
108 {
109    /* Test that opt_shrink_vectors correctly removes unused trailing channels
110     * of alus.
111     *
112     * vec4 32 ssa_1 = fmov ssa_0.xyzx
113     * vec1 32 ssa_2 = fmov ssa_1.x
114     *
115     * to
116     *
117     * vec1 32 ssa_1 = fmov ssa_0.x
118     * vec1 32 ssa_2 = fmov ssa_1.x
119     */
120 
121    nir_def *alu_result = nir_build_alu1(b, nir_op_mov, in_def);
122    nir_alu_instr *alu_instr = nir_instr_as_alu(alu_result->parent_instr);
123    alu_result->num_components = 4;
124    set_swizzle(&alu_instr->src[0], "xyxx");
125 
126    nir_def *alu2_result = nir_build_alu1(b, nir_op_mov, alu_result);
127    nir_alu_instr *alu2_instr = nir_instr_as_alu(alu2_result->parent_instr);
128    set_swizzle(&alu2_instr->src[0], "x");
129    alu2_result->num_components = 1;
130 
131    nir_store_var(b, out_var, alu2_result, 1);
132 
133    ASSERT_TRUE(nir_opt_shrink_vectors(b->shader, true));
134 
135    nir_validate_shader(b->shader, NULL);
136 
137    check_swizzle(&alu_instr->src[0], "x");
138    ASSERT_TRUE(alu_result->num_components == 1);
139 
140    ASSERT_FALSE(nir_opt_shrink_vectors(b->shader, true));
141 }
142 
TEST_F(nir_opt_shrink_vectors_test,opt_shrink_vectors_simple)143 TEST_F(nir_opt_shrink_vectors_test, opt_shrink_vectors_simple)
144 {
145    /* Tests that opt_shrink_vectors correctly shrinks a simple case.
146     *
147     * vec4 32 ssa_2 = load_const (3.0, 1.0, 2.0, 1.0)
148     * vec4 32 ssa_3 = fadd ssa_1.xxxy, ssa_2.ywyz
149     * vec1 32 ssa_4 = fdot3 ssa_3.xzw ssa_3.xzw
150     *
151     * to
152     *
153     * vec2 32 ssa_2 = load_const (1.0, 2.0)
154     * vec2 32 ssa_3 = fadd ssa_1, ssa_2
155     * vec1 32 ssa_4 = fdot3 ssa_3.xxy ssa_3.xxy
156     */
157 
158    nir_def *imm_vec = nir_imm_vec4(b, 3.0, 1.0, 2.0, 1.0);
159 
160    nir_def *alu_result = nir_build_alu2(b, nir_op_fadd, in_def, imm_vec);
161    nir_alu_instr *alu_instr = nir_instr_as_alu(alu_result->parent_instr);
162    alu_result->num_components = 4;
163    set_swizzle(&alu_instr->src[0], "xxxy");
164    set_swizzle(&alu_instr->src[1], "ywyz");
165 
166    nir_def *alu2_result = nir_build_alu2(b, nir_op_fdot3, alu_result, alu_result);
167    nir_alu_instr *alu2_instr = nir_instr_as_alu(alu2_result->parent_instr);
168    set_swizzle(&alu2_instr->src[0], "xzw");
169    set_swizzle(&alu2_instr->src[1], "xzw");
170 
171    nir_store_var(b, out_var, alu2_result, 1);
172 
173    ASSERT_TRUE(nir_opt_shrink_vectors(b->shader, true));
174 
175    nir_validate_shader(b->shader, NULL);
176 
177    ASSERT_TRUE(imm_vec->num_components == 2);
178    nir_load_const_instr * imm_vec_instr = nir_instr_as_load_const(imm_vec->parent_instr);
179    ASSERT_TRUE(nir_const_value_as_float(imm_vec_instr->value[0], 32) == 1.0);
180    ASSERT_TRUE(nir_const_value_as_float(imm_vec_instr->value[1], 32) == 2.0);
181 
182    ASSERT_TRUE(alu_result->num_components == 2);
183    check_swizzle(&alu_instr->src[0], "xy");
184    check_swizzle(&alu_instr->src[1], "xy");
185 
186    check_swizzle(&alu2_instr->src[0], "xxy");
187    check_swizzle(&alu2_instr->src[1], "xxy");
188 
189    ASSERT_FALSE(nir_opt_shrink_vectors(b->shader, true));
190 
191    nir_validate_shader(b->shader, NULL);
192 }
193 
TEST_F(nir_opt_shrink_vectors_test,opt_shrink_vectors_vec8)194 TEST_F(nir_opt_shrink_vectors_test, opt_shrink_vectors_vec8)
195 {
196    /* Tests that opt_shrink_vectors correctly shrinks a case
197     * dealing with vec8 shrinking. The shrinking would result in
198     * vec6 for load const and vec7 for fadd and is therefore not allowed,
199     * but check that we still properly reuse the channels and move
200     * the unused channels to the end.
201     *
202     * vec8 32 ssa_2 = load_const (1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 2.0, 6.0)
203     * vec8 32 ssa_3 = fadd ssa_1.xxxxxxxy, ssa_2.afhdefgh
204     * vec1 32 ssa_4 = fdot8 ssa_3.accdefgh ssa_3.accdefgh
205     *
206     * to
207     *
208     * vec8 32 ssa_2 = load_const (1.0, 3.0, 4.0, 5.0, 2.0, 6.0, .., ..))
209     * vec8 32 ssa_3 = fadd ssa_1.xxxxxxy_ ssa_2.afbcdef_
210     * vec1 32 ssa_4 = fdot8 ssa_3.abbcdefg ssa_3.abbcdefg
211     */
212 
213    nir_const_value v[8] = {
214       nir_const_value_for_float(1.0, 32),
215       nir_const_value_for_float(1.0, 32),
216       nir_const_value_for_float(2.0, 32),
217       nir_const_value_for_float(3.0, 32),
218       nir_const_value_for_float(4.0, 32),
219       nir_const_value_for_float(5.0, 32),
220       nir_const_value_for_float(2.0, 32),
221       nir_const_value_for_float(6.0, 32),
222    };
223    nir_def *imm_vec = nir_build_imm(b, 8, 32, v);
224 
225    nir_def *alu_result = nir_build_alu2(b, nir_op_fadd, in_def, imm_vec);
226    nir_alu_instr *alu_instr = nir_instr_as_alu(alu_result->parent_instr);
227    alu_result->num_components = 8;
228    set_swizzle(&alu_instr->src[0], "xxxxxxxy");
229    set_swizzle(&alu_instr->src[1], "afhdefgh");
230 
231    nir_def *alu2_result = nir_build_alu2(b, nir_op_fdot8, alu_result, alu_result);
232    nir_alu_instr *alu2_instr = nir_instr_as_alu(alu2_result->parent_instr);
233    set_swizzle(&alu2_instr->src[0], "accdefgh");
234    set_swizzle(&alu2_instr->src[1], "accdefgh");
235 
236    nir_store_var(b, out_var, alu2_result, 1);
237 
238    ASSERT_TRUE(nir_opt_shrink_vectors(b->shader, true));
239 
240    nir_validate_shader(b->shader, NULL);
241 
242    ASSERT_TRUE(imm_vec->num_components == 8);
243    nir_load_const_instr * imm_vec_instr = nir_instr_as_load_const(imm_vec->parent_instr);
244    ASSERT_TRUE(nir_const_value_as_float(imm_vec_instr->value[0], 32) == 1.0);
245    ASSERT_TRUE(nir_const_value_as_float(imm_vec_instr->value[1], 32) == 3.0);
246    ASSERT_TRUE(nir_const_value_as_float(imm_vec_instr->value[2], 32) == 4.0);
247    ASSERT_TRUE(nir_const_value_as_float(imm_vec_instr->value[3], 32) == 5.0);
248    ASSERT_TRUE(nir_const_value_as_float(imm_vec_instr->value[4], 32) == 2.0);
249    ASSERT_TRUE(nir_const_value_as_float(imm_vec_instr->value[5], 32) == 6.0);
250 
251    ASSERT_TRUE(alu_result->num_components == 8);
252    check_swizzle(&alu_instr->src[0], "xxxxxxy");
253    check_swizzle(&alu_instr->src[1], "afbcdef");
254 
255    check_swizzle(&alu2_instr->src[0], "abbcdefg");
256    check_swizzle(&alu2_instr->src[1], "abbcdefg");
257 
258    ASSERT_FALSE(nir_opt_shrink_vectors(b->shader, true));
259 
260    nir_validate_shader(b->shader, NULL);
261 }
262 
TEST_F(nir_opt_shrink_vectors_test,opt_shrink_phis_loop_simple)263 TEST_F(nir_opt_shrink_vectors_test, opt_shrink_phis_loop_simple)
264 {
265    /* Test that the phi is shrinked in the following case.
266     *
267     *    v = vec4(0.0, 0.0, 0.0, 0.0);
268     *    while (v.y < 3) {
269     *       v.y += 1.0;
270     *    }
271     *
272     * This mimics nir for loops that come out of nine+ttn.
273     */
274    nir_def *v = nir_imm_vec4(b, 0.0, 0.0, 0.0, 0.0);
275    nir_def *increment = nir_imm_float(b, 1.0);
276    nir_def *loop_max = nir_imm_float(b, 3.0);
277 
278    nir_phi_instr *const phi = nir_phi_instr_create(b->shader);
279    nir_def *phi_def = &phi->def;
280 
281    nir_loop *loop = nir_push_loop(b);
282 
283    nir_def_init(&phi->instr, &phi->def, v->num_components, v->bit_size);
284 
285    nir_phi_instr_add_src(phi, v->parent_instr->block, v);
286 
287    nir_def *fge = nir_fge(b, phi_def, loop_max);
288    nir_alu_instr *fge_alu_instr = nir_instr_as_alu(fge->parent_instr);
289    fge->num_components = 1;
290    fge_alu_instr->src[0].swizzle[0] = 1;
291 
292    nir_if *nif = nir_push_if(b, fge);
293    {
294       nir_jump_instr *jump = nir_jump_instr_create(b->shader, nir_jump_break);
295       nir_builder_instr_insert(b, &jump->instr);
296    }
297    nir_pop_if(b, nif);
298 
299    nir_def *fadd = nir_fadd(b, phi_def, increment);
300    nir_alu_instr *fadd_alu_instr = nir_instr_as_alu(fadd->parent_instr);
301    fadd->num_components = 1;
302    fadd_alu_instr->src[0].swizzle[0] = 1;
303 
304    nir_scalar srcs[4] = {{0}};
305    for (unsigned i = 0; i < 4; i++) {
306       srcs[i] = nir_get_scalar(phi_def, i);
307    }
308    srcs[1] = nir_get_scalar(fadd, 0);
309    nir_def *vec = nir_vec_scalars(b, srcs, 4);
310 
311    nir_phi_instr_add_src(phi, vec->parent_instr->block, vec);
312 
313    nir_pop_loop(b, loop);
314 
315    b->cursor = nir_before_block(nir_loop_first_block(loop));
316    nir_builder_instr_insert(b, &phi->instr);
317 
318    /* Generated nir:
319     *
320     * impl main {
321     *         block block_0:
322     *         * preds: *
323     *         vec1 32 ssa_0 = deref_var &in (shader_in vec2)
324     *         vec2 32 ssa_1 = intrinsic load_deref (ssa_0) (access=0)
325     *         vec4 32 ssa_2 = load_const (0x00000000, 0x00000000, 0x00000000, 0x00000000) = (0.000000, 0.000000, 0.000000, 0.000000)
326     *         vec1 32 ssa_3 = load_const (0x3f800000 = 1.000000)
327     *         vec1 32 ssa_4 = load_const (0x40400000 = 3.000000)
328     *         * succs: block_1 *
329     *         loop {
330     *                 block block_1:
331     *                 * preds: block_0 block_4 *
332     *                 vec4 32 ssa_8 = phi block_0: ssa_2, block_4: ssa_7
333     *                 vec1  1 ssa_5 = fge ssa_8.y, ssa_4
334     *                 * succs: block_2 block_3 *
335     *                 if ssa_5 {
336     *                         block block_2:
337     *                         * preds: block_1 *
338     *                         break
339     *                         * succs: block_5 *
340     *                 } else {
341     *                         block block_3:
342     *                         * preds: block_1 *
343     *                         * succs: block_4 *
344     *                 }
345     *                 block block_4:
346     *                 * preds: block_3 *
347     *                 vec1 32 ssa_6 = fadd ssa_8.y, ssa_3
348     *                 vec4 32 ssa_7 = vec4 ssa_8.x, ssa_6, ssa_8.z, ssa_8.w
349     *                 * succs: block_1 *
350     *         }
351     *         block block_5:
352     *         * preds: block_2 *
353     *         * succs: block_6 *
354     *         block block_6:
355     * }
356     */
357 
358    nir_validate_shader(b->shader, NULL);
359 
360    ASSERT_TRUE(nir_opt_shrink_vectors(b->shader, true));
361    ASSERT_TRUE(phi_def->num_components == 1);
362    check_swizzle(&fge_alu_instr->src[0], "x");
363    check_swizzle(&fadd_alu_instr->src[0], "x");
364 
365    nir_validate_shader(b->shader, NULL);
366 }
367 
TEST_F(nir_opt_shrink_vectors_test,opt_shrink_phis_loop_swizzle)368 TEST_F(nir_opt_shrink_vectors_test, opt_shrink_phis_loop_swizzle)
369 {
370    /* Test that the phi is shrinked properly in the following case where
371     * some swizzling happens in the channels.
372     *
373     *    v = vec4(0.0, 0.0, 0.0, 0.0);
374     *    while (v.z < 3) {
375     *       v = vec4(v.x, v.z + 1, v.y, v.w};
376     *    }
377     */
378    nir_def *v = nir_imm_vec4(b, 0.0, 0.0, 0.0, 0.0);
379    nir_def *increment = nir_imm_float(b, 1.0);
380    nir_def *loop_max = nir_imm_float(b, 3.0);
381 
382    nir_phi_instr *const phi = nir_phi_instr_create(b->shader);
383    nir_def *phi_def = &phi->def;
384 
385    nir_loop *loop = nir_push_loop(b);
386 
387    nir_def_init(&phi->instr, &phi->def, v->num_components, v->bit_size);
388 
389    nir_phi_instr_add_src(phi, v->parent_instr->block, v);
390 
391    nir_def *fge = nir_fge(b, phi_def, loop_max);
392    nir_alu_instr *fge_alu_instr = nir_instr_as_alu(fge->parent_instr);
393    fge->num_components = 1;
394    fge_alu_instr->src[0].swizzle[0] = 2;
395 
396    nir_if *nif = nir_push_if(b, fge);
397 
398       nir_jump_instr *jump = nir_jump_instr_create(b->shader, nir_jump_break);
399       nir_builder_instr_insert(b, &jump->instr);
400 
401    nir_pop_if(b, nif);
402 
403    nir_def *fadd = nir_fadd(b, phi_def, increment);
404    nir_alu_instr *fadd_alu_instr = nir_instr_as_alu(fadd->parent_instr);
405    fadd->num_components = 1;
406    fadd_alu_instr->src[0].swizzle[0] = 2;
407 
408    nir_scalar srcs[4] = {{0}};
409    srcs[0] = nir_get_scalar(phi_def, 0);
410    srcs[1] = nir_get_scalar(fadd, 0);
411    srcs[2] = nir_get_scalar(phi_def, 1);
412    srcs[3] = nir_get_scalar(phi_def, 3);
413    nir_def *vec = nir_vec_scalars(b, srcs, 4);
414 
415    nir_phi_instr_add_src(phi, vec->parent_instr->block, vec);
416 
417    nir_pop_loop(b, loop);
418 
419    b->cursor = nir_before_block(nir_loop_first_block(loop));
420    nir_builder_instr_insert(b, &phi->instr);
421 
422    /* Generated nir:
423     *
424     * impl main {
425     *         block block_0:
426     *         * preds: *
427     *         vec1 32 ssa_0 = deref_var &in (shader_in vec2)
428     *         vec2 32 ssa_1 = intrinsic load_deref (ssa_0) (access=0)
429     *         vec4 32 ssa_2 = load_const (0x00000000, 0x00000000, 0x00000000, 0x00000000) = (0.000000, 0.000000, 0.000000, 0.000000)
430     *         vec1 32 ssa_3 = load_const (0x3f800000 = 1.000000)
431     *         vec1 32 ssa_4 = load_const (0x40400000 = 3.000000)
432     *         * succs: block_1 *
433     *         loop {
434     *                 block block_1:
435     *                 * preds: block_0 block_4 *
436     *                 vec4 32 ssa_8 = phi block_0: ssa_2, block_4: ssa_7
437     *                 vec1  1 ssa_5 = fge ssa_8.z, ssa_4
438     *                 * succs: block_2 block_3 *
439     *                 if ssa_5 {
440     *                         block block_2:
441     *                         * preds: block_1 *
442     *                         break
443     *                         * succs: block_5 *
444     *                 } else {
445     *                         block block_3:
446     *                         * preds: block_1 *
447     *                         * succs: block_4 *
448     *                 }
449     *                 block block_4:
450     *                 * preds: block_3 *
451     *                 vec1 32 ssa_6 = fadd ssa_8.z, ssa_3
452     *                 vec4 32 ssa_7 = vec4 ssa_8.x, ssa_6, ssa_8.y, ssa_8.w
453     *                 * succs: block_1 *
454     *         }
455     *         block block_5:
456     *         * preds: block_2 *
457     *         * succs: block_6 *
458     *         block block_6:
459     * }
460     */
461 
462    nir_validate_shader(b->shader, NULL);
463 
464    ASSERT_TRUE(nir_opt_shrink_vectors(b->shader, true));
465    ASSERT_TRUE(phi_def->num_components == 2);
466 
467    check_swizzle(&fge_alu_instr->src[0], "y");
468    check_swizzle(&fadd_alu_instr->src[0], "y");
469 
470    nir_validate_shader(b->shader, NULL);
471 }
472 
TEST_F(nir_opt_shrink_vectors_test,opt_shrink_phis_loop_phi_out)473 TEST_F(nir_opt_shrink_vectors_test, opt_shrink_phis_loop_phi_out)
474 {
475    /* Test that the phi is not shrinked when used by intrinsic.
476     *
477     *    v = vec4(0.0, 0.0, 0.0, 0.0);
478     *    while (v.y < 3) {
479     *       v.y += 1.0;
480     *    }
481     *    out = v;
482     */
483    nir_def *v = nir_imm_vec4(b, 0.0, 0.0, 0.0, 0.0);
484    nir_def *increment = nir_imm_float(b, 1.0);
485    nir_def *loop_max = nir_imm_float(b, 3.0);
486 
487    nir_phi_instr *const phi = nir_phi_instr_create(b->shader);
488    nir_def *phi_def = &phi->def;
489 
490    nir_loop *loop = nir_push_loop(b);
491 
492    nir_def_init(&phi->instr, &phi->def, v->num_components, v->bit_size);
493 
494    nir_phi_instr_add_src(phi, v->parent_instr->block, v);
495 
496    nir_def *fge = nir_fge(b, phi_def, loop_max);
497    nir_alu_instr *fge_alu_instr = nir_instr_as_alu(fge->parent_instr);
498    fge->num_components = 1;
499    fge_alu_instr->src[0].swizzle[0] = 1;
500 
501    nir_if *nif = nir_push_if(b, fge);
502    {
503       nir_jump_instr *jump = nir_jump_instr_create(b->shader, nir_jump_break);
504       nir_builder_instr_insert(b, &jump->instr);
505    }
506    nir_pop_if(b, nif);
507 
508    nir_def *fadd = nir_fadd(b, phi_def, increment);
509    nir_alu_instr *fadd_alu_instr = nir_instr_as_alu(fadd->parent_instr);
510    fadd->num_components = 1;
511    fadd_alu_instr->src[0].swizzle[0] = 1;
512 
513    nir_scalar srcs[4] = {{0}};
514    for (unsigned i = 0; i < 4; i++) {
515       srcs[i] = nir_get_scalar(phi_def, i);
516    }
517    srcs[1] = nir_get_scalar(fadd, 0);
518    nir_def *vec = nir_vec_scalars(b, srcs, 4);
519 
520    nir_phi_instr_add_src(phi, vec->parent_instr->block, vec);
521 
522    nir_pop_loop(b, loop);
523 
524    out_var = nir_variable_create(b->shader,
525                                  nir_var_shader_out,
526                                  glsl_vec_type(4), "out4");
527 
528    nir_store_var(b, out_var, phi_def, BITFIELD_MASK(4));
529 
530    b->cursor = nir_before_block(nir_loop_first_block(loop));
531    nir_builder_instr_insert(b, &phi->instr);
532 
533    /* Generated nir:
534     *
535     * impl main {
536     *         block block_0:
537     *         * preds: *
538     *         vec1 32 ssa_0 = deref_var &in (shader_in vec2)
539     *         vec2 32 ssa_1 = intrinsic load_deref (ssa_0) (access=0)
540     *         vec4 32 ssa_2 = load_const (0x00000000, 0x00000000, 0x00000000, 0x00000000) = (0.000000, 0.000000, 0.000000, 0.000000)
541     *         vec1 32 ssa_3 = load_const (0x3f800000 = 1.000000)
542     *         vec1 32 ssa_4 = load_const (0x40400000 = 3.000000)
543     *         * succs: block_1 *
544     *         loop {
545     *                 block block_1:
546     *                 * preds: block_0 block_4 *
547     *                 vec4 32 ssa_9 = phi block_0: ssa_2, block_4: ssa_7
548     *                 vec1  1 ssa_5 = fge ssa_9.y, ssa_4
549     *                 * succs: block_2 block_3 *
550     *                 if ssa_5 {
551     *                         block block_2:
552     *                         * preds: block_1 *
553     *                         break
554     *                         * succs: block_5 *
555     *                 } else {
556     *                         block block_3:
557     *                         * preds: block_1 *
558     *                         * succs: block_4 *
559     *                 }
560     *                 block block_4:
561     *                 * preds: block_3 *
562     *                 vec1 32 ssa_6 = fadd ssa_9.y, ssa_3
563     *                 vec4 32 ssa_7 = vec4 ssa_9.x, ssa_6, ssa_9.z, ssa_9.w
564     *                 * succs: block_1 *
565     *         }
566     *         block block_5:
567     *         * preds: block_2 *
568     *         vec1 32 ssa_8 = deref_var &out4 (shader_out vec4)
569     *         intrinsic store_deref (ssa_8, ssa_9) (wrmask=xyzw *15*, access=0)
570     *         * succs: block_6 *
571     *         block block_6:
572     * }
573     */
574 
575    nir_validate_shader(b->shader, NULL);
576 
577    ASSERT_FALSE(nir_opt_shrink_vectors(b->shader, true));
578    ASSERT_TRUE(phi_def->num_components == 4);
579 }
580