i965: only try print GLSL IR once when using INTEL_DEBUG to dump ir
[mesa.git] / src / mesa / drivers / dri / i965 / brw_ir_vec4.h
1 /* -*- c++ -*- */
2 /*
3 * Copyright © 2011-2015 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #ifndef BRW_IR_VEC4_H
26 #define BRW_IR_VEC4_H
27
28 #include "brw_shader.h"
29 #include "brw_context.h"
30
31 namespace brw {
32
33 class dst_reg;
34
35 class src_reg : public backend_reg
36 {
37 public:
38 DECLARE_RALLOC_CXX_OPERATORS(src_reg)
39
40 void init();
41
42 src_reg(enum brw_reg_file file, int nr, const glsl_type *type);
43 src_reg();
44 src_reg(struct ::brw_reg reg);
45
46 bool equals(const src_reg &r) const;
47
48 src_reg(class vec4_visitor *v, const struct glsl_type *type);
49 src_reg(class vec4_visitor *v, const struct glsl_type *type, int size);
50
51 explicit src_reg(const dst_reg &reg);
52
53 src_reg *reladdr;
54 };
55
56 static inline src_reg
57 retype(src_reg reg, enum brw_reg_type type)
58 {
59 reg.type = type;
60 return reg;
61 }
62
63 namespace detail {
64
65 static inline void
66 add_byte_offset(backend_reg *reg, unsigned bytes)
67 {
68 switch (reg->file) {
69 case BAD_FILE:
70 break;
71 case VGRF:
72 case ATTR:
73 case UNIFORM:
74 reg->offset += bytes;
75 assert(reg->offset % 16 == 0);
76 break;
77 case MRF: {
78 const unsigned suboffset = reg->offset + bytes;
79 reg->nr += suboffset / REG_SIZE;
80 reg->offset = suboffset % REG_SIZE;
81 assert(reg->offset % 16 == 0);
82 break;
83 }
84 case ARF:
85 case FIXED_GRF: {
86 const unsigned suboffset = reg->subnr + bytes;
87 reg->nr += suboffset / REG_SIZE;
88 reg->subnr = suboffset % REG_SIZE;
89 assert(reg->subnr % 16 == 0);
90 break;
91 }
92 default:
93 assert(bytes == 0);
94 }
95 }
96
97 } /* namepace detail */
98
99 static inline src_reg
100 byte_offset(src_reg reg, unsigned bytes)
101 {
102 detail::add_byte_offset(&reg, bytes);
103 return reg;
104 }
105
106 static inline src_reg
107 offset(src_reg reg, unsigned width, unsigned delta)
108 {
109 const unsigned stride = (reg.file == UNIFORM ? 0 : 4);
110 const unsigned num_components = MAX2(width / 4 * stride, 4);
111 return byte_offset(reg, num_components * type_sz(reg.type) * delta);
112 }
113
114 /**
115 * Reswizzle a given source register.
116 * \sa brw_swizzle().
117 */
118 static inline src_reg
119 swizzle(src_reg reg, unsigned swizzle)
120 {
121 if (reg.file == IMM)
122 reg.ud = brw_swizzle_immediate(reg.type, reg.ud, swizzle);
123 else
124 reg.swizzle = brw_compose_swizzle(swizzle, reg.swizzle);
125
126 return reg;
127 }
128
129 static inline src_reg
130 negate(src_reg reg)
131 {
132 assert(reg.file != IMM);
133 reg.negate = !reg.negate;
134 return reg;
135 }
136
137 static inline bool
138 is_uniform(const src_reg &reg)
139 {
140 return (reg.file == IMM || reg.file == UNIFORM || reg.is_null()) &&
141 (!reg.reladdr || is_uniform(*reg.reladdr));
142 }
143
144 class dst_reg : public backend_reg
145 {
146 public:
147 DECLARE_RALLOC_CXX_OPERATORS(dst_reg)
148
149 void init();
150
151 dst_reg();
152 dst_reg(enum brw_reg_file file, int nr);
153 dst_reg(enum brw_reg_file file, int nr, const glsl_type *type,
154 unsigned writemask);
155 dst_reg(enum brw_reg_file file, int nr, brw_reg_type type,
156 unsigned writemask);
157 dst_reg(struct ::brw_reg reg);
158 dst_reg(class vec4_visitor *v, const struct glsl_type *type);
159
160 explicit dst_reg(const src_reg &reg);
161
162 bool equals(const dst_reg &r) const;
163
164 src_reg *reladdr;
165 };
166
167 static inline dst_reg
168 retype(dst_reg reg, enum brw_reg_type type)
169 {
170 reg.type = type;
171 return reg;
172 }
173
174 static inline dst_reg
175 byte_offset(dst_reg reg, unsigned bytes)
176 {
177 detail::add_byte_offset(&reg, bytes);
178 return reg;
179 }
180
181 static inline dst_reg
182 offset(dst_reg reg, unsigned width, unsigned delta)
183 {
184 const unsigned stride = (reg.file == UNIFORM ? 0 : 4);
185 const unsigned num_components = MAX2(width / 4 * stride, 4);
186 return byte_offset(reg, num_components * type_sz(reg.type) * delta);
187 }
188
189 static inline dst_reg
190 writemask(dst_reg reg, unsigned mask)
191 {
192 assert(reg.file != IMM);
193 assert((reg.writemask & mask) != 0);
194 reg.writemask &= mask;
195 return reg;
196 }
197
198 /**
199 * Return an integer identifying the discrete address space a register is
200 * contained in. A register is by definition fully contained in the single
201 * reg_space it belongs to, so two registers with different reg_space ids are
202 * guaranteed not to overlap. Most register files are a single reg_space of
203 * its own, only the VGRF file is composed of multiple discrete address
204 * spaces, one for each VGRF allocation.
205 */
206 static inline uint32_t
207 reg_space(const backend_reg &r)
208 {
209 return r.file << 16 | (r.file == VGRF ? r.nr : 0);
210 }
211
212 /**
213 * Return the base offset in bytes of a register relative to the start of its
214 * reg_space().
215 */
216 static inline unsigned
217 reg_offset(const backend_reg &r)
218 {
219 return (r.file == VGRF || r.file == IMM ? 0 : r.nr) *
220 (r.file == UNIFORM ? 16 : REG_SIZE) + r.offset +
221 (r.file == ARF || r.file == FIXED_GRF ? r.subnr : 0);
222 }
223
224 /**
225 * Return whether the register region starting at \p r and spanning \p dr
226 * bytes could potentially overlap the register region starting at \p s and
227 * spanning \p ds bytes.
228 */
229 static inline bool
230 regions_overlap(const backend_reg &r, unsigned dr,
231 const backend_reg &s, unsigned ds)
232 {
233 if (r.file == MRF && (r.nr & BRW_MRF_COMPR4)) {
234 /* COMPR4 regions are translated by the hardware during decompression
235 * into two separate half-regions 4 MRFs apart from each other.
236 */
237 backend_reg t0 = r;
238 t0.nr &= ~BRW_MRF_COMPR4;
239 backend_reg t1 = t0;
240 t1.offset += 4 * REG_SIZE;
241 return regions_overlap(t0, dr / 2, s, ds) ||
242 regions_overlap(t1, dr / 2, s, ds);
243
244 } else if (s.file == MRF && (s.nr & BRW_MRF_COMPR4)) {
245 return regions_overlap(s, ds, r, dr);
246
247 } else {
248 return reg_space(r) == reg_space(s) &&
249 !(reg_offset(r) + dr <= reg_offset(s) ||
250 reg_offset(s) + ds <= reg_offset(r));
251 }
252 }
253
254 class vec4_instruction : public backend_instruction {
255 public:
256 DECLARE_RALLOC_CXX_OPERATORS(vec4_instruction)
257
258 vec4_instruction(enum opcode opcode,
259 const dst_reg &dst = dst_reg(),
260 const src_reg &src0 = src_reg(),
261 const src_reg &src1 = src_reg(),
262 const src_reg &src2 = src_reg());
263
264 dst_reg dst;
265 src_reg src[3];
266
267 enum brw_urb_write_flags urb_write_flags;
268
269 unsigned sol_binding; /**< gen6: SOL binding table index */
270 bool sol_final_write; /**< gen6: send commit message */
271 unsigned sol_vertex; /**< gen6: used for setting dst index in SVB header */
272
273 bool is_send_from_grf();
274 unsigned size_read(unsigned arg) const;
275 bool can_reswizzle(const struct gen_device_info *devinfo, int dst_writemask,
276 int swizzle, int swizzle_mask);
277 void reswizzle(int dst_writemask, int swizzle);
278 bool can_do_source_mods(const struct gen_device_info *devinfo);
279 bool can_do_writemask(const struct gen_device_info *devinfo);
280 bool can_change_types() const;
281 bool has_source_and_destination_hazard() const;
282
283 bool reads_flag()
284 {
285 return predicate || opcode == VS_OPCODE_UNPACK_FLAGS_SIMD4X2;
286 }
287
288 bool reads_flag(unsigned c)
289 {
290 if (opcode == VS_OPCODE_UNPACK_FLAGS_SIMD4X2)
291 return true;
292
293 switch (predicate) {
294 case BRW_PREDICATE_NONE:
295 return false;
296 case BRW_PREDICATE_ALIGN16_REPLICATE_X:
297 return c == 0;
298 case BRW_PREDICATE_ALIGN16_REPLICATE_Y:
299 return c == 1;
300 case BRW_PREDICATE_ALIGN16_REPLICATE_Z:
301 return c == 2;
302 case BRW_PREDICATE_ALIGN16_REPLICATE_W:
303 return c == 3;
304 default:
305 return true;
306 }
307 }
308
309 bool writes_flag()
310 {
311 return (conditional_mod && (opcode != BRW_OPCODE_SEL &&
312 opcode != BRW_OPCODE_IF &&
313 opcode != BRW_OPCODE_WHILE));
314 }
315 };
316
317 /**
318 * Make the execution of \p inst dependent on the evaluation of a possibly
319 * inverted predicate.
320 */
321 inline vec4_instruction *
322 set_predicate_inv(enum brw_predicate pred, bool inverse,
323 vec4_instruction *inst)
324 {
325 inst->predicate = pred;
326 inst->predicate_inverse = inverse;
327 return inst;
328 }
329
330 /**
331 * Make the execution of \p inst dependent on the evaluation of a predicate.
332 */
333 inline vec4_instruction *
334 set_predicate(enum brw_predicate pred, vec4_instruction *inst)
335 {
336 return set_predicate_inv(pred, false, inst);
337 }
338
339 /**
340 * Write the result of evaluating the condition given by \p mod to a flag
341 * register.
342 */
343 inline vec4_instruction *
344 set_condmod(enum brw_conditional_mod mod, vec4_instruction *inst)
345 {
346 inst->conditional_mod = mod;
347 return inst;
348 }
349
350 /**
351 * Clamp the result of \p inst to the saturation range of its destination
352 * datatype.
353 */
354 inline vec4_instruction *
355 set_saturate(bool saturate, vec4_instruction *inst)
356 {
357 inst->saturate = saturate;
358 return inst;
359 }
360
361 /**
362 * Return the number of dataflow registers written by the instruction (either
363 * fully or partially) counted from 'floor(reg_offset(inst->dst) /
364 * register_size)'. The somewhat arbitrary register size unit is 16B for the
365 * UNIFORM and IMM files and 32B for all other files.
366 */
367 inline unsigned
368 regs_written(const vec4_instruction *inst)
369 {
370 assert(inst->dst.file != UNIFORM && inst->dst.file != IMM);
371 return DIV_ROUND_UP(reg_offset(inst->dst) % REG_SIZE + inst->size_written,
372 REG_SIZE);
373 }
374
375 /**
376 * Return the number of dataflow registers read by the instruction (either
377 * fully or partially) counted from 'floor(reg_offset(inst->src[i]) /
378 * register_size)'. The somewhat arbitrary register size unit is 16B for the
379 * UNIFORM and IMM files and 32B for all other files.
380 */
381 inline unsigned
382 regs_read(const vec4_instruction *inst, unsigned i)
383 {
384 const unsigned reg_size =
385 inst->src[i].file == UNIFORM || inst->src[i].file == IMM ? 16 : REG_SIZE;
386 return DIV_ROUND_UP(reg_offset(inst->src[i]) % reg_size + inst->size_read(i),
387 reg_size);
388 }
389
390 } /* namespace brw */
391
392 #endif