xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/etnaviv/etnaviv_nir_lower_source_mods.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2014 Intel Corporation
3  * Copyright © 2023 Igalia S.L.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #include "etnaviv_nir.h"
26 #include "etnaviv_compiler_nir.h"
27 
28 /*
29  * This pass lowers the neg and abs operations to pass_flags on
30  * ALU operations.
31  */
32 
33 static void
alu_src_consume_abs(nir_instr * instr,unsigned idx)34 alu_src_consume_abs(nir_instr *instr, unsigned idx)
35 {
36    set_src_mod_abs(instr, idx);
37 }
38 
39 static void
alu_src_consume_negate(nir_instr * instr,unsigned idx)40 alu_src_consume_negate(nir_instr *instr, unsigned idx)
41 {
42    /* If abs is set on the source, the negate goes away */
43    if (!is_src_mod_abs(instr, idx))
44       toggle_src_mod_neg(instr, idx);
45 }
46 
47 static bool
nir_lower_to_source_mods_instr(nir_builder * b,nir_instr * instr,void * data)48 nir_lower_to_source_mods_instr(nir_builder *b, nir_instr *instr,
49                                void *data)
50 {
51    bool progress = false;
52 
53    if (instr->type != nir_instr_type_alu)
54       return false;
55 
56    nir_alu_instr *alu = nir_instr_as_alu(instr);
57 
58    for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++) {
59       if (alu->src[i].src.ssa->parent_instr->type != nir_instr_type_alu)
60          continue;
61 
62       nir_alu_instr *parent = nir_instr_as_alu(alu->src[i].src.ssa->parent_instr);
63 
64       if (nir_alu_type_get_base_type(nir_op_infos[alu->op].input_types[i]) != nir_type_float)
65          continue;
66 
67       if (!(parent->op == nir_op_fabs) &&
68           !(parent->op == nir_op_fneg)) {
69          continue;
70       }
71 
72       if (nir_src_bit_size(alu->src[i].src) == 64)
73          continue;
74 
75       /* We can only store up to 3 source modifiers. */
76       if (i >= 3)
77          continue;
78 
79       nir_src_rewrite(&alu->src[i].src, parent->src[0].src.ssa);
80 
81       /* Apply any modifiers that come from the parent opcode */
82       if (parent->op == nir_op_fneg)
83          alu_src_consume_negate(instr, i);
84       if (parent->op == nir_op_fabs)
85          alu_src_consume_abs(instr, i);
86 
87       /* Apply modifiers from the parent source */
88       if (is_src_mod_neg(&parent->instr, 0))
89          alu_src_consume_negate(instr, i);
90       if (is_src_mod_abs(&parent->instr, 0))
91          alu_src_consume_abs(instr, i);
92 
93       for (int j = 0; j < 4; ++j) {
94          if (!nir_alu_instr_channel_used(alu, i, j))
95             continue;
96          alu->src[i].swizzle[j] = parent->src[0].swizzle[alu->src[i].swizzle[j]];
97       }
98 
99       if (nir_def_is_unused(&parent->def))
100          nir_instr_remove(&parent->instr);
101 
102       progress = true;
103    }
104 
105    return progress;
106 }
107 
108 bool
etna_nir_lower_to_source_mods(nir_shader * shader)109 etna_nir_lower_to_source_mods(nir_shader *shader)
110 {
111    nir_shader_clear_pass_flags(shader);
112 
113    return nir_shader_instructions_pass(shader,
114                                        nir_lower_to_source_mods_instr,
115                                        nir_metadata_control_flow,
116                                        NULL);
117 }
118