xref: /aosp_15_r20/external/mesa3d/src/compiler/nir/nir_legacy.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2023 Valve Corporation
3*61046927SAndroid Build Coastguard Worker  * Copyright 2020 Collabora, Ltd.
4*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker  */
6*61046927SAndroid Build Coastguard Worker 
7*61046927SAndroid Build Coastguard Worker #include "nir_legacy.h"
8*61046927SAndroid Build Coastguard Worker #include "nir.h"
9*61046927SAndroid Build Coastguard Worker #include "nir_builder.h"
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker bool
nir_legacy_float_mod_folds(nir_alu_instr * mod)12*61046927SAndroid Build Coastguard Worker nir_legacy_float_mod_folds(nir_alu_instr *mod)
13*61046927SAndroid Build Coastguard Worker {
14*61046927SAndroid Build Coastguard Worker    assert(mod->op == nir_op_fabs || mod->op == nir_op_fneg);
15*61046927SAndroid Build Coastguard Worker 
16*61046927SAndroid Build Coastguard Worker    /* No legacy user supports fp64 modifiers */
17*61046927SAndroid Build Coastguard Worker    if (mod->def.bit_size == 64)
18*61046927SAndroid Build Coastguard Worker       return false;
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker    nir_foreach_use_including_if(src, &mod->def) {
21*61046927SAndroid Build Coastguard Worker       if (nir_src_is_if(src))
22*61046927SAndroid Build Coastguard Worker          return false;
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker       nir_instr *parent = nir_src_parent_instr(src);
25*61046927SAndroid Build Coastguard Worker       if (parent->type != nir_instr_type_alu)
26*61046927SAndroid Build Coastguard Worker          return false;
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker       nir_alu_instr *alu = nir_instr_as_alu(parent);
29*61046927SAndroid Build Coastguard Worker       nir_alu_src *alu_src = list_entry(src, nir_alu_src, src);
30*61046927SAndroid Build Coastguard Worker       unsigned src_index = alu_src - alu->src;
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker       assert(src_index < nir_op_infos[alu->op].num_inputs);
33*61046927SAndroid Build Coastguard Worker       nir_alu_type src_type = nir_op_infos[alu->op].input_types[src_index];
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker       if (nir_alu_type_get_base_type(src_type) != nir_type_float)
36*61046927SAndroid Build Coastguard Worker          return false;
37*61046927SAndroid Build Coastguard Worker    }
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker    return true;
40*61046927SAndroid Build Coastguard Worker }
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker static nir_legacy_alu_src
chase_alu_src_helper(const nir_src * src)43*61046927SAndroid Build Coastguard Worker chase_alu_src_helper(const nir_src *src)
44*61046927SAndroid Build Coastguard Worker {
45*61046927SAndroid Build Coastguard Worker    nir_intrinsic_instr *load = nir_load_reg_for_def(src->ssa);
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker    if (load) {
48*61046927SAndroid Build Coastguard Worker       bool indirect = (load->intrinsic == nir_intrinsic_load_reg_indirect);
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker       return (nir_legacy_alu_src){
51*61046927SAndroid Build Coastguard Worker          .src.is_ssa = false,
52*61046927SAndroid Build Coastguard Worker          .src.reg = {
53*61046927SAndroid Build Coastguard Worker             .handle = load->src[0].ssa,
54*61046927SAndroid Build Coastguard Worker             .base_offset = nir_intrinsic_base(load),
55*61046927SAndroid Build Coastguard Worker             .indirect = indirect ? load->src[1].ssa : NULL },
56*61046927SAndroid Build Coastguard Worker          .fabs = nir_intrinsic_legacy_fabs(load),
57*61046927SAndroid Build Coastguard Worker          .fneg = nir_intrinsic_legacy_fneg(load),
58*61046927SAndroid Build Coastguard Worker       };
59*61046927SAndroid Build Coastguard Worker    } else {
60*61046927SAndroid Build Coastguard Worker       return (nir_legacy_alu_src){
61*61046927SAndroid Build Coastguard Worker          .src.is_ssa = true,
62*61046927SAndroid Build Coastguard Worker          .src.ssa = src->ssa,
63*61046927SAndroid Build Coastguard Worker       };
64*61046927SAndroid Build Coastguard Worker    }
65*61046927SAndroid Build Coastguard Worker }
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker static inline bool
chase_source_mod(nir_def ** ssa,nir_op op,uint8_t * swizzle)68*61046927SAndroid Build Coastguard Worker chase_source_mod(nir_def **ssa, nir_op op, uint8_t *swizzle)
69*61046927SAndroid Build Coastguard Worker {
70*61046927SAndroid Build Coastguard Worker    if ((*ssa)->parent_instr->type != nir_instr_type_alu)
71*61046927SAndroid Build Coastguard Worker       return false;
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker    nir_alu_instr *alu = nir_instr_as_alu((*ssa)->parent_instr);
74*61046927SAndroid Build Coastguard Worker    if (alu->op != op)
75*61046927SAndroid Build Coastguard Worker       return false;
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker    /* If there are other uses of the modifier that don't fold, we can't fold it
78*61046927SAndroid Build Coastguard Worker     * here either, in case of it's reading from a load_reg that won't be
79*61046927SAndroid Build Coastguard Worker     * emitted.
80*61046927SAndroid Build Coastguard Worker     */
81*61046927SAndroid Build Coastguard Worker    if (!nir_legacy_float_mod_folds(alu))
82*61046927SAndroid Build Coastguard Worker       return false;
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    /* This only works for unary ops */
85*61046927SAndroid Build Coastguard Worker    assert(nir_op_infos[op].num_inputs == 1);
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    /* To fuse the source mod in, we need to compose the swizzles and string
88*61046927SAndroid Build Coastguard Worker     * through the source.
89*61046927SAndroid Build Coastguard Worker     */
90*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; ++i)
91*61046927SAndroid Build Coastguard Worker       swizzle[i] = alu->src[0].swizzle[swizzle[i]];
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker    *ssa = alu->src[0].src.ssa;
94*61046927SAndroid Build Coastguard Worker    return true;
95*61046927SAndroid Build Coastguard Worker }
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker nir_legacy_alu_src
nir_legacy_chase_alu_src(const nir_alu_src * src,bool fuse_fabs)98*61046927SAndroid Build Coastguard Worker nir_legacy_chase_alu_src(const nir_alu_src *src, bool fuse_fabs)
99*61046927SAndroid Build Coastguard Worker {
100*61046927SAndroid Build Coastguard Worker    if (src->src.ssa->parent_instr->type == nir_instr_type_alu) {
101*61046927SAndroid Build Coastguard Worker       nir_legacy_alu_src out = {
102*61046927SAndroid Build Coastguard Worker          .src.is_ssa = true,
103*61046927SAndroid Build Coastguard Worker          .src.ssa = src->src.ssa,
104*61046927SAndroid Build Coastguard Worker       };
105*61046927SAndroid Build Coastguard Worker       STATIC_ASSERT(sizeof(src->swizzle) == sizeof(out.swizzle));
106*61046927SAndroid Build Coastguard Worker       memcpy(out.swizzle, src->swizzle, sizeof(src->swizzle));
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker       /* To properly handle foo(fneg(fabs(x))), we first chase fneg and then
109*61046927SAndroid Build Coastguard Worker        * fabs, since we chase from bottom-up. We don't handle fabs(fneg(x))
110*61046927SAndroid Build Coastguard Worker        * since nir_opt_algebraic should have eliminated that.
111*61046927SAndroid Build Coastguard Worker        */
112*61046927SAndroid Build Coastguard Worker       out.fneg = chase_source_mod(&out.src.ssa, nir_op_fneg, out.swizzle);
113*61046927SAndroid Build Coastguard Worker       if (fuse_fabs)
114*61046927SAndroid Build Coastguard Worker          out.fabs = chase_source_mod(&out.src.ssa, nir_op_fabs, out.swizzle);
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker       return out;
117*61046927SAndroid Build Coastguard Worker    } else {
118*61046927SAndroid Build Coastguard Worker       nir_legacy_alu_src out = chase_alu_src_helper(&src->src);
119*61046927SAndroid Build Coastguard Worker       memcpy(out.swizzle, src->swizzle, sizeof(src->swizzle));
120*61046927SAndroid Build Coastguard Worker       return out;
121*61046927SAndroid Build Coastguard Worker    }
122*61046927SAndroid Build Coastguard Worker }
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker static nir_legacy_alu_dest
chase_alu_dest_helper(nir_def * def)125*61046927SAndroid Build Coastguard Worker chase_alu_dest_helper(nir_def *def)
126*61046927SAndroid Build Coastguard Worker {
127*61046927SAndroid Build Coastguard Worker    nir_intrinsic_instr *store = nir_store_reg_for_def(def);
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker    if (store) {
130*61046927SAndroid Build Coastguard Worker       bool indirect = (store->intrinsic == nir_intrinsic_store_reg_indirect);
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker       return (nir_legacy_alu_dest){
133*61046927SAndroid Build Coastguard Worker          .dest.is_ssa = false,
134*61046927SAndroid Build Coastguard Worker          .dest.reg = {
135*61046927SAndroid Build Coastguard Worker             .handle = store->src[1].ssa,
136*61046927SAndroid Build Coastguard Worker             .base_offset = nir_intrinsic_base(store),
137*61046927SAndroid Build Coastguard Worker             .indirect = indirect ? store->src[2].ssa : NULL },
138*61046927SAndroid Build Coastguard Worker          .fsat = nir_intrinsic_legacy_fsat(store),
139*61046927SAndroid Build Coastguard Worker          .write_mask = nir_intrinsic_write_mask(store),
140*61046927SAndroid Build Coastguard Worker       };
141*61046927SAndroid Build Coastguard Worker    } else {
142*61046927SAndroid Build Coastguard Worker       return (nir_legacy_alu_dest){
143*61046927SAndroid Build Coastguard Worker          .dest.is_ssa = true,
144*61046927SAndroid Build Coastguard Worker          .dest.ssa = def,
145*61046927SAndroid Build Coastguard Worker          .write_mask = nir_component_mask(def->num_components),
146*61046927SAndroid Build Coastguard Worker       };
147*61046927SAndroid Build Coastguard Worker    }
148*61046927SAndroid Build Coastguard Worker }
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker bool
nir_legacy_fsat_folds(nir_alu_instr * fsat)151*61046927SAndroid Build Coastguard Worker nir_legacy_fsat_folds(nir_alu_instr *fsat)
152*61046927SAndroid Build Coastguard Worker {
153*61046927SAndroid Build Coastguard Worker    assert(fsat->op == nir_op_fsat);
154*61046927SAndroid Build Coastguard Worker    nir_def *def = fsat->src[0].src.ssa;
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    /* No legacy user supports fp64 modifiers */
157*61046927SAndroid Build Coastguard Worker    if (def->bit_size == 64)
158*61046927SAndroid Build Coastguard Worker       return false;
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker    /* Must be the only use */
161*61046927SAndroid Build Coastguard Worker    if (!list_is_singular(&def->uses))
162*61046927SAndroid Build Coastguard Worker       return false;
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker    assert(&fsat->src[0].src ==
165*61046927SAndroid Build Coastguard Worker           list_first_entry(&def->uses, nir_src, use_link));
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker    nir_instr *generate = def->parent_instr;
168*61046927SAndroid Build Coastguard Worker    if (generate->type != nir_instr_type_alu)
169*61046927SAndroid Build Coastguard Worker       return false;
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    nir_alu_instr *generate_alu = nir_instr_as_alu(generate);
172*61046927SAndroid Build Coastguard Worker    nir_alu_type dest_type = nir_op_infos[generate_alu->op].output_type;
173*61046927SAndroid Build Coastguard Worker    if (dest_type != nir_type_float)
174*61046927SAndroid Build Coastguard Worker       return false;
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker    /* If we are a saturating a source modifier fsat(fabs(x)), we need to emit
177*61046927SAndroid Build Coastguard Worker     * either the fsat or the modifier or else the sequence disappears.
178*61046927SAndroid Build Coastguard Worker     */
179*61046927SAndroid Build Coastguard Worker    if (generate_alu->op == nir_op_fabs || generate_alu->op == nir_op_fneg)
180*61046927SAndroid Build Coastguard Worker       return false;
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    /* We can't do expansions without a move in the middle */
183*61046927SAndroid Build Coastguard Worker    unsigned nr_components = generate_alu->def.num_components;
184*61046927SAndroid Build Coastguard Worker    if (fsat->def.num_components != nr_components)
185*61046927SAndroid Build Coastguard Worker       return false;
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker    /* We don't handle swizzles here, so check for the identity */
188*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < nr_components; ++i) {
189*61046927SAndroid Build Coastguard Worker       if (fsat->src[0].swizzle[i] != i)
190*61046927SAndroid Build Coastguard Worker          return false;
191*61046927SAndroid Build Coastguard Worker    }
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker    return true;
194*61046927SAndroid Build Coastguard Worker }
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker static inline bool
chase_fsat(nir_def ** def)197*61046927SAndroid Build Coastguard Worker chase_fsat(nir_def **def)
198*61046927SAndroid Build Coastguard Worker {
199*61046927SAndroid Build Coastguard Worker    /* No legacy user supports fp64 modifiers */
200*61046927SAndroid Build Coastguard Worker    if ((*def)->bit_size == 64)
201*61046927SAndroid Build Coastguard Worker       return false;
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker    if (!list_is_singular(&(*def)->uses))
204*61046927SAndroid Build Coastguard Worker       return false;
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker    nir_src *use = list_first_entry(&(*def)->uses, nir_src, use_link);
207*61046927SAndroid Build Coastguard Worker    if (nir_src_is_if(use) || nir_src_parent_instr(use)->type != nir_instr_type_alu)
208*61046927SAndroid Build Coastguard Worker       return false;
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker    nir_alu_instr *fsat = nir_instr_as_alu(nir_src_parent_instr(use));
211*61046927SAndroid Build Coastguard Worker    if (fsat->op != nir_op_fsat || !nir_legacy_fsat_folds(fsat))
212*61046927SAndroid Build Coastguard Worker       return false;
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker    /* Otherwise, we're good */
215*61046927SAndroid Build Coastguard Worker    nir_alu_instr *alu = nir_instr_as_alu(nir_src_parent_instr(use));
216*61046927SAndroid Build Coastguard Worker    *def = &alu->def;
217*61046927SAndroid Build Coastguard Worker    return true;
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker nir_legacy_alu_dest
nir_legacy_chase_alu_dest(nir_def * def)221*61046927SAndroid Build Coastguard Worker nir_legacy_chase_alu_dest(nir_def *def)
222*61046927SAndroid Build Coastguard Worker {
223*61046927SAndroid Build Coastguard Worker    /* Try SSA fsat. No users support 64-bit modifiers. */
224*61046927SAndroid Build Coastguard Worker    if (chase_fsat(&def)) {
225*61046927SAndroid Build Coastguard Worker       return (nir_legacy_alu_dest){
226*61046927SAndroid Build Coastguard Worker          .dest.is_ssa = true,
227*61046927SAndroid Build Coastguard Worker          .dest.ssa = def,
228*61046927SAndroid Build Coastguard Worker          .fsat = true,
229*61046927SAndroid Build Coastguard Worker          .write_mask = nir_component_mask(def->num_components),
230*61046927SAndroid Build Coastguard Worker       };
231*61046927SAndroid Build Coastguard Worker    } else {
232*61046927SAndroid Build Coastguard Worker       return chase_alu_dest_helper(def);
233*61046927SAndroid Build Coastguard Worker    }
234*61046927SAndroid Build Coastguard Worker }
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker nir_legacy_src
nir_legacy_chase_src(const nir_src * src)237*61046927SAndroid Build Coastguard Worker nir_legacy_chase_src(const nir_src *src)
238*61046927SAndroid Build Coastguard Worker {
239*61046927SAndroid Build Coastguard Worker    nir_legacy_alu_src alu_src = chase_alu_src_helper(src);
240*61046927SAndroid Build Coastguard Worker    assert(!alu_src.fabs && !alu_src.fneg);
241*61046927SAndroid Build Coastguard Worker    return alu_src.src;
242*61046927SAndroid Build Coastguard Worker }
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker nir_legacy_dest
nir_legacy_chase_dest(nir_def * def)245*61046927SAndroid Build Coastguard Worker nir_legacy_chase_dest(nir_def *def)
246*61046927SAndroid Build Coastguard Worker {
247*61046927SAndroid Build Coastguard Worker    nir_legacy_alu_dest alu_dest = chase_alu_dest_helper(def);
248*61046927SAndroid Build Coastguard Worker    assert(!alu_dest.fsat);
249*61046927SAndroid Build Coastguard Worker    assert(alu_dest.write_mask == nir_component_mask(def->num_components));
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker    return alu_dest.dest;
252*61046927SAndroid Build Coastguard Worker }
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker static bool
fuse_mods_with_registers(nir_builder * b,nir_instr * instr,void * fuse_fabs_)255*61046927SAndroid Build Coastguard Worker fuse_mods_with_registers(nir_builder *b, nir_instr *instr, void *fuse_fabs_)
256*61046927SAndroid Build Coastguard Worker {
257*61046927SAndroid Build Coastguard Worker    bool *fuse_fabs = fuse_fabs_;
258*61046927SAndroid Build Coastguard Worker    if (instr->type != nir_instr_type_alu)
259*61046927SAndroid Build Coastguard Worker       return false;
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker    nir_alu_instr *alu = nir_instr_as_alu(instr);
262*61046927SAndroid Build Coastguard Worker    if ((alu->op == nir_op_fneg || (*fuse_fabs && alu->op == nir_op_fabs)) &&
263*61046927SAndroid Build Coastguard Worker        nir_legacy_float_mod_folds(alu)) {
264*61046927SAndroid Build Coastguard Worker       /* Try to fold this instruction into the load, if possible.  We only do
265*61046927SAndroid Build Coastguard Worker        * this for loads in the same block as the use because uses of loads
266*61046927SAndroid Build Coastguard Worker        * which cross block boundaries aren't trivial anyway.
267*61046927SAndroid Build Coastguard Worker        */
268*61046927SAndroid Build Coastguard Worker       nir_intrinsic_instr *load = nir_load_reg_for_def(alu->src[0].src.ssa);
269*61046927SAndroid Build Coastguard Worker       if (load != NULL) {
270*61046927SAndroid Build Coastguard Worker          /* Duplicate the load before changing it in case there are other
271*61046927SAndroid Build Coastguard Worker           * users. We assume someone has run CSE so there should be at most
272*61046927SAndroid Build Coastguard Worker           * four load instructions generated (one for each possible modifier
273*61046927SAndroid Build Coastguard Worker           * combination), but likely only one or two.
274*61046927SAndroid Build Coastguard Worker           */
275*61046927SAndroid Build Coastguard Worker          b->cursor = nir_before_instr(&load->instr);
276*61046927SAndroid Build Coastguard Worker          load = nir_instr_as_intrinsic(nir_instr_clone(b->shader, &load->instr));
277*61046927SAndroid Build Coastguard Worker          nir_builder_instr_insert(b, &load->instr);
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker          if (alu->op == nir_op_fabs) {
280*61046927SAndroid Build Coastguard Worker             nir_intrinsic_set_legacy_fabs(load, true);
281*61046927SAndroid Build Coastguard Worker             nir_intrinsic_set_legacy_fneg(load, false);
282*61046927SAndroid Build Coastguard Worker          } else {
283*61046927SAndroid Build Coastguard Worker             assert(alu->op == nir_op_fneg);
284*61046927SAndroid Build Coastguard Worker             bool old_fneg = nir_intrinsic_legacy_fneg(load);
285*61046927SAndroid Build Coastguard Worker             nir_intrinsic_set_legacy_fneg(load, !old_fneg);
286*61046927SAndroid Build Coastguard Worker          }
287*61046927SAndroid Build Coastguard Worker 
288*61046927SAndroid Build Coastguard Worker          /* Rewrite all the users to use the modified load instruction.  We
289*61046927SAndroid Build Coastguard Worker           * already know that they're all float ALU instructions because
290*61046927SAndroid Build Coastguard Worker           * nir_legacy_float_mod_folds() returned true.
291*61046927SAndroid Build Coastguard Worker           */
292*61046927SAndroid Build Coastguard Worker          nir_foreach_use_including_if_safe(use, &alu->def) {
293*61046927SAndroid Build Coastguard Worker             assert(!nir_src_is_if(use));
294*61046927SAndroid Build Coastguard Worker             assert(nir_src_parent_instr(use)->type == nir_instr_type_alu);
295*61046927SAndroid Build Coastguard Worker             nir_alu_src *alu_use = list_entry(use, nir_alu_src, src);
296*61046927SAndroid Build Coastguard Worker             nir_src_rewrite(&alu_use->src, &load->def);
297*61046927SAndroid Build Coastguard Worker             for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; ++i)
298*61046927SAndroid Build Coastguard Worker                alu_use->swizzle[i] = alu->src[0].swizzle[alu_use->swizzle[i]];
299*61046927SAndroid Build Coastguard Worker          }
300*61046927SAndroid Build Coastguard Worker 
301*61046927SAndroid Build Coastguard Worker          nir_instr_remove(&alu->instr);
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker          return true;
304*61046927SAndroid Build Coastguard Worker       } else {
305*61046927SAndroid Build Coastguard Worker          /* We don't want to attempt to add saturate to foldable mod ops */
306*61046927SAndroid Build Coastguard Worker          return false;
307*61046927SAndroid Build Coastguard Worker       }
308*61046927SAndroid Build Coastguard Worker    }
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker    nir_legacy_alu_dest dest = nir_legacy_chase_alu_dest(&alu->def);
311*61046927SAndroid Build Coastguard Worker    if (dest.fsat) {
312*61046927SAndroid Build Coastguard Worker       nir_intrinsic_instr *store = nir_store_reg_for_def(dest.dest.ssa);
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker       if (store) {
315*61046927SAndroid Build Coastguard Worker          nir_intrinsic_set_legacy_fsat(store, true);
316*61046927SAndroid Build Coastguard Worker          nir_src_rewrite(&store->src[0], &alu->def);
317*61046927SAndroid Build Coastguard Worker          return true;
318*61046927SAndroid Build Coastguard Worker       }
319*61046927SAndroid Build Coastguard Worker    }
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker    return false;
322*61046927SAndroid Build Coastguard Worker }
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker void
nir_legacy_trivialize(nir_shader * s,bool fuse_fabs)325*61046927SAndroid Build Coastguard Worker nir_legacy_trivialize(nir_shader *s, bool fuse_fabs)
326*61046927SAndroid Build Coastguard Worker {
327*61046927SAndroid Build Coastguard Worker    /* First, fuse modifiers with registers. This ensures that the helpers do not
328*61046927SAndroid Build Coastguard Worker     * chase registers recursively, allowing registers to be trivialized easier.
329*61046927SAndroid Build Coastguard Worker     */
330*61046927SAndroid Build Coastguard Worker    if (nir_shader_instructions_pass(s, fuse_mods_with_registers,
331*61046927SAndroid Build Coastguard Worker                                     nir_metadata_control_flow,
332*61046927SAndroid Build Coastguard Worker                                     &fuse_fabs)) {
333*61046927SAndroid Build Coastguard Worker       /* If we made progress, we likely left dead loads. Clean them up. */
334*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(s, nir_opt_dce);
335*61046927SAndroid Build Coastguard Worker    }
336*61046927SAndroid Build Coastguard Worker 
337*61046927SAndroid Build Coastguard Worker    /* Now that modifiers are dealt with, we can trivialize the regular way. */
338*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(s, nir_trivialize_registers);
339*61046927SAndroid Build Coastguard Worker }
340