this->declarations.push_degenerate_list_at_head(&declarator_list->link);
}
+/**
+ * Do the set of common optimizations passes
+ *
+ * \param ir List of instructions to be optimized
+ * \param linked Is the shader linked? This enables
+ * optimizations passes that remove code at
+ * global scope and could cause linking to
+ * fail.
+ * \param uniform_locations_assigned Have locations already been assigned for
+ * uniforms? This prevents the declarations
+ * of unused uniforms from being removed.
+ * The setting of this flag only matters if
+ * \c linked is \c true.
+ * \param max_unroll_iterations Maximum number of loop iterations to be
+ * unrolled. Setting to 0 forces all loops
+ * to be unrolled.
+ */
bool
-do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations)
+do_common_optimization(exec_list *ir, bool linked,
+ bool uniform_locations_assigned,
+ unsigned max_unroll_iterations)
{
GLboolean progress = GL_FALSE;
progress = do_copy_propagation(ir) || progress;
progress = do_copy_propagation_elements(ir) || progress;
if (linked)
- progress = do_dead_code(ir) || progress;
+ progress = do_dead_code(ir, uniform_locations_assigned) || progress;
else
progress = do_dead_code_unlinked(ir) || progress;
progress = do_dead_code_local(ir) || progress;
#define MOD_TO_FRACT 0x20
#define INT_DIV_TO_MUL_RCP 0x40
-bool do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations);
+bool do_common_optimization(exec_list *ir, bool linked,
+ bool uniform_locations_assigned,
+ unsigned max_unroll_iterations);
bool do_algebraic(exec_list *instructions);
bool do_constant_folding(exec_list *instructions);
bool do_copy_propagation(exec_list *instructions);
bool do_copy_propagation_elements(exec_list *instructions);
bool do_constant_propagation(exec_list *instructions);
-bool do_dead_code(exec_list *instructions);
+bool do_dead_code(exec_list *instructions, bool uniform_locations_assigned);
bool do_dead_code_local(exec_list *instructions);
bool do_dead_code_unlinked(exec_list *instructions);
bool do_dead_functions(exec_list *instructions);
if (ctx->ShaderCompilerOptions[i].LowerClipDistance)
lower_clip_distance(prog->_LinkedShaders[i]->ir);
- while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, 32))
+ while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, 32))
;
}
if (!state->error && !shader->ir->is_empty()) {
bool progress;
do {
- progress = do_common_optimization(shader->ir, false, 32);
+ progress = do_common_optimization(shader->ir, false, false, 32);
} while (progress);
validate_ir_tree(shader->ir);
* for usage on an unlinked instruction stream.
*/
bool
-do_dead_code(exec_list *instructions)
+do_dead_code(exec_list *instructions, bool uniform_locations_assigned)
{
ir_variable_refcount_visitor v;
bool progress = false;
*/
/* uniform initializers are precious, and could get used by another
- * stage.
+ * stage. Also, once uniform locations have been assigned, the
+ * declaration cannot be deleted.
*/
if (entry->var->mode == ir_var_uniform &&
- entry->var->constant_value)
+ (uniform_locations_assigned || entry->var->constant_value))
continue;
entry->var->remove();
foreach_iter(exec_list_iterator, sigiter, *f) {
ir_function_signature *sig =
(ir_function_signature *) sigiter.get();
- if (do_dead_code(&sig->body))
+ /* The setting of the uniform_locations_assigned flag here is
+ * irrelevent. If there is a uniform declaration encountered
+ * inside the body of the function, something has already gone
+ * terribly, terribly wrong.
+ */
+ if (do_dead_code(&sig->body, false))
progress = true;
}
}
if (sscanf(optimization, "do_common_optimization ( %d , %d ) ",
&int_0, &int_1) == 2) {
- return do_common_optimization(ir, int_0 != 0, int_1);
+ return do_common_optimization(ir, int_0 != 0, false, int_1);
} else if (strcmp(optimization, "do_algebraic") == 0) {
return do_algebraic(ir);
} else if (strcmp(optimization, "do_constant_folding") == 0) {
} else if (strcmp(optimization, "do_constant_propagation") == 0) {
return do_constant_propagation(ir);
} else if (strcmp(optimization, "do_dead_code") == 0) {
- return do_dead_code(ir);
+ return do_dead_code(ir, false);
} else if (strcmp(optimization, "do_dead_code_local") == 0) {
return do_dead_code_local(ir);
} else if (strcmp(optimization, "do_dead_code_unlinked") == 0) {
false /* loops */
) || progress;
- progress = do_common_optimization(shader->ir, true, 32) || progress;
+ progress = do_common_optimization(shader->ir, true, true, 32)
+ || progress;
} while (progress);
validate_ir_tree(shader->ir);
validate_ir_tree(p.shader->ir);
- while (do_common_optimization(p.shader->ir, false, 32))
+ while (do_common_optimization(p.shader->ir, false, false, 32))
;
reparent_ir(p.shader->ir, p.shader->ir);
progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
- progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress;
+ progress = do_common_optimization(ir, true, true,
+ options->MaxUnrollIterations)
+ || progress;
progress = lower_quadop_vector(ir, true) || progress;
/* Do some optimization at compile time to reduce shader IR size
* and reduce later work if the same shader is linked multiple times
*/
- while (do_common_optimization(shader->ir, false, 32))
+ while (do_common_optimization(shader->ir, false, false, 32))
;
validate_ir_tree(shader->ir);
progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
- progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress;
+ progress = do_common_optimization(ir, true, true,
+ options->MaxUnrollIterations)
+ || progress;
progress = lower_quadop_vector(ir, false) || progress;