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