1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright © 2010 Intel Corporation 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"), 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions: 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the next 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * paragraph) shall be included in all copies or substantial portions of the 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software. 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE. 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \file opt_constant_variable.cpp 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Marks variables assigned a single constant value over the course 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the program as constant. 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The goal here is to trigger further constant folding and then dead 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * code elimination. This is common with vector/matrix constructors 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and calls to builtin functions. 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir.h" 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_visitor.h" 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_optimization.h" 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "glsl_types.h" 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace { 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct assignment_entry { 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exec_node link; 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int assignment_count; 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var; 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_constant *constval; 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool our_scope; 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ir_constant_variable_visitor : public ir_hierarchical_visitor { 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic: 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit_enter(ir_dereference_variable *); 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit(ir_variable *); 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit_enter(ir_assignment *); 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit_enter(ir_call *); 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exec_list list; 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} /* unnamed namespace */ 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct assignment_entry * 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgget_assignment_entry(ir_variable *var, exec_list *list) 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct assignment_entry *entry; 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list_typed(struct assignment_entry, entry, link, list) { 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (entry->var == var) 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return entry; 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry = (struct assignment_entry *)calloc(1, sizeof(*entry)); 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->var = var; 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org list->push_head(&entry->link); 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return entry; 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_variable_visitor::visit(ir_variable *ir) 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct assignment_entry *entry = get_assignment_entry(ir, &this->list); 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->our_scope = true; 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Skip derefs of variables so that we can detect declarations. */ 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_variable_visitor::visit_enter(ir_dereference_variable *ir) 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (void)ir; 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue_with_parent; 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_variable_visitor::visit_enter(ir_assignment *ir) 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_constant *constval; 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct assignment_entry *entry; 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry = get_assignment_entry(ir->lhs->variable_referenced(), &this->list); 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(entry); 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->assignment_count++; 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If it's already constant, don't do the work. */ 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (entry->var->constant_value) 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* OK, now find if we actually have all the right conditions for 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * this to be a constant value assigned to the var. 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ir->condition) 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var = ir->whole_variable_written(); 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!var) 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org constval = ir->rhs->constant_expression_value(); 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!constval) 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Mark this entry as having a constant assignment (if the 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * assignment count doesn't go >1). do_constant_variable will fix 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * up the variable with the constant value later. 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->constval = constval; 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_variable_visitor::visit_enter(ir_call *ir) 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Mark any out parameters as assigned to */ 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exec_list_iterator sig_iter = ir->callee->parameters.iterator(); 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_iter(exec_list_iterator, iter, *ir) { 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_rvalue *param_rval = (ir_rvalue *)iter.get(); 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *param = (ir_variable *)sig_iter.get(); 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (param->mode == ir_var_out || 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org param->mode == ir_var_inout) { 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var = param_rval->variable_referenced(); 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct assignment_entry *entry; 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(var); 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry = get_assignment_entry(var, &this->list); 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->assignment_count++; 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sig_iter.next(); 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Mark the return storage as having been assigned to */ 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ir->return_deref != NULL) { 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var = ir->return_deref->variable_referenced(); 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct assignment_entry *entry; 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(var); 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry = get_assignment_entry(var, &this->list); 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->assignment_count++; 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Does a copy propagation pass on the code present in the instruction stream. 167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdo_constant_variable(exec_list *instructions) 170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool progress = false; 172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_constant_variable_visitor v; 173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org v.run(instructions); 175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org while (!v.list.is_empty()) { 177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct assignment_entry *entry; 179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry = exec_node_data(struct assignment_entry, v.list.head, link); 180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (entry->assignment_count == 1 && entry->constval && entry->our_scope) { 182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->var->constant_value = entry->constval; 183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org progress = true; 184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->link.remove(); 186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free(entry); 187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return progress; 190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdo_constant_variable_unlinked(exec_list *instructions) 194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool progress = false; 196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_iter(exec_list_iterator, iter, *instructions) { 198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_instruction *ir = (ir_instruction *)iter.get(); 199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function *f = ir->as_function(); 200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (f) { 201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_iter(exec_list_iterator, sigiter, *f) { 202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function_signature *sig = 203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (ir_function_signature *) sigiter.get(); 204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (do_constant_variable(&sig->body)) 205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org progress = true; 206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return progress; 211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 212