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