1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * Copyright 2007-2008 VMware, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include "util/u_memory.h"
30 #include "lp_bld_const.h"
31 #include "lp_bld_type.h"
32 #include "lp_bld_init.h"
33 #include "lp_bld_flow.h"
34 #include "lp_bld_ir_common.h"
35 #include "lp_bld_logic.h"
36
37 /*
38 * Return the context for the current function.
39 * (always 'main', if shader doesn't do any function calls)
40 */
41 static inline struct function_ctx *
func_ctx(struct lp_exec_mask * mask)42 func_ctx(struct lp_exec_mask *mask)
43 {
44 assert(mask->function_stack_size > 0);
45 assert(mask->function_stack_size <= LP_MAX_NUM_FUNCS);
46 return &mask->function_stack[mask->function_stack_size - 1];
47 }
48
49 /*
50 * Returns true if we're in a loop.
51 * It's global, meaning that it returns true even if there's
52 * no loop inside the current function, but we were inside
53 * a loop inside another function, from which this one was called.
54 */
55 static inline bool
mask_has_loop(struct lp_exec_mask * mask)56 mask_has_loop(struct lp_exec_mask *mask)
57 {
58 int i;
59 for (i = mask->function_stack_size - 1; i >= 0; --i) {
60 const struct function_ctx *ctx = &mask->function_stack[i];
61 if (ctx->loop_stack_size > 0)
62 return true;
63 }
64 return false;
65 }
66
67 /*
68 * Returns true if we're inside a switch statement.
69 * It's global, meaning that it returns true even if there's
70 * no switch in the current function, but we were inside
71 * a switch inside another function, from which this one was called.
72 */
73 static inline bool
mask_has_switch(struct lp_exec_mask * mask)74 mask_has_switch(struct lp_exec_mask *mask)
75 {
76 int i;
77 for (i = mask->function_stack_size - 1; i >= 0; --i) {
78 const struct function_ctx *ctx = &mask->function_stack[i];
79 if (ctx->switch_stack_size > 0)
80 return true;
81 }
82 return false;
83 }
84
85 /*
86 * Returns true if we're inside a conditional.
87 * It's global, meaning that it returns true even if there's
88 * no conditional in the current function, but we were inside
89 * a conditional inside another function, from which this one was called.
90 */
91 static inline bool
mask_has_cond(struct lp_exec_mask * mask)92 mask_has_cond(struct lp_exec_mask *mask)
93 {
94 int i;
95 for (i = mask->function_stack_size - 1; i >= 0; --i) {
96 const struct function_ctx *ctx = &mask->function_stack[i];
97 if (ctx->cond_stack_size > 0)
98 return true;
99 }
100 return false;
101 }
102
lp_exec_mask_update(struct lp_exec_mask * mask)103 void lp_exec_mask_update(struct lp_exec_mask *mask)
104 {
105 LLVMBuilderRef builder = mask->bld->gallivm->builder;
106 bool has_loop_mask = mask_has_loop(mask);
107 bool has_cond_mask = mask_has_cond(mask);
108 bool has_switch_mask = mask_has_switch(mask);
109 bool has_ret_mask = mask->function_stack_size > 1 ||
110 mask->ret_in_main;
111
112 if (has_loop_mask) {
113 /*for loops we need to update the entire mask at runtime */
114 LLVMValueRef tmp;
115 assert(mask->break_mask);
116 tmp = LLVMBuildAnd(builder,
117 mask->cont_mask,
118 mask->break_mask,
119 "maskcb");
120 mask->exec_mask = LLVMBuildAnd(builder,
121 mask->cond_mask,
122 tmp,
123 "maskfull");
124 } else
125 mask->exec_mask = mask->cond_mask;
126
127 if (has_switch_mask) {
128 mask->exec_mask = LLVMBuildAnd(builder,
129 mask->exec_mask,
130 mask->switch_mask,
131 "switchmask");
132 }
133
134 if (has_ret_mask) {
135 mask->exec_mask = LLVMBuildAnd(builder,
136 mask->exec_mask,
137 mask->ret_mask,
138 "callmask");
139 }
140
141 mask->has_mask = (has_cond_mask ||
142 has_loop_mask ||
143 has_switch_mask ||
144 has_ret_mask);
145 }
146
147 /*
148 * Initialize a function context at the specified index.
149 */
150 void
lp_exec_mask_function_init(struct lp_exec_mask * mask,int function_idx)151 lp_exec_mask_function_init(struct lp_exec_mask *mask, int function_idx)
152 {
153 LLVMTypeRef int_type = LLVMInt32TypeInContext(mask->bld->gallivm->context);
154 LLVMBuilderRef builder = mask->bld->gallivm->builder;
155 struct function_ctx *ctx = &mask->function_stack[function_idx];
156
157 ctx->cond_stack_size = 0;
158 ctx->loop_stack_size = 0;
159 ctx->bgnloop_stack_size = 0;
160 ctx->switch_stack_size = 0;
161
162 if (function_idx == 0) {
163 ctx->ret_mask = mask->ret_mask;
164 }
165
166 ctx->loop_limiter = lp_build_alloca(mask->bld->gallivm,
167 int_type, "looplimiter");
168 LLVMBuildStore(
169 builder,
170 LLVMConstInt(int_type, LP_MAX_TGSI_LOOP_ITERATIONS, false),
171 ctx->loop_limiter);
172 }
173
lp_exec_mask_init(struct lp_exec_mask * mask,struct lp_build_context * bld)174 void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context *bld)
175 {
176 mask->bld = bld;
177 mask->has_mask = false;
178 mask->ret_in_main = false;
179 /* For the main function */
180 mask->function_stack_size = 1;
181
182 mask->int_vec_type = lp_build_int_vec_type(bld->gallivm, mask->bld->type);
183 mask->exec_mask = mask->ret_mask = mask->break_mask = mask->cont_mask =
184 mask->cond_mask = mask->switch_mask =
185 LLVMConstAllOnes(mask->int_vec_type);
186
187 mask->function_stack = CALLOC(LP_MAX_NUM_FUNCS,
188 sizeof(mask->function_stack[0]));
189 lp_exec_mask_function_init(mask, 0);
190 }
191
192 void
lp_exec_mask_fini(struct lp_exec_mask * mask)193 lp_exec_mask_fini(struct lp_exec_mask *mask)
194 {
195 FREE(mask->function_stack);
196 }
197
198 /* stores val into an address pointed to by dst_ptr.
199 * mask->exec_mask is used to figure out which bits of val
200 * should be stored into the address
201 * (0 means don't store this bit, 1 means do store).
202 */
lp_exec_mask_store(struct lp_exec_mask * mask,struct lp_build_context * bld_store,LLVMValueRef val,LLVMValueRef dst_ptr)203 void lp_exec_mask_store(struct lp_exec_mask *mask,
204 struct lp_build_context *bld_store,
205 LLVMValueRef val,
206 LLVMValueRef dst_ptr)
207 {
208 LLVMBuilderRef builder = mask->bld->gallivm->builder;
209 LLVMValueRef exec_mask = mask->has_mask ? mask->exec_mask : NULL;
210
211 assert(lp_check_value(bld_store->type, val));
212 assert(LLVMGetTypeKind(LLVMTypeOf(dst_ptr)) == LLVMPointerTypeKind);
213 assert(LLVM_VERSION_MAJOR >= 15
214 || (LLVMGetElementType(LLVMTypeOf(dst_ptr)) == LLVMTypeOf(val)
215 || LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(dst_ptr))) == LLVMArrayTypeKind));
216
217 if (exec_mask) {
218 LLVMValueRef res, dst;
219
220 dst = LLVMBuildLoad2(builder, LLVMTypeOf(val), dst_ptr, "");
221 if (bld_store->type.width < 32)
222 exec_mask = LLVMBuildTrunc(builder, exec_mask, bld_store->vec_type, "");
223 res = lp_build_select(bld_store, exec_mask, val, dst);
224 LLVMBuildStore(builder, res, dst_ptr);
225 } else
226 LLVMBuildStore(builder, val, dst_ptr);
227 }
228
lp_exec_bgnloop_post_phi(struct lp_exec_mask * mask)229 void lp_exec_bgnloop_post_phi(struct lp_exec_mask *mask)
230 {
231 LLVMBuilderRef builder = mask->bld->gallivm->builder;
232 struct function_ctx *ctx = func_ctx(mask);
233
234 if (ctx->loop_stack_size != ctx->bgnloop_stack_size) {
235 mask->break_mask = LLVMBuildLoad2(builder, mask->int_vec_type, ctx->break_var, "");
236 lp_exec_mask_update(mask);
237 ctx->bgnloop_stack_size = ctx->loop_stack_size;
238 }
239 }
240
lp_exec_bgnloop(struct lp_exec_mask * mask,bool load)241 void lp_exec_bgnloop(struct lp_exec_mask *mask, bool load)
242 {
243 LLVMBuilderRef builder = mask->bld->gallivm->builder;
244 struct function_ctx *ctx = func_ctx(mask);
245
246 if (ctx->loop_stack_size >= LP_MAX_TGSI_NESTING) {
247 ++ctx->loop_stack_size;
248 return;
249 }
250
251 ctx->break_type_stack[ctx->loop_stack_size + ctx->switch_stack_size] =
252 ctx->break_type;
253 ctx->break_type = LP_EXEC_MASK_BREAK_TYPE_LOOP;
254
255 ctx->loop_stack[ctx->loop_stack_size].loop_block = ctx->loop_block;
256 ctx->loop_stack[ctx->loop_stack_size].cont_mask = mask->cont_mask;
257 ctx->loop_stack[ctx->loop_stack_size].break_mask = mask->break_mask;
258 ctx->loop_stack[ctx->loop_stack_size].break_var = ctx->break_var;
259 ++ctx->loop_stack_size;
260
261 ctx->break_var = lp_build_alloca(mask->bld->gallivm, mask->int_vec_type, "");
262 LLVMBuildStore(builder, mask->break_mask, ctx->break_var);
263
264 ctx->loop_block = lp_build_insert_new_block(mask->bld->gallivm, "bgnloop");
265
266 LLVMBuildBr(builder, ctx->loop_block);
267 LLVMPositionBuilderAtEnd(builder, ctx->loop_block);
268
269 if (load) {
270 lp_exec_bgnloop_post_phi(mask);
271 }
272 }
273
lp_exec_endloop(struct gallivm_state * gallivm,struct lp_exec_mask * exec_mask,struct lp_build_mask_context * mask)274 void lp_exec_endloop(struct gallivm_state *gallivm,
275 struct lp_exec_mask *exec_mask,
276 struct lp_build_mask_context *mask)
277 {
278 LLVMBuilderRef builder = exec_mask->bld->gallivm->builder;
279 struct function_ctx *ctx = func_ctx(exec_mask);
280 LLVMBasicBlockRef endloop;
281 LLVMTypeRef int_type = LLVMInt32TypeInContext(exec_mask->bld->gallivm->context);
282 LLVMTypeRef mask_type = LLVMIntTypeInContext(exec_mask->bld->gallivm->context, exec_mask->bld->type.length);
283 LLVMValueRef i1cond, i2cond, icond, limiter;
284
285 assert(exec_mask->break_mask);
286
287 assert(ctx->loop_stack_size);
288 if (ctx->loop_stack_size > LP_MAX_TGSI_NESTING) {
289 --ctx->loop_stack_size;
290 --ctx->bgnloop_stack_size;
291 return;
292 }
293
294 /*
295 * Restore the cont_mask, but don't pop
296 */
297 exec_mask->cont_mask = ctx->loop_stack[ctx->loop_stack_size - 1].cont_mask;
298 lp_exec_mask_update(exec_mask);
299
300 /*
301 * Unlike the continue mask, the break_mask must be preserved across loop
302 * iterations
303 */
304 LLVMBuildStore(builder, exec_mask->break_mask, ctx->break_var);
305
306 /* Decrement the loop limiter */
307 limiter = LLVMBuildLoad2(builder, int_type, ctx->loop_limiter, "");
308
309 limiter = LLVMBuildSub(
310 builder,
311 limiter,
312 LLVMConstInt(int_type, 1, false),
313 "");
314
315 LLVMBuildStore(builder, limiter, ctx->loop_limiter);
316
317 LLVMValueRef end_mask = exec_mask->exec_mask;
318 if (mask)
319 end_mask = LLVMBuildAnd(builder, exec_mask->exec_mask, lp_build_mask_value(mask), "");
320 end_mask = LLVMBuildICmp(builder, LLVMIntNE, end_mask, lp_build_zero(gallivm, exec_mask->bld->type), "");
321 end_mask = LLVMBuildBitCast(builder, end_mask, mask_type, "");
322
323 /* i1cond = (end_mask != 0) */
324 i1cond = LLVMBuildICmp(
325 builder,
326 LLVMIntNE,
327 end_mask,
328 LLVMConstNull(mask_type), "i1cond");
329
330 /* i2cond = (looplimiter > 0) */
331 i2cond = LLVMBuildICmp(
332 builder,
333 LLVMIntSGT,
334 limiter,
335 LLVMConstNull(int_type), "i2cond");
336
337 /* if( i1cond && i2cond ) */
338 icond = LLVMBuildAnd(builder, i1cond, i2cond, "");
339
340 endloop = lp_build_insert_new_block(exec_mask->bld->gallivm, "endloop");
341
342 LLVMBuildCondBr(builder,
343 icond, ctx->loop_block, endloop);
344
345 LLVMPositionBuilderAtEnd(builder, endloop);
346
347 assert(ctx->loop_stack_size);
348 --ctx->loop_stack_size;
349 --ctx->bgnloop_stack_size;
350 exec_mask->cont_mask = ctx->loop_stack[ctx->loop_stack_size].cont_mask;
351 exec_mask->break_mask = ctx->loop_stack[ctx->loop_stack_size].break_mask;
352 ctx->loop_block = ctx->loop_stack[ctx->loop_stack_size].loop_block;
353 ctx->break_var = ctx->loop_stack[ctx->loop_stack_size].break_var;
354 ctx->break_type = ctx->break_type_stack[ctx->loop_stack_size +
355 ctx->switch_stack_size];
356
357 lp_exec_mask_update(exec_mask);
358 }
359
lp_exec_mask_cond_push(struct lp_exec_mask * mask,LLVMValueRef val)360 void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
361 LLVMValueRef val)
362 {
363 LLVMBuilderRef builder = mask->bld->gallivm->builder;
364 struct function_ctx *ctx = func_ctx(mask);
365
366 if (ctx->cond_stack_size >= LP_MAX_TGSI_NESTING) {
367 ctx->cond_stack_size++;
368 return;
369 }
370 if (ctx->cond_stack_size == 0 && mask->function_stack_size == 1) {
371 assert(mask->cond_mask == LLVMConstAllOnes(mask->int_vec_type));
372 }
373 ctx->cond_stack[ctx->cond_stack_size++] = mask->cond_mask;
374 assert(LLVMTypeOf(val) == mask->int_vec_type);
375 mask->cond_mask = LLVMBuildAnd(builder,
376 mask->cond_mask,
377 val,
378 "");
379 lp_exec_mask_update(mask);
380 }
381
lp_exec_mask_cond_invert(struct lp_exec_mask * mask)382 void lp_exec_mask_cond_invert(struct lp_exec_mask *mask)
383 {
384 LLVMBuilderRef builder = mask->bld->gallivm->builder;
385 struct function_ctx *ctx = func_ctx(mask);
386 LLVMValueRef prev_mask;
387 LLVMValueRef inv_mask;
388
389 assert(ctx->cond_stack_size);
390 if (ctx->cond_stack_size >= LP_MAX_TGSI_NESTING)
391 return;
392 prev_mask = ctx->cond_stack[ctx->cond_stack_size - 1];
393 if (ctx->cond_stack_size == 1 && mask->function_stack_size == 1) {
394 assert(prev_mask == LLVMConstAllOnes(mask->int_vec_type));
395 }
396
397 inv_mask = LLVMBuildNot(builder, mask->cond_mask, "");
398
399 mask->cond_mask = LLVMBuildAnd(builder,
400 inv_mask,
401 prev_mask, "");
402 lp_exec_mask_update(mask);
403 }
404
lp_exec_mask_cond_pop(struct lp_exec_mask * mask)405 void lp_exec_mask_cond_pop(struct lp_exec_mask *mask)
406 {
407 struct function_ctx *ctx = func_ctx(mask);
408 assert(ctx->cond_stack_size);
409 --ctx->cond_stack_size;
410 if (ctx->cond_stack_size >= LP_MAX_TGSI_NESTING)
411 return;
412 mask->cond_mask = ctx->cond_stack[ctx->cond_stack_size];
413 lp_exec_mask_update(mask);
414 }
415
416
lp_exec_continue(struct lp_exec_mask * mask)417 void lp_exec_continue(struct lp_exec_mask *mask)
418 {
419 LLVMBuilderRef builder = mask->bld->gallivm->builder;
420 LLVMValueRef exec_mask = LLVMBuildNot(builder,
421 mask->exec_mask,
422 "");
423
424 mask->cont_mask = LLVMBuildAnd(builder,
425 mask->cont_mask,
426 exec_mask, "");
427
428 lp_exec_mask_update(mask);
429 }
430
lp_exec_break(struct lp_exec_mask * mask,int * pc,bool break_always)431 void lp_exec_break(struct lp_exec_mask *mask, int *pc,
432 bool break_always)
433 {
434 LLVMBuilderRef builder = mask->bld->gallivm->builder;
435 struct function_ctx *ctx = func_ctx(mask);
436
437 if (ctx->break_type == LP_EXEC_MASK_BREAK_TYPE_LOOP) {
438 LLVMValueRef exec_mask = LLVMBuildNot(builder,
439 mask->exec_mask,
440 "break");
441
442 mask->break_mask = LLVMBuildAnd(builder,
443 mask->break_mask,
444 exec_mask, "break_full");
445 }
446 else {
447 if (ctx->switch_in_default) {
448 /*
449 * stop default execution but only if this is an unconditional switch.
450 * (The condition here is not perfect since dead code after break is
451 * allowed but should be sufficient since false negatives are just
452 * unoptimized - so we don't have to pre-evaluate that).
453 */
454 if(break_always && ctx->switch_pc) {
455 if (pc)
456 *pc = ctx->switch_pc;
457 return;
458 }
459 }
460
461 if (break_always) {
462 mask->switch_mask = LLVMConstNull(mask->bld->int_vec_type);
463 }
464 else {
465 LLVMValueRef exec_mask = LLVMBuildNot(builder,
466 mask->exec_mask,
467 "break");
468 mask->switch_mask = LLVMBuildAnd(builder,
469 mask->switch_mask,
470 exec_mask, "break_switch");
471 }
472 }
473
474 lp_exec_mask_update(mask);
475 }
476