ir_instruction* base_ir;
ir_rvalue* array;
bool is_write;
+ unsigned int write_mask;
ir_variable* var;
assignment_generator()
/* Just clone the rest of the deref chain when trying to get at the
* underlying variable.
*/
- void *mem_ctx = talloc_parent(base_ir);
- ir_rvalue *element =
+ void *mem_ctx = ralloc_parent(base_ir);
+ ir_dereference *element =
new(mem_ctx) ir_dereference_array(this->array->clone(mem_ctx, NULL),
new(mem_ctx) ir_constant(i));
ir_rvalue *variable = new(mem_ctx) ir_dereference_variable(this->var);
- ir_assignment *assignment = (is_write)
- ? new(mem_ctx) ir_assignment(element, variable, condition)
- : new(mem_ctx) ir_assignment(variable, element, condition);
+ ir_assignment *assignment;
+ if (is_write) {
+ assignment = new(mem_ctx) ir_assignment(element, variable, condition,
+ write_mask);
+ } else {
+ assignment = new(mem_ctx) ir_assignment(variable, element, condition);
+ }
list->push_tail(assignment);
}
linear_sequence_max_length(linear_sequence_max_length),
condition_components(condition_components)
{
- this->mem_ctx = talloc_parent(index);
+ this->mem_ctx = ralloc_parent(index);
}
void linear_sequence(unsigned begin, unsigned end, exec_list *list)
new(this->mem_ctx) ir_dereference_variable(index);
if (comps) {
- const ir_swizzle_mask m = { 0, 1, 2, 3, comps, false };
+ const ir_swizzle_mask m = { 0, 0, 0, 0, comps, false };
broadcast_index = new(this->mem_ctx) ir_swizzle(broadcast_index, m);
}
class variable_index_to_cond_assign_visitor : public ir_rvalue_visitor {
public:
- variable_index_to_cond_assign_visitor()
+ variable_index_to_cond_assign_visitor(bool lower_input,
+ bool lower_output,
+ bool lower_temp,
+ bool lower_uniform)
{
this->progress = false;
+ this->lower_inputs = lower_input;
+ this->lower_outputs = lower_output;
+ this->lower_temps = lower_temp;
+ this->lower_uniforms = lower_uniform;
}
bool progress;
+ bool lower_inputs;
+ bool lower_outputs;
+ bool lower_temps;
+ bool lower_uniforms;
+
+ bool is_array_or_matrix(const ir_instruction *ir) const
+ {
+ return (ir->type->is_array() || ir->type->is_matrix());
+ }
+
+ bool needs_lowering(ir_dereference_array *deref) const
+ {
+ if (deref == NULL || deref->array_index->as_constant()
+ || !is_array_or_matrix(deref->array))
+ return false;
+
+ if (deref->array->ir_type == ir_type_constant)
+ return this->lower_temps;
+
+ const ir_variable *const var = deref->array->variable_referenced();
+ switch (var->mode) {
+ case ir_var_auto:
+ case ir_var_temporary:
+ return this->lower_temps;
+ case ir_var_uniform:
+ return this->lower_uniforms;
+ case ir_var_in:
+ case ir_var_const_in:
+ return (var->location == -1) ? this->lower_temps : this->lower_inputs;
+ case ir_var_out:
+ return (var->location == -1) ? this->lower_temps : this->lower_outputs;
+ case ir_var_inout:
+ return this->lower_temps;
+ }
+
+ assert(!"Should not get here.");
+ return false;
+ }
ir_variable *convert_dereference_array(ir_dereference_array *orig_deref,
- ir_rvalue* value)
+ ir_assignment* orig_assign)
{
- unsigned length;
- if (orig_deref->array->type->is_array())
- length = orig_deref->array->type->length;
- else if (orig_deref->array->type->is_matrix())
- length = orig_deref->array->type->matrix_columns;
- else
- assert(0);
+ assert(is_array_or_matrix(orig_deref->array));
+
+ const unsigned length = (orig_deref->array->type->is_array())
+ ? orig_deref->array->type->length
+ : orig_deref->array->type->matrix_columns;
- void *const mem_ctx = talloc_parent(base_ir);
- ir_variable *var =
- new(mem_ctx) ir_variable(orig_deref->type, "dereference_array_value",
- ir_var_temporary);
- base_ir->insert_before(var);
+ void *const mem_ctx = ralloc_parent(base_ir);
+
+ /* Temporary storage for either the result of the dereference of
+ * the array, or the RHS that's being assigned into the
+ * dereference of the array.
+ */
+ ir_variable *var;
+
+ if (orig_assign) {
+ var = new(mem_ctx) ir_variable(orig_assign->rhs->type,
+ "dereference_array_value",
+ ir_var_temporary);
+ base_ir->insert_before(var);
- if (value) {
ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(var);
- ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, value, NULL);
+ ir_assignment *assign = new(mem_ctx) ir_assignment(lhs,
+ orig_assign->rhs,
+ NULL);
base_ir->insert_before(assign);
+ } else {
+ var = new(mem_ctx) ir_variable(orig_deref->type,
+ "dereference_array_value",
+ ir_var_temporary);
+ base_ir->insert_before(var);
}
/* Store the index to a temporary to avoid reusing its tree. */
ag.array = orig_deref->array;
ag.base_ir = base_ir;
ag.var = var;
- ag.is_write = !!value;
+ if (orig_assign) {
+ ag.is_write = true;
+ ag.write_mask = orig_assign->write_mask;
+ } else {
+ ag.is_write = false;
+ }
switch_generator sg(ag, index, 4, 4);
return;
ir_dereference_array* orig_deref = (*pir)->as_dereference_array();
- if (orig_deref && !orig_deref->array_index->as_constant()
- && (orig_deref->array->type->is_array()
- || orig_deref->array->type->is_matrix())) {
+ if (needs_lowering(orig_deref)) {
ir_variable* var = convert_dereference_array(orig_deref, 0);
assert(var);
- *pir = new(talloc_parent(base_ir)) ir_dereference_variable(var);
+ *pir = new(ralloc_parent(base_ir)) ir_dereference_variable(var);
this->progress = true;
}
}
ir_dereference_array *orig_deref = ir->lhs->as_dereference_array();
- if (orig_deref && !orig_deref->array_index->as_constant()
- && (orig_deref->array->type->is_array()
- || orig_deref->array->type->is_matrix())) {
- convert_dereference_array(orig_deref, ir->rhs);
+ if (needs_lowering(orig_deref)) {
+ convert_dereference_array(orig_deref, ir);
ir->remove();
this->progress = true;
}
};
bool
-lower_variable_index_to_cond_assign(exec_list *instructions)
+lower_variable_index_to_cond_assign(exec_list *instructions,
+ bool lower_input,
+ bool lower_output,
+ bool lower_temp,
+ bool lower_uniform)
{
- variable_index_to_cond_assign_visitor v;
+ variable_index_to_cond_assign_visitor v(lower_input,
+ lower_output,
+ lower_temp,
+ lower_uniform);
visit_list_elements(&v, instructions);