brw_vec4.cpp revision 8174945d3346dc049ae56dcb4bf1eab39f5c88aa
1/* 2 * Copyright © 2011 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "brw_vec4.h" 25extern "C" { 26#include "main/macros.h" 27#include "program/prog_parameter.h" 28} 29 30#define MAX_INSTRUCTION (1 << 30) 31 32namespace brw { 33 34void 35vec4_visitor::calculate_live_intervals() 36{ 37 int *def = ralloc_array(mem_ctx, int, virtual_grf_count); 38 int *use = ralloc_array(mem_ctx, int, virtual_grf_count); 39 int loop_depth = 0; 40 int loop_start = 0; 41 42 if (this->live_intervals_valid) 43 return; 44 45 for (int i = 0; i < virtual_grf_count; i++) { 46 def[i] = MAX_INSTRUCTION; 47 use[i] = -1; 48 } 49 50 int ip = 0; 51 foreach_list(node, &this->instructions) { 52 vec4_instruction *inst = (vec4_instruction *)node; 53 54 if (inst->opcode == BRW_OPCODE_DO) { 55 if (loop_depth++ == 0) 56 loop_start = ip; 57 } else if (inst->opcode == BRW_OPCODE_WHILE) { 58 loop_depth--; 59 60 if (loop_depth == 0) { 61 /* Patches up the use of vars marked for being live across 62 * the whole loop. 63 */ 64 for (int i = 0; i < virtual_grf_count; i++) { 65 if (use[i] == loop_start) { 66 use[i] = ip; 67 } 68 } 69 } 70 } else { 71 for (unsigned int i = 0; i < 3; i++) { 72 if (inst->src[i].file == GRF) { 73 int reg = inst->src[i].reg; 74 75 if (!loop_depth) { 76 use[reg] = ip; 77 } else { 78 def[reg] = MIN2(loop_start, def[reg]); 79 use[reg] = loop_start; 80 81 /* Nobody else is going to go smash our start to 82 * later in the loop now, because def[reg] now 83 * points before the bb header. 84 */ 85 } 86 } 87 } 88 if (inst->dst.file == GRF) { 89 int reg = inst->dst.reg; 90 91 if (!loop_depth) { 92 def[reg] = MIN2(def[reg], ip); 93 } else { 94 def[reg] = MIN2(def[reg], loop_start); 95 } 96 } 97 } 98 99 ip++; 100 } 101 102 ralloc_free(this->virtual_grf_def); 103 ralloc_free(this->virtual_grf_use); 104 this->virtual_grf_def = def; 105 this->virtual_grf_use = use; 106 107 this->live_intervals_valid = true; 108} 109 110bool 111vec4_visitor::virtual_grf_interferes(int a, int b) 112{ 113 int start = MAX2(this->virtual_grf_def[a], this->virtual_grf_def[b]); 114 int end = MIN2(this->virtual_grf_use[a], this->virtual_grf_use[b]); 115 116 /* We can't handle dead register writes here, without iterating 117 * over the whole instruction stream to find every single dead 118 * write to that register to compare to the live interval of the 119 * other register. Just assert that dead_code_eliminate() has been 120 * called. 121 */ 122 assert((this->virtual_grf_use[a] != -1 || 123 this->virtual_grf_def[a] == MAX_INSTRUCTION) && 124 (this->virtual_grf_use[b] != -1 || 125 this->virtual_grf_def[b] == MAX_INSTRUCTION)); 126 127 return start < end; 128} 129 130/** 131 * Must be called after calculate_live_intervales() to remove unused 132 * writes to registers -- register allocation will fail otherwise 133 * because something deffed but not used won't be considered to 134 * interfere with other regs. 135 */ 136bool 137vec4_visitor::dead_code_eliminate() 138{ 139 bool progress = false; 140 int pc = 0; 141 142 calculate_live_intervals(); 143 144 foreach_list_safe(node, &this->instructions) { 145 vec4_instruction *inst = (vec4_instruction *)node; 146 147 if (inst->dst.file == GRF && this->virtual_grf_use[inst->dst.reg] <= pc) { 148 inst->remove(); 149 progress = true; 150 } 151 152 pc++; 153 } 154 155 if (progress) 156 live_intervals_valid = false; 157 158 return progress; 159} 160 161} /* namespace brw */ 162