• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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