#include "ir_visitor.h"
#include "ir_optimization.h"
#include "glsl_types.h"
+#include "util/hash_table.h"
+
+namespace {
struct assignment_entry {
- exec_node link;
int assignment_count;
ir_variable *var;
ir_constant *constval;
virtual ir_visitor_status visit_enter(ir_assignment *);
virtual ir_visitor_status visit_enter(ir_call *);
- exec_list list;
+ struct hash_table *ht;
};
+} /* unnamed namespace */
+
static struct assignment_entry *
-get_assignment_entry(ir_variable *var, exec_list *list)
+get_assignment_entry(ir_variable *var, struct hash_table *ht)
{
+ struct hash_entry *hte = _mesa_hash_table_search(ht, var);
struct assignment_entry *entry;
- foreach_list_typed(struct assignment_entry, entry, link, list) {
- if (entry->var == var)
- return entry;
+ if (hte) {
+ entry = (struct assignment_entry *) hte->data;
+ } else {
+ entry = (struct assignment_entry *) calloc(1, sizeof(*entry));
+ entry->var = var;
+ _mesa_hash_table_insert(ht, var, entry);
}
- entry = (struct assignment_entry *)calloc(1, sizeof(*entry));
- entry->var = var;
- list->push_head(&entry->link);
return entry;
}
ir_visitor_status
ir_constant_variable_visitor::visit(ir_variable *ir)
{
- struct assignment_entry *entry = get_assignment_entry(ir, &this->list);
+ struct assignment_entry *entry = get_assignment_entry(ir, this->ht);
entry->our_scope = true;
return visit_continue;
}
ir_constant *constval;
struct assignment_entry *entry;
- entry = get_assignment_entry(ir->lhs->variable_referenced(), &this->list);
+ entry = get_assignment_entry(ir->lhs->variable_referenced(), this->ht);
assert(entry);
entry->assignment_count++;
/* OK, now find if we actually have all the right conditions for
* this to be a constant value assigned to the var.
*/
- if (ir->condition) {
- constval = ir->condition->constant_expression_value();
- if (!constval || !constval->value.b[0])
- return visit_continue;
- }
+ if (ir->condition)
+ return visit_continue;
ir_variable *var = ir->whole_variable_written();
if (!var)
return visit_continue;
+ /* Ignore buffer variables, since the underlying storage is shared
+ * and we can't be sure that this variable won't be written by another
+ * thread.
+ */
+ if (var->data.mode == ir_var_shader_storage)
+ return visit_continue;
+
constval = ir->rhs->constant_expression_value();
if (!constval)
return visit_continue;
ir_visitor_status
ir_constant_variable_visitor::visit_enter(ir_call *ir)
{
- exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
- foreach_iter(exec_list_iterator, iter, *ir) {
- ir_rvalue *param_rval = (ir_rvalue *)iter.get();
- ir_variable *param = (ir_variable *)sig_iter.get();
-
- if (param->mode == ir_var_out ||
- param->mode == ir_var_inout) {
+ /* Mark any out parameters as assigned to */
+ foreach_two_lists(formal_node, &ir->callee->parameters,
+ actual_node, &ir->actual_parameters) {
+ ir_rvalue *param_rval = (ir_rvalue *) actual_node;
+ ir_variable *param = (ir_variable *) formal_node;
+
+ if (param->data.mode == ir_var_function_out ||
+ param->data.mode == ir_var_function_inout) {
ir_variable *var = param_rval->variable_referenced();
struct assignment_entry *entry;
assert(var);
- entry = get_assignment_entry(var, &this->list);
+ entry = get_assignment_entry(var, this->ht);
entry->assignment_count++;
}
- sig_iter.next();
}
+
+ /* Mark the return storage as having been assigned to */
+ if (ir->return_deref != NULL) {
+ ir_variable *var = ir->return_deref->variable_referenced();
+ struct assignment_entry *entry;
+
+ assert(var);
+ entry = get_assignment_entry(var, this->ht);
+ entry->assignment_count++;
+ }
+
return visit_continue;
}
bool progress = false;
ir_constant_variable_visitor v;
+ v.ht = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
v.run(instructions);
- while (!v.list.is_empty()) {
-
- struct assignment_entry *entry;
- entry = exec_node_data(struct assignment_entry, v.list.head, link);
+ struct hash_entry *hte;
+ hash_table_foreach(v.ht, hte) {
+ struct assignment_entry *entry = (struct assignment_entry *) hte->data;
if (entry->assignment_count == 1 && entry->constval && entry->our_scope) {
entry->var->constant_value = entry->constval;
progress = true;
}
- entry->link.remove();
+ hte->data = NULL;
free(entry);
}
+ _mesa_hash_table_destroy(v.ht, NULL);
return progress;
}
{
bool progress = false;
- foreach_iter(exec_list_iterator, iter, *instructions) {
- ir_instruction *ir = (ir_instruction *)iter.get();
+ foreach_in_list(ir_instruction, ir, instructions) {
ir_function *f = ir->as_function();
if (f) {
- foreach_iter(exec_list_iterator, sigiter, *f) {
- ir_function_signature *sig =
- (ir_function_signature *) sigiter.get();
+ foreach_in_list(ir_function_signature, sig, &f->signatures) {
if (do_constant_variable(&sig->body))
progress = true;
}