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 * Connor Abbott (cwabbott0@gmail.com)
29 #include "nir_builder.h"
30 #include "nir_phi_builder.h"
33 struct regs_to_ssa_state
{
36 struct nir_phi_builder_value
**values
;
40 rewrite_src(nir_src
*src
, void *_state
)
42 struct regs_to_ssa_state
*state
= _state
;
47 nir_instr
*instr
= src
->parent_instr
;
48 nir_register
*reg
= src
->reg
.reg
;
49 struct nir_phi_builder_value
*value
= state
->values
[reg
->index
];
54 if (instr
->type
== nir_instr_type_phi
) {
55 nir_phi_src
*phi_src
= exec_node_data(nir_phi_src
, src
, src
);
56 block
= phi_src
->pred
;
61 nir_ssa_def
*def
= nir_phi_builder_value_get_block_def(value
, block
);
62 nir_instr_rewrite_src(instr
, src
, nir_src_for_ssa(def
));
68 rewrite_if_condition(nir_if
*nif
, struct regs_to_ssa_state
*state
)
70 if (nif
->condition
.is_ssa
)
73 nir_block
*block
= nir_cf_node_as_block(nir_cf_node_prev(&nif
->cf_node
));
74 nir_register
*reg
= nif
->condition
.reg
.reg
;
75 struct nir_phi_builder_value
*value
= state
->values
[reg
->index
];
79 nir_ssa_def
*def
= nir_phi_builder_value_get_block_def(value
, block
);
80 nir_if_rewrite_condition(nif
, nir_src_for_ssa(def
));
84 rewrite_dest(nir_dest
*dest
, void *_state
)
86 struct regs_to_ssa_state
*state
= _state
;
91 nir_instr
*instr
= dest
->reg
.parent_instr
;
92 nir_register
*reg
= dest
->reg
.reg
;
93 struct nir_phi_builder_value
*value
= state
->values
[reg
->index
];
97 list_del(&dest
->reg
.def_link
);
98 nir_ssa_dest_init(instr
, dest
, reg
->num_components
,
99 reg
->bit_size
, reg
->name
);
101 nir_phi_builder_value_set_block_def(value
, instr
->block
, &dest
->ssa
);
107 rewrite_alu_instr(nir_alu_instr
*alu
, struct regs_to_ssa_state
*state
)
109 nir_foreach_src(&alu
->instr
, rewrite_src
, state
);
111 if (alu
->dest
.dest
.is_ssa
)
114 nir_register
*reg
= alu
->dest
.dest
.reg
.reg
;
115 struct nir_phi_builder_value
*value
= state
->values
[reg
->index
];
119 unsigned write_mask
= alu
->dest
.write_mask
;
120 if (write_mask
== (1 << reg
->num_components
) - 1) {
121 /* This is the simple case where the instruction writes all the
122 * components. We can handle that the same as any other destination.
124 rewrite_dest(&alu
->dest
.dest
, state
);
128 /* Calculate the number of components the final instruction, which for
129 * per-component things is the number of output components of the
130 * instruction and non-per-component things is the number of enabled
131 * channels in the write mask.
133 unsigned num_components
;
134 unsigned vec_swizzle
[4] = { 0, 1, 2, 3 };
135 if (nir_op_infos
[alu
->op
].output_size
== 0) {
136 /* Figure out the swizzle we need on the vecN operation and compute
137 * the number of components in the SSA def at the same time.
140 for (unsigned index
= 0; index
< 4; index
++) {
141 if (write_mask
& (1 << index
))
142 vec_swizzle
[index
] = num_components
++;
145 /* When we change the output writemask, we need to change
146 * the swizzles for per-component inputs too
148 for (unsigned i
= 0; i
< nir_op_infos
[alu
->op
].num_inputs
; i
++) {
149 if (nir_op_infos
[alu
->op
].input_sizes
[i
] != 0)
153 * We keep two indices:
154 * 1. The index of the original (non-SSA) component
155 * 2. The index of the post-SSA, compacted, component
157 * We need to map the swizzle component at index 1 to the swizzle
158 * component at index 2. Since index 1 is always larger than
159 * index 2, we can do it in a single loop.
162 unsigned ssa_index
= 0;
163 for (unsigned index
= 0; index
< 4; index
++) {
164 if (!((write_mask
>> index
) & 1))
167 alu
->src
[i
].swizzle
[ssa_index
++] = alu
->src
[i
].swizzle
[index
];
169 assert(ssa_index
== num_components
);
172 num_components
= nir_op_infos
[alu
->op
].output_size
;
174 assert(num_components
<= 4);
176 alu
->dest
.write_mask
= (1 << num_components
) - 1;
177 list_del(&alu
->dest
.dest
.reg
.def_link
);
178 nir_ssa_dest_init(&alu
->instr
, &alu
->dest
.dest
, num_components
,
179 reg
->bit_size
, reg
->name
);
181 nir_op vecN_op
= nir_op_vec(reg
->num_components
);
183 nir_alu_instr
*vec
= nir_alu_instr_create(state
->shader
, vecN_op
);
185 nir_ssa_def
*old_src
=
186 nir_phi_builder_value_get_block_def(value
, alu
->instr
.block
);
187 nir_ssa_def
*new_src
= &alu
->dest
.dest
.ssa
;
189 for (unsigned i
= 0; i
< reg
->num_components
; i
++) {
190 if (write_mask
& (1 << i
)) {
191 vec
->src
[i
].src
= nir_src_for_ssa(new_src
);
192 vec
->src
[i
].swizzle
[0] = vec_swizzle
[i
];
194 vec
->src
[i
].src
= nir_src_for_ssa(old_src
);
195 vec
->src
[i
].swizzle
[0] = i
;
199 nir_ssa_dest_init(&vec
->instr
, &vec
->dest
.dest
, reg
->num_components
,
200 reg
->bit_size
, reg
->name
);
201 nir_instr_insert(nir_after_instr(&alu
->instr
), &vec
->instr
);
203 nir_phi_builder_value_set_block_def(value
, alu
->instr
.block
,
204 &vec
->dest
.dest
.ssa
);
208 nir_lower_regs_to_ssa_impl(nir_function_impl
*impl
)
210 if (exec_list_is_empty(&impl
->registers
))
213 nir_metadata_require(impl
, nir_metadata_block_index
|
214 nir_metadata_dominance
);
215 nir_index_local_regs(impl
);
217 void *dead_ctx
= ralloc_context(NULL
);
218 struct regs_to_ssa_state state
;
219 state
.shader
= impl
->function
->shader
;
220 state
.values
= ralloc_array(dead_ctx
, struct nir_phi_builder_value
*,
223 struct nir_phi_builder
*phi_build
= nir_phi_builder_create(impl
);
225 const unsigned block_set_words
= BITSET_WORDS(impl
->num_blocks
);
226 BITSET_WORD
*defs
= ralloc_array(dead_ctx
, BITSET_WORD
, block_set_words
);
228 nir_foreach_register(reg
, &impl
->registers
) {
229 if (reg
->num_array_elems
!= 0) {
230 /* This pass only really works on "plain" registers. If it's a
231 * packed or array register, just set the value to NULL so that the
232 * rewrite portion of the pass will know to ignore it.
234 state
.values
[reg
->index
] = NULL
;
238 memset(defs
, 0, block_set_words
* sizeof(*defs
));
240 nir_foreach_def(dest
, reg
)
241 BITSET_SET(defs
, dest
->reg
.parent_instr
->block
->index
);
243 state
.values
[reg
->index
] =
244 nir_phi_builder_add_value(phi_build
, reg
->num_components
,
245 reg
->bit_size
, defs
);
248 nir_foreach_block(block
, impl
) {
249 nir_foreach_instr(instr
, block
) {
250 switch (instr
->type
) {
251 case nir_instr_type_alu
:
252 rewrite_alu_instr(nir_instr_as_alu(instr
), &state
);
255 case nir_instr_type_phi
:
256 /* We rewrite sources as a separate pass */
257 nir_foreach_dest(instr
, rewrite_dest
, &state
);
261 nir_foreach_src(instr
, rewrite_src
, &state
);
262 nir_foreach_dest(instr
, rewrite_dest
, &state
);
266 nir_if
*following_if
= nir_block_get_following_if(block
);
268 rewrite_if_condition(following_if
, &state
);
270 /* Handle phi sources that source from this block. We have to do this
271 * as a separate pass because the phi builder assumes that uses and
272 * defs are processed in an order that respects dominance. When we have
273 * loops, a phi source may be a back-edge so we have to handle it as if
274 * it were one of the last instructions in the predecessor block.
276 for (unsigned i
= 0; i
< ARRAY_SIZE(block
->successors
); i
++) {
277 if (block
->successors
[i
] == NULL
)
280 nir_foreach_instr(instr
, block
->successors
[i
]) {
281 if (instr
->type
!= nir_instr_type_phi
)
284 nir_phi_instr
*phi
= nir_instr_as_phi(instr
);
285 nir_foreach_phi_src(phi_src
, phi
) {
286 if (phi_src
->pred
== block
)
287 rewrite_src(&phi_src
->src
, &state
);
293 nir_phi_builder_finish(phi_build
);
295 nir_foreach_register_safe(reg
, &impl
->registers
) {
296 if (state
.values
[reg
->index
]) {
297 assert(list_is_empty(®
->uses
));
298 assert(list_is_empty(®
->if_uses
));
299 assert(list_is_empty(®
->defs
));
300 exec_node_remove(®
->node
);
304 ralloc_free(dead_ctx
);
306 nir_metadata_preserve(impl
, nir_metadata_block_index
|
307 nir_metadata_dominance
);
312 nir_lower_regs_to_ssa(nir_shader
*shader
)
314 bool progress
= false;
316 nir_foreach_function(function
, shader
) {
318 progress
|= nir_lower_regs_to_ssa_impl(function
->impl
);