2 * Copyright © 2014 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 DEALINGS
24 * Jason Ekstrand (jason@jlekstrand.net)
31 * Implements a quick-and-dirty out-of-ssa pass.
34 struct from_ssa_state
{
37 struct hash_table
*ssa_table
;
38 nir_function_impl
*current_impl
;
42 rewrite_ssa_src(nir_src
*src
, void *void_state
)
44 struct from_ssa_state
*state
= void_state
;
47 struct hash_entry
*entry
=
48 _mesa_hash_table_search(state
->ssa_table
, src
->ssa
);
50 memset(src
, 0, sizeof *src
);
51 src
->reg
.reg
= (nir_register
*)entry
->data
;
58 reg_create_from_def(nir_ssa_def
*def
, struct from_ssa_state
*state
)
60 nir_register
*reg
= nir_local_reg_create(state
->current_impl
);
61 reg
->name
= def
->name
;
62 reg
->num_components
= def
->num_components
;
63 reg
->num_array_elems
= 0;
65 /* Might as well steal the use-def information from SSA */
66 _mesa_set_destroy(reg
->uses
, NULL
);
67 reg
->uses
= def
->uses
;
68 _mesa_set_destroy(reg
->if_uses
, NULL
);
69 reg
->if_uses
= def
->if_uses
;
70 _mesa_set_add(reg
->defs
, _mesa_hash_pointer(def
->parent_instr
),
73 /* Add the new register to the table and rewrite the destination */
74 _mesa_hash_table_insert(state
->ssa_table
, def
, reg
);
80 rewrite_ssa_dest(nir_dest
*dest
, void *void_state
)
82 struct from_ssa_state
*state
= void_state
;
85 nir_register
*reg
= reg_create_from_def(&dest
->ssa
, state
);
86 memset(dest
, 0, sizeof *dest
);
94 convert_from_ssa_block(nir_block
*block
, void *void_state
)
96 struct from_ssa_state
*state
= void_state
;
98 nir_foreach_instr_safe(block
, instr
) {
99 if (instr
->type
== nir_instr_type_ssa_undef
) {
100 nir_ssa_undef_instr
*undef
= nir_instr_as_ssa_undef(instr
);
101 reg_create_from_def(&undef
->def
, state
);
102 exec_node_remove(&instr
->node
);
103 ralloc_steal(state
->dead_ctx
, instr
);
105 nir_foreach_src(instr
, rewrite_ssa_src
, state
);
106 nir_foreach_dest(instr
, rewrite_ssa_dest
, state
);
110 if (block
->cf_node
.node
.next
!= NULL
&& /* check that we aren't the end node */
111 !nir_cf_node_is_last(&block
->cf_node
) &&
112 nir_cf_node_next(&block
->cf_node
)->type
== nir_cf_node_if
) {
113 nir_if
*if_stmt
= nir_cf_node_as_if(nir_cf_node_next(&block
->cf_node
));
114 rewrite_ssa_src(&if_stmt
->condition
, state
);
121 remove_phi_nodes(nir_block
*block
, void *void_state
)
123 struct from_ssa_state
*state
= void_state
;
125 nir_foreach_instr_safe(block
, instr
) {
126 /* Phi nodes only ever come at the start of a block */
127 if (instr
->type
!= nir_instr_type_phi
)
130 nir_foreach_dest(instr
, rewrite_ssa_dest
, state
);
132 nir_phi_instr
*phi
= nir_instr_as_phi(instr
);
133 foreach_list_typed(nir_phi_src
, src
, node
, &phi
->srcs
) {
134 assert(src
->src
.is_ssa
);
135 struct hash_entry
*entry
=
136 _mesa_hash_table_search(state
->ssa_table
, src
->src
.ssa
);
137 nir_alu_instr
*mov
= nir_alu_instr_create(state
->mem_ctx
, nir_op_imov
);
138 mov
->dest
.dest
= nir_dest_copy(phi
->dest
, state
->mem_ctx
);
140 nir_register
*reg
= (nir_register
*)entry
->data
;
141 mov
->src
[0].src
.reg
.reg
= reg
;
142 mov
->dest
.write_mask
= (1 << reg
->num_components
) - 1;
144 mov
->src
[0].src
= nir_src_copy(src
->src
, state
->mem_ctx
);
145 mov
->dest
.write_mask
= (1 << src
->src
.ssa
->num_components
) - 1;
148 nir_instr
*block_end
= nir_block_last_instr(src
->pred
);
149 if (block_end
&& block_end
->type
== nir_instr_type_jump
) {
150 /* If the last instruction in the block is a jump, we want to
151 * place the moves after the jump. Otherwise, we want to place
152 * them at the very end.
154 exec_node_insert_node_before(&block_end
->node
, &mov
->instr
.node
);
156 exec_list_push_tail(&src
->pred
->instr_list
, &mov
->instr
.node
);
160 exec_node_remove(&instr
->node
);
161 ralloc_steal(state
->dead_ctx
, instr
);
168 nir_convert_from_ssa_impl(nir_function_impl
*impl
)
170 struct from_ssa_state state
;
172 state
.mem_ctx
= ralloc_parent(impl
);
173 state
.dead_ctx
= ralloc_context(NULL
);
174 state
.current_impl
= impl
;
175 state
.ssa_table
= _mesa_hash_table_create(NULL
, _mesa_hash_pointer
,
176 _mesa_key_pointer_equal
);
178 nir_foreach_block(impl
, remove_phi_nodes
, &state
);
179 nir_foreach_block(impl
, convert_from_ssa_block
, &state
);
181 /* Clean up dead instructions and the hash table */
182 ralloc_free(state
.dead_ctx
);
183 _mesa_hash_table_destroy(state
.ssa_table
, NULL
);
187 nir_convert_from_ssa(nir_shader
*shader
)
189 nir_foreach_overload(shader
, overload
) {
191 nir_convert_from_ssa_impl(overload
->impl
);