760bc1f7acdea9adb5c15a051256e65989fe0670
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vec4.cpp
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"
25 extern "C" {
26 #include "main/macros.h"
27 #include "program/prog_parameter.h"
28 }
29
30 #define MAX_INSTRUCTION (1 << 30)
31
32 namespace brw {
33
34 void
35 vec4_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
110 bool
111 vec4_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 */
136 bool
137 vec4_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 */