X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Floop_analysis.h;h=3b1971d7edce2ca3283ac5ae820c1b75224ac67b;hb=afa4129cf6ee0a64811b118d270f1b05d7d05325;hp=50c512f847f286a60d63d525e086009c6a17c48f;hpb=9434a0749f26c640305f68ef85d17a31063a5705;p=mesa.git diff --git a/src/glsl/loop_analysis.h b/src/glsl/loop_analysis.h index 50c512f847f..3b1971d7edc 100644 --- a/src/glsl/loop_analysis.h +++ b/src/glsl/loop_analysis.h @@ -36,6 +36,34 @@ extern class loop_state * analyze_loop_variables(exec_list *instructions); +/** + * Fill in loop control fields + * + * Based on analysis of loop variables, this function tries to remove + * redundant sequences in the loop of the form + * + * (if (expression bool ...) (break)) + * + * For example, if it is provable that one loop exit condition will + * always be satisfied before another, the unnecessary exit condition will be + * removed. + */ +extern bool +set_loop_controls(exec_list *instructions, loop_state *ls); + + +extern bool +unroll_loops(exec_list *instructions, loop_state *ls, + const struct gl_shader_compiler_options *options); + +ir_rvalue * +find_initial_value(ir_loop *loop, ir_variable *var); + +int +calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, + enum ir_expression_operation op); + + /** * Tracking for all variables used in a loop */ @@ -43,14 +71,10 @@ 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 *); - /** - * Loop whose variable state is being tracked by this structure - */ - ir_loop *loop; - /** * Variables that have not yet been classified */ @@ -79,21 +103,44 @@ public: */ exec_list terminators; + /** + * If any of the terminators in \c terminators leads to termination of the + * loop after a constant number of iterations, this is the terminator that + * leads to termination after the smallest number of iterations. Otherwise + * NULL. + */ + loop_terminator *limiting_terminator; + /** * Hash table containing all variables accessed in this loop */ hash_table *var_hash; + /** + * Number of ir_loop_jump instructions that operate on this loop + */ + unsigned num_loop_jumps; + + /** + * Whether this loop contains any function calls. + */ + bool contains_calls; + loop_variable_state() { + this->num_loop_jumps = 0; + this->contains_calls = false; this->var_hash = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare); + this->limiting_terminator = NULL; } ~loop_variable_state() { hash_table_dtor(this->var_hash); } + + DECLARE_RALLOC_CXX_OPERATORS(loop_variable_state) }; @@ -108,8 +155,11 @@ public: /** Are all variables in the RHS of the assignment loop constants? */ bool rhs_clean; - /** Is there an assignment to the variable that is conditional? */ - bool conditional_assignment; + /** + * Is there an assignment to the variable that is conditional, or inside a + * nested loop? + */ + bool conditional_or_nested_assignment; /** Reference to the first assignment to the variable in the loop body. */ ir_assignment *first_assignment; @@ -118,29 +168,32 @@ public: unsigned num_assignments; /** - * Increment values for loop induction variables + * Increment value for a loop induction variable * - * Loop induction variables have a single increment of the form - * \c b * \c biv + \c c, where \c b and \c c are loop constants and \c i - * is a basic loop induction variable. + * If this is a loop induction variable, the amount by which the variable + * is incremented on each iteration through the loop. * - * If \c iv_scale is \c NULL, 1 is used. If \c biv is the same as \c var, - * then \c var is a basic loop induction variable. + * If this is not a loop induction variable, NULL. */ - /*@{*/ - ir_rvalue *iv_scale; - ir_variable *biv; ir_rvalue *increment; - /*@}*/ + + + inline bool is_induction_var() const + { + /* Induction variables always have a non-null increment, and vice + * versa. + */ + return this->increment != NULL; + } inline bool is_loop_constant() const { const bool is_const = (this->num_assignments == 0) - || ((this->num_assignments == 1) - && !this->conditional_assignment + || (((this->num_assignments == 1) + && !this->conditional_or_nested_assignment && !this->read_before_write - && this->rhs_clean); + && this->rhs_clean) || this->var->data.read_only); /* If the RHS of *the* assignment is clean, then there must be exactly * one assignment of the variable. @@ -148,18 +201,32 @@ public: assert((this->rhs_clean && (this->num_assignments == 1)) || !this->rhs_clean); - /* Variables that are marked read-only *MUST* be loop constant. - */ - assert(!this->var->read_only || (this->var->read_only && is_const)); - return is_const; } + + void record_reference(bool in_assignee, + bool in_conditional_code_or_nested_loop, + ir_assignment *current_assignment); }; class loop_terminator : public exec_node { public: + loop_terminator() + : ir(NULL), iterations(-1) + { + } + + /** + * Statement which terminates the loop. + */ ir_if *ir; + + /** + * The number of iterations after which the terminator is known to + * terminate the loop (if that is a fixed value). Otherwise -1. + */ + int iterations; }; @@ -174,6 +241,8 @@ public: loop_variable_state *insert(ir_loop *ir); + bool loop_found; + private: loop_state(); @@ -184,7 +253,7 @@ private: void *mem_ctx; - friend class loop_analysis; + friend loop_state *analyze_loop_variables(exec_list *instructions); }; #endif /* LOOP_ANALYSIS_H */