2 * Copyright © 2016 Intel Corporation
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:
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
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.
27 add_src(nir_src
*src
, struct set
*invariants
)
30 _mesa_set_add(invariants
, src
->ssa
);
32 _mesa_set_add(invariants
, src
->reg
.reg
);
37 add_src_cb(nir_src
*src
, void *state
)
44 dest_is_invariant(nir_dest
*dest
, struct set
*invariants
)
47 return _mesa_set_search(invariants
, &dest
->ssa
);
49 return _mesa_set_search(invariants
, dest
->reg
.reg
);
54 add_cf_node(nir_cf_node
*cf
, struct set
*invariants
)
56 if (cf
->type
== nir_cf_node_if
) {
57 nir_if
*if_stmt
= nir_cf_node_as_if(cf
);
58 add_src(&if_stmt
->condition
, invariants
);
62 add_cf_node(cf
->parent
, invariants
);
66 add_var(nir_variable
*var
, struct set
*invariants
)
68 _mesa_set_add(invariants
, var
);
72 var_is_invariant(nir_variable
*var
, struct set
* invariants
)
74 return var
->data
.invariant
|| _mesa_set_search(invariants
, var
);
78 propagate_invariant_instr(nir_instr
*instr
, struct set
*invariants
)
80 switch (instr
->type
) {
81 case nir_instr_type_alu
: {
82 nir_alu_instr
*alu
= nir_instr_as_alu(instr
);
83 if (!dest_is_invariant(&alu
->dest
.dest
, invariants
))
87 nir_foreach_src(instr
, add_src_cb
, invariants
);
91 case nir_instr_type_tex
: {
92 nir_tex_instr
*tex
= nir_instr_as_tex(instr
);
93 if (dest_is_invariant(&tex
->dest
, invariants
))
94 nir_foreach_src(instr
, add_src_cb
, invariants
);
98 case nir_instr_type_intrinsic
: {
99 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
100 switch (intrin
->intrinsic
) {
101 case nir_intrinsic_copy_var
:
102 /* If the destination is invariant then so is the source */
103 if (var_is_invariant(intrin
->variables
[0]->var
, invariants
))
104 add_var(intrin
->variables
[1]->var
, invariants
);
107 case nir_intrinsic_load_var
:
108 if (dest_is_invariant(&intrin
->dest
, invariants
))
109 add_var(intrin
->variables
[0]->var
, invariants
);
112 case nir_intrinsic_store_var
:
113 if (var_is_invariant(intrin
->variables
[0]->var
, invariants
))
114 add_src(&intrin
->src
[0], invariants
);
123 case nir_instr_type_jump
:
124 case nir_instr_type_ssa_undef
:
125 case nir_instr_type_load_const
:
126 break; /* Nothing to do */
128 case nir_instr_type_phi
: {
129 nir_phi_instr
*phi
= nir_instr_as_phi(instr
);
130 if (!dest_is_invariant(&phi
->dest
, invariants
))
133 nir_foreach_phi_src(src
, phi
) {
134 add_src(&src
->src
, invariants
);
135 add_cf_node(&src
->pred
->cf_node
, invariants
);
140 case nir_instr_type_call
:
141 unreachable("This pass must be run after function inlining");
143 case nir_instr_type_parallel_copy
:
145 unreachable("Cannot have this instruction type");
150 propagate_invariant_impl(nir_function_impl
*impl
, struct set
*invariants
)
152 bool progress
= false;
155 uint32_t prev_entries
= invariants
->entries
;
157 nir_foreach_block_reverse(block
, impl
) {
158 nir_foreach_instr_reverse(instr
, block
)
159 propagate_invariant_instr(instr
, invariants
);
162 /* Keep running until we make no more progress. */
163 if (invariants
->entries
> prev_entries
) {
172 nir_metadata_preserve(impl
, nir_metadata_block_index
|
173 nir_metadata_dominance
|
174 nir_metadata_live_ssa_defs
);
181 nir_propagate_invariant(nir_shader
*shader
)
183 /* Hash set of invariant things */
184 struct set
*invariants
= _mesa_set_create(NULL
, _mesa_hash_pointer
,
185 _mesa_key_pointer_equal
);
187 bool progress
= false;
188 nir_foreach_function(function
, shader
) {
189 if (function
->impl
&& propagate_invariant_impl(function
->impl
, invariants
))
193 _mesa_set_destroy(invariants
, NULL
);