glsl: Extract functions from loop_analysis::visit(ir_dereference_variable *).

This function is about to get more complex.

Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
Paul Berry
2013-11-28 10:42:01 -08:00
parent 69c44d65c8
commit 2e060551bd
2 changed files with 71 additions and 25 deletions

View File

@@ -33,6 +33,43 @@ static bool all_expression_operands_are_loop_constant(ir_rvalue *,
static ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *);
/**
* Record the fact that the given loop variable was referenced inside the loop.
*
* \arg in_assignee is true if the reference was on the LHS of an assignment.
*
* \arg in_conditional_code is true if the reference occurred inside an if
* statement.
*
* \arg current_assignment is the ir_assignment node that the loop variable is
* on the LHS of, if any (ignored if \c in_assignee is false).
*/
void
loop_variable::record_reference(bool in_assignee, bool in_conditional_code,
ir_assignment *current_assignment)
{
if (in_assignee) {
assert(current_assignment != NULL);
this->conditional_assignment = in_conditional_code
|| current_assignment->condition != NULL;
if (this->first_assignment == NULL) {
assert(this->num_assignments == 0);
this->first_assignment = current_assignment;
}
this->num_assignments++;
} else if (this->first_assignment == current_assignment) {
/* This catches the case where the variable is used in the RHS of an
* assignment where it is also in the LHS.
*/
this->read_before_write = true;
}
}
loop_state::loop_state()
{
this->ht = hash_table_ctor(0, hash_table_pointer_hash,
@@ -102,6 +139,33 @@ loop_variable_state::insert(ir_if *if_stmt)
return t;
}
/**
* If the given variable already is recorded in the state for this loop,
* return the corresponding loop_variable object that records information
* about it.
*
* Otherwise, create a new loop_variable object to record information about
* the variable, and set its \c read_before_write field appropriately based on
* \c in_assignee.
*
* \arg in_assignee is true if this variable was encountered on the LHS of an
* assignment.
*/
loop_variable *
loop_variable_state::get_or_insert(ir_variable *var, bool in_assignee)
{
loop_variable *lv = this->get(var);
if (lv == NULL) {
lv = this->insert(var);
lv->read_before_write = !in_assignee;
}
return lv;
}
namespace {
class loop_analysis : public ir_hierarchical_visitor {
@@ -181,32 +245,10 @@ loop_analysis::visit(ir_dereference_variable *ir)
(loop_variable_state *) this->state.get_head();
ir_variable *var = ir->variable_referenced();
loop_variable *lv = ls->get(var);
loop_variable *lv = ls->get_or_insert(var, this->in_assignee);
if (lv == NULL) {
lv = ls->insert(var);
lv->read_before_write = !this->in_assignee;
}
if (this->in_assignee) {
assert(this->current_assignment != NULL);
lv->conditional_assignment = (this->if_statement_depth > 0)
|| (this->current_assignment->condition != NULL);
if (lv->first_assignment == NULL) {
assert(lv->num_assignments == 0);
lv->first_assignment = this->current_assignment;
}
lv->num_assignments++;
} else if (lv->first_assignment == this->current_assignment) {
/* This catches the case where the variable is used in the RHS of an
* assignment where it is also in the LHS.
*/
lv->read_before_write = true;
}
lv->record_reference(this->in_assignee, this->if_statement_depth > 0,
this->current_assignment);
return visit_continue;
}

View File

@@ -67,6 +67,7 @@ class loop_variable_state : public exec_node {
public:
class loop_variable *get(const ir_variable *);
class loop_variable *insert(ir_variable *);
class loop_variable *get_or_insert(ir_variable *, bool in_assignee);
class loop_terminator *insert(ir_if *);
@@ -212,6 +213,9 @@ public:
return is_const;
}
void record_reference(bool in_assignee, bool in_conditional_code,
ir_assignment *current_assignment);
};