revert 213 commits (to 56092) from the last month. 10 still need work to resolve...
[AROS.git] / workbench / libs / mesa / src / gallium / auxiliary / gallivm / lp_bld_flow.c
bloba9c9c7af10c2d046fe28124b853c40b06af4d047
1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 /**
29 * LLVM control flow build helpers.
31 * @author Jose Fonseca <jfonseca@vmware.com>
34 #include "util/u_debug.h"
35 #include "util/u_memory.h"
37 #include "lp_bld_init.h"
38 #include "lp_bld_type.h"
39 #include "lp_bld_flow.h"
42 /**
43 * Insert a new block, right where builder is pointing to.
45 * This is useful important not only for aesthetic reasons, but also for
46 * performance reasons, as frequently run blocks should be laid out next to
47 * each other and fall-throughs maximized.
49 * See also llvm/lib/Transforms/Scalar/BasicBlockPlacement.cpp.
51 * Note: this function has no dependencies on the flow code and could
52 * be used elsewhere.
54 LLVMBasicBlockRef
55 lp_build_insert_new_block(struct gallivm_state *gallivm, const char *name)
57 LLVMBasicBlockRef current_block;
58 LLVMBasicBlockRef next_block;
59 LLVMBasicBlockRef new_block;
61 /* get current basic block */
62 current_block = LLVMGetInsertBlock(gallivm->builder);
64 /* check if there's another block after this one */
65 next_block = LLVMGetNextBasicBlock(current_block);
66 if (next_block) {
67 /* insert the new block before the next block */
68 new_block = LLVMInsertBasicBlockInContext(gallivm->context, next_block, name);
70 else {
71 /* append new block after current block */
72 LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
73 new_block = LLVMAppendBasicBlockInContext(gallivm->context, function, name);
76 return new_block;
80 /**
81 * Begin a "skip" block. Inside this block we can test a condition and
82 * skip to the end of the block if the condition is false.
84 void
85 lp_build_flow_skip_begin(struct lp_build_skip_context *skip,
86 struct gallivm_state *gallivm)
88 skip->gallivm = gallivm;
89 /* create new basic block */
90 skip->block = lp_build_insert_new_block(gallivm, "skip");
94 /**
95 * Insert code to test a condition and branch to the end of the current
96 * skip block if the condition is true.
98 void
99 lp_build_flow_skip_cond_break(struct lp_build_skip_context *skip,
100 LLVMValueRef cond)
102 LLVMBasicBlockRef new_block;
104 new_block = lp_build_insert_new_block(skip->gallivm, "");
106 /* if cond is true, goto skip->block, else goto new_block */
107 LLVMBuildCondBr(skip->gallivm->builder, cond, skip->block, new_block);
109 LLVMPositionBuilderAtEnd(skip->gallivm->builder, new_block);
113 void
114 lp_build_flow_skip_end(struct lp_build_skip_context *skip)
116 /* goto block */
117 LLVMBuildBr(skip->gallivm->builder, skip->block);
118 LLVMPositionBuilderAtEnd(skip->gallivm->builder, skip->block);
123 * Check if the mask predicate is zero. If so, jump to the end of the block.
125 void
126 lp_build_mask_check(struct lp_build_mask_context *mask)
128 LLVMBuilderRef builder = mask->skip.gallivm->builder;
129 LLVMValueRef value;
130 LLVMValueRef cond;
132 value = lp_build_mask_value(mask);
134 /* cond = (mask == 0) */
135 cond = LLVMBuildICmp(builder,
136 LLVMIntEQ,
137 LLVMBuildBitCast(builder, value, mask->reg_type, ""),
138 LLVMConstNull(mask->reg_type),
139 "");
141 /* if cond, goto end of block */
142 lp_build_flow_skip_cond_break(&mask->skip, cond);
147 * Begin a section of code which is predicated on a mask.
148 * \param mask the mask context, initialized here
149 * \param flow the flow context
150 * \param type the type of the mask
151 * \param value storage for the mask
153 void
154 lp_build_mask_begin(struct lp_build_mask_context *mask,
155 struct gallivm_state *gallivm,
156 struct lp_type type,
157 LLVMValueRef value)
159 memset(mask, 0, sizeof *mask);
161 mask->reg_type = LLVMIntTypeInContext(gallivm->context, type.width * type.length);
162 mask->var = lp_build_alloca(gallivm,
163 lp_build_int_vec_type(gallivm, type),
164 "execution_mask");
166 LLVMBuildStore(gallivm->builder, value, mask->var);
168 lp_build_flow_skip_begin(&mask->skip, gallivm);
172 LLVMValueRef
173 lp_build_mask_value(struct lp_build_mask_context *mask)
175 return LLVMBuildLoad(mask->skip.gallivm->builder, mask->var, "");
180 * Update boolean mask with given value (bitwise AND).
181 * Typically used to update the quad's pixel alive/killed mask
182 * after depth testing, alpha testing, TGSI_OPCODE_KIL, etc.
184 void
185 lp_build_mask_update(struct lp_build_mask_context *mask,
186 LLVMValueRef value)
188 value = LLVMBuildAnd(mask->skip.gallivm->builder,
189 lp_build_mask_value(mask),
190 value, "");
191 LLVMBuildStore(mask->skip.gallivm->builder, value, mask->var);
196 * End section of code which is predicated on a mask.
198 LLVMValueRef
199 lp_build_mask_end(struct lp_build_mask_context *mask)
201 lp_build_flow_skip_end(&mask->skip);
202 return lp_build_mask_value(mask);
207 void
208 lp_build_loop_begin(struct lp_build_loop_state *state,
209 struct gallivm_state *gallivm,
210 LLVMValueRef start)
213 LLVMBuilderRef builder = gallivm->builder;
215 state->block = lp_build_insert_new_block(gallivm, "loop_begin");
217 state->counter_var = lp_build_alloca(gallivm, LLVMTypeOf(start), "loop_counter");
218 state->gallivm = gallivm;
220 LLVMBuildStore(builder, start, state->counter_var);
222 LLVMBuildBr(builder, state->block);
224 LLVMPositionBuilderAtEnd(builder, state->block);
226 state->counter = LLVMBuildLoad(builder, state->counter_var, "");
230 void
231 lp_build_loop_end_cond(struct lp_build_loop_state *state,
232 LLVMValueRef end,
233 LLVMValueRef step,
234 LLVMIntPredicate llvm_cond)
236 LLVMBuilderRef builder = state->gallivm->builder;
237 LLVMValueRef next;
238 LLVMValueRef cond;
239 LLVMBasicBlockRef after_block;
241 if (!step)
242 step = LLVMConstInt(LLVMTypeOf(end), 1, 0);
244 next = LLVMBuildAdd(builder, state->counter, step, "");
246 LLVMBuildStore(builder, next, state->counter_var);
248 cond = LLVMBuildICmp(builder, llvm_cond, next, end, "");
250 after_block = lp_build_insert_new_block(state->gallivm, "loop_end");
252 LLVMBuildCondBr(builder, cond, after_block, state->block);
254 LLVMPositionBuilderAtEnd(builder, after_block);
256 state->counter = LLVMBuildLoad(builder, state->counter_var, "");
260 void
261 lp_build_loop_end(struct lp_build_loop_state *state,
262 LLVMValueRef end,
263 LLVMValueRef step)
265 lp_build_loop_end_cond(state, end, step, LLVMIntNE);
271 Example of if/then/else building:
273 int x;
274 if (cond) {
275 x = 1 + 2;
277 else {
278 x = 2 + 3;
281 Is built with:
283 // x needs an alloca variable
284 x = lp_build_alloca(builder, type, "x");
287 lp_build_if(ctx, builder, cond);
288 LLVMBuildStore(LLVMBuildAdd(1, 2), x);
289 lp_build_else(ctx);
290 LLVMBuildStore(LLVMBuildAdd(2, 3). x);
291 lp_build_endif(ctx);
298 * Begin an if/else/endif construct.
300 void
301 lp_build_if(struct lp_build_if_state *ifthen,
302 struct gallivm_state *gallivm,
303 LLVMValueRef condition)
305 LLVMBasicBlockRef block = LLVMGetInsertBlock(gallivm->builder);
307 memset(ifthen, 0, sizeof *ifthen);
308 ifthen->gallivm = gallivm;
309 ifthen->condition = condition;
310 ifthen->entry_block = block;
312 /* create endif/merge basic block for the phi functions */
313 ifthen->merge_block = lp_build_insert_new_block(gallivm, "endif-block");
315 /* create/insert true_block before merge_block */
316 ifthen->true_block =
317 LLVMInsertBasicBlockInContext(gallivm->context,
318 ifthen->merge_block,
319 "if-true-block");
321 /* successive code goes into the true block */
322 LLVMPositionBuilderAtEnd(gallivm->builder, ifthen->true_block);
327 * Begin else-part of a conditional
329 void
330 lp_build_else(struct lp_build_if_state *ifthen)
332 LLVMBuilderRef builder = ifthen->gallivm->builder;
334 /* Append an unconditional Br(anch) instruction on the true_block */
335 LLVMBuildBr(builder, ifthen->merge_block);
337 /* create/insert false_block before the merge block */
338 ifthen->false_block =
339 LLVMInsertBasicBlockInContext(ifthen->gallivm->context,
340 ifthen->merge_block,
341 "if-false-block");
343 /* successive code goes into the else block */
344 LLVMPositionBuilderAtEnd(builder, ifthen->false_block);
349 * End a conditional.
351 void
352 lp_build_endif(struct lp_build_if_state *ifthen)
354 LLVMBuilderRef builder = ifthen->gallivm->builder;
356 /* Insert branch to the merge block from current block */
357 LLVMBuildBr(builder, ifthen->merge_block);
360 * Now patch in the various branch instructions.
363 /* Insert the conditional branch instruction at the end of entry_block */
364 LLVMPositionBuilderAtEnd(builder, ifthen->entry_block);
365 if (ifthen->false_block) {
366 /* we have an else clause */
367 LLVMBuildCondBr(builder, ifthen->condition,
368 ifthen->true_block, ifthen->false_block);
370 else {
371 /* no else clause */
372 LLVMBuildCondBr(builder, ifthen->condition,
373 ifthen->true_block, ifthen->merge_block);
376 /* Resume building code at end of the ifthen->merge_block */
377 LLVMPositionBuilderAtEnd(builder, ifthen->merge_block);
382 * Allocate a scalar (or vector) variable.
384 * Although not strictly part of control flow, control flow has deep impact in
385 * how variables should be allocated.
387 * The mem2reg optimization pass is the recommended way to dealing with mutable
388 * variables, and SSA. It looks for allocas and if it can handle them, it
389 * promotes them, but only looks for alloca instructions in the entry block of
390 * the function. Being in the entry block guarantees that the alloca is only
391 * executed once, which makes analysis simpler.
393 * See also:
394 * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory
396 LLVMValueRef
397 lp_build_alloca(struct gallivm_state *gallivm,
398 LLVMTypeRef type,
399 const char *name)
401 LLVMBuilderRef builder = gallivm->builder;
402 LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
403 LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
404 LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
405 LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
406 LLVMBuilderRef first_builder = LLVMCreateBuilderInContext(gallivm->context);
407 LLVMValueRef res;
409 if (first_instr) {
410 LLVMPositionBuilderBefore(first_builder, first_instr);
411 } else {
412 LLVMPositionBuilderAtEnd(first_builder, first_block);
415 res = LLVMBuildAlloca(first_builder, type, name);
416 LLVMBuildStore(builder, LLVMConstNull(type), res);
418 LLVMDisposeBuilder(first_builder);
420 return res;
425 * Allocate an array of scalars/vectors.
427 * mem2reg pass is not capable of promoting structs or arrays to registers, but
428 * we still put it in the first block anyway as failure to put allocas in the
429 * first block may prevent the X86 backend from successfully align the stack as
430 * required.
432 * Also the scalarrepl pass is supposedly more powerful and can promote
433 * arrays in many cases.
435 * See also:
436 * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory
438 LLVMValueRef
439 lp_build_array_alloca(struct gallivm_state *gallivm,
440 LLVMTypeRef type,
441 LLVMValueRef count,
442 const char *name)
444 LLVMBuilderRef builder = gallivm->builder;
445 LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
446 LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
447 LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
448 LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
449 LLVMBuilderRef first_builder = LLVMCreateBuilderInContext(gallivm->context);
450 LLVMValueRef res;
452 if (first_instr) {
453 LLVMPositionBuilderBefore(first_builder, first_instr);
454 } else {
455 LLVMPositionBuilderAtEnd(first_builder, first_block);
458 res = LLVMBuildArrayAlloca(first_builder, type, count, name);
460 LLVMDisposeBuilder(first_builder);
462 return res;