1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/**
29bf215546Sopenharmony_ci * LLVM control flow build helpers.
30bf215546Sopenharmony_ci *
31bf215546Sopenharmony_ci * @author Jose Fonseca <jfonseca@vmware.com>
32bf215546Sopenharmony_ci */
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#include "util/u_debug.h"
35bf215546Sopenharmony_ci#include "util/u_memory.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "lp_bld_init.h"
38bf215546Sopenharmony_ci#include "lp_bld_type.h"
39bf215546Sopenharmony_ci#include "lp_bld_flow.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci/**
43bf215546Sopenharmony_ci * Insert a new block, right where builder is pointing to.
44bf215546Sopenharmony_ci *
45bf215546Sopenharmony_ci * This is useful important not only for aesthetic reasons, but also for
46bf215546Sopenharmony_ci * performance reasons, as frequently run blocks should be laid out next to
47bf215546Sopenharmony_ci * each other and fall-throughs maximized.
48bf215546Sopenharmony_ci *
49bf215546Sopenharmony_ci * See also llvm/lib/Transforms/Scalar/BasicBlockPlacement.cpp.
50bf215546Sopenharmony_ci *
51bf215546Sopenharmony_ci * Note: this function has no dependencies on the flow code and could
52bf215546Sopenharmony_ci * be used elsewhere.
53bf215546Sopenharmony_ci */
54bf215546Sopenharmony_ciLLVMBasicBlockRef
55bf215546Sopenharmony_cilp_build_insert_new_block(struct gallivm_state *gallivm, const char *name)
56bf215546Sopenharmony_ci{
57bf215546Sopenharmony_ci   LLVMBasicBlockRef current_block;
58bf215546Sopenharmony_ci   LLVMBasicBlockRef next_block;
59bf215546Sopenharmony_ci   LLVMBasicBlockRef new_block;
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   /* get current basic block */
62bf215546Sopenharmony_ci   current_block = LLVMGetInsertBlock(gallivm->builder);
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   /* check if there's another block after this one */
65bf215546Sopenharmony_ci   next_block = LLVMGetNextBasicBlock(current_block);
66bf215546Sopenharmony_ci   if (next_block) {
67bf215546Sopenharmony_ci      /* insert the new block before the next block */
68bf215546Sopenharmony_ci      new_block = LLVMInsertBasicBlockInContext(gallivm->context, next_block, name);
69bf215546Sopenharmony_ci   }
70bf215546Sopenharmony_ci   else {
71bf215546Sopenharmony_ci      /* append new block after current block */
72bf215546Sopenharmony_ci      LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
73bf215546Sopenharmony_ci      new_block = LLVMAppendBasicBlockInContext(gallivm->context, function, name);
74bf215546Sopenharmony_ci   }
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   return new_block;
77bf215546Sopenharmony_ci}
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci/**
81bf215546Sopenharmony_ci * Begin a "skip" block.  Inside this block we can test a condition and
82bf215546Sopenharmony_ci * skip to the end of the block if the condition is false.
83bf215546Sopenharmony_ci */
84bf215546Sopenharmony_civoid
85bf215546Sopenharmony_cilp_build_flow_skip_begin(struct lp_build_skip_context *skip,
86bf215546Sopenharmony_ci                         struct gallivm_state *gallivm)
87bf215546Sopenharmony_ci{
88bf215546Sopenharmony_ci   skip->gallivm = gallivm;
89bf215546Sopenharmony_ci   /* create new basic block */
90bf215546Sopenharmony_ci   skip->block = lp_build_insert_new_block(gallivm, "skip");
91bf215546Sopenharmony_ci}
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci/**
95bf215546Sopenharmony_ci * Insert code to test a condition and branch to the end of the current
96bf215546Sopenharmony_ci * skip block if the condition is true.
97bf215546Sopenharmony_ci */
98bf215546Sopenharmony_civoid
99bf215546Sopenharmony_cilp_build_flow_skip_cond_break(struct lp_build_skip_context *skip,
100bf215546Sopenharmony_ci                              LLVMValueRef cond)
101bf215546Sopenharmony_ci{
102bf215546Sopenharmony_ci   LLVMBasicBlockRef new_block;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   new_block = lp_build_insert_new_block(skip->gallivm, "");
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   /* if cond is true, goto skip->block, else goto new_block */
107bf215546Sopenharmony_ci   LLVMBuildCondBr(skip->gallivm->builder, cond, skip->block, new_block);
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(skip->gallivm->builder, new_block);
110bf215546Sopenharmony_ci}
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_civoid
114bf215546Sopenharmony_cilp_build_flow_skip_end(struct lp_build_skip_context *skip)
115bf215546Sopenharmony_ci{
116bf215546Sopenharmony_ci   /* goto block */
117bf215546Sopenharmony_ci   LLVMBuildBr(skip->gallivm->builder, skip->block);
118bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(skip->gallivm->builder, skip->block);
119bf215546Sopenharmony_ci}
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci/**
123bf215546Sopenharmony_ci * Check if the mask predicate is zero.  If so, jump to the end of the block.
124bf215546Sopenharmony_ci */
125bf215546Sopenharmony_civoid
126bf215546Sopenharmony_cilp_build_mask_check(struct lp_build_mask_context *mask)
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci   LLVMBuilderRef builder = mask->skip.gallivm->builder;
129bf215546Sopenharmony_ci   LLVMValueRef value;
130bf215546Sopenharmony_ci   LLVMValueRef cond;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   value = lp_build_mask_value(mask);
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   /*
135bf215546Sopenharmony_ci    * XXX this doesn't quite generate the most efficient code possible, if
136bf215546Sopenharmony_ci    * the masks are vectors which have all bits set to the same value
137bf215546Sopenharmony_ci    * in each element.
138bf215546Sopenharmony_ci    * movmskps/pmovmskb would be more efficient to get the required value
139bf215546Sopenharmony_ci    * into ordinary reg (certainly with 8 floats).
140bf215546Sopenharmony_ci    * Not sure if llvm could figure that out on its own.
141bf215546Sopenharmony_ci    */
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   /* cond = (mask == 0) */
144bf215546Sopenharmony_ci   cond = LLVMBuildICmp(builder,
145bf215546Sopenharmony_ci                        LLVMIntEQ,
146bf215546Sopenharmony_ci                        LLVMBuildBitCast(builder, value, mask->reg_type, ""),
147bf215546Sopenharmony_ci                        LLVMConstNull(mask->reg_type),
148bf215546Sopenharmony_ci                        "");
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   /* if cond, goto end of block */
151bf215546Sopenharmony_ci   lp_build_flow_skip_cond_break(&mask->skip, cond);
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci/**
156bf215546Sopenharmony_ci * Begin a section of code which is predicated on a mask.
157bf215546Sopenharmony_ci * \param mask  the mask context, initialized here
158bf215546Sopenharmony_ci * \param flow  the flow context
159bf215546Sopenharmony_ci * \param type  the type of the mask
160bf215546Sopenharmony_ci * \param value  storage for the mask
161bf215546Sopenharmony_ci */
162bf215546Sopenharmony_civoid
163bf215546Sopenharmony_cilp_build_mask_begin(struct lp_build_mask_context *mask,
164bf215546Sopenharmony_ci                    struct gallivm_state *gallivm,
165bf215546Sopenharmony_ci                    struct lp_type type,
166bf215546Sopenharmony_ci                    LLVMValueRef value)
167bf215546Sopenharmony_ci{
168bf215546Sopenharmony_ci   memset(mask, 0, sizeof *mask);
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   mask->reg_type = LLVMIntTypeInContext(gallivm->context, type.width * type.length);
171bf215546Sopenharmony_ci   mask->var_type = lp_build_int_vec_type(gallivm, type);
172bf215546Sopenharmony_ci   mask->var = lp_build_alloca(gallivm,
173bf215546Sopenharmony_ci                               mask->var_type,
174bf215546Sopenharmony_ci                               "execution_mask");
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   LLVMBuildStore(gallivm->builder, value, mask->var);
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   lp_build_flow_skip_begin(&mask->skip, gallivm);
179bf215546Sopenharmony_ci}
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ciLLVMValueRef
183bf215546Sopenharmony_cilp_build_mask_value(struct lp_build_mask_context *mask)
184bf215546Sopenharmony_ci{
185bf215546Sopenharmony_ci   return LLVMBuildLoad2(mask->skip.gallivm->builder, mask->var_type, mask->var, "");
186bf215546Sopenharmony_ci}
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci/**
190bf215546Sopenharmony_ci * Update boolean mask with given value (bitwise AND).
191bf215546Sopenharmony_ci * Typically used to update the quad's pixel alive/killed mask
192bf215546Sopenharmony_ci * after depth testing, alpha testing, TGSI_OPCODE_KILL_IF, etc.
193bf215546Sopenharmony_ci */
194bf215546Sopenharmony_civoid
195bf215546Sopenharmony_cilp_build_mask_update(struct lp_build_mask_context *mask,
196bf215546Sopenharmony_ci                     LLVMValueRef value)
197bf215546Sopenharmony_ci{
198bf215546Sopenharmony_ci   value = LLVMBuildAnd(mask->skip.gallivm->builder,
199bf215546Sopenharmony_ci                        lp_build_mask_value(mask),
200bf215546Sopenharmony_ci                        value, "");
201bf215546Sopenharmony_ci   LLVMBuildStore(mask->skip.gallivm->builder, value, mask->var);
202bf215546Sopenharmony_ci}
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci/*
205bf215546Sopenharmony_ci * Update boolean mask with given value.
206bf215546Sopenharmony_ci * Used for per-sample shading to force per-sample execution masks.
207bf215546Sopenharmony_ci */
208bf215546Sopenharmony_civoid
209bf215546Sopenharmony_cilp_build_mask_force(struct lp_build_mask_context *mask,
210bf215546Sopenharmony_ci                    LLVMValueRef value)
211bf215546Sopenharmony_ci{
212bf215546Sopenharmony_ci   LLVMBuildStore(mask->skip.gallivm->builder, value, mask->var);
213bf215546Sopenharmony_ci}
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci/**
216bf215546Sopenharmony_ci * End section of code which is predicated on a mask.
217bf215546Sopenharmony_ci */
218bf215546Sopenharmony_ciLLVMValueRef
219bf215546Sopenharmony_cilp_build_mask_end(struct lp_build_mask_context *mask)
220bf215546Sopenharmony_ci{
221bf215546Sopenharmony_ci   lp_build_flow_skip_end(&mask->skip);
222bf215546Sopenharmony_ci   return lp_build_mask_value(mask);
223bf215546Sopenharmony_ci}
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_civoid
228bf215546Sopenharmony_cilp_build_loop_begin(struct lp_build_loop_state *state,
229bf215546Sopenharmony_ci                    struct gallivm_state *gallivm,
230bf215546Sopenharmony_ci                    LLVMValueRef start)
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci{
233bf215546Sopenharmony_ci   LLVMBuilderRef builder = gallivm->builder;
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   state->block = lp_build_insert_new_block(gallivm, "loop_begin");
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci   state->counter_type = LLVMTypeOf(start);
238bf215546Sopenharmony_ci   state->counter_var = lp_build_alloca(gallivm, state->counter_type, "loop_counter");
239bf215546Sopenharmony_ci   state->gallivm = gallivm;
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci   LLVMBuildStore(builder, start, state->counter_var);
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   LLVMBuildBr(builder, state->block);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(builder, state->block);
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci   state->counter = LLVMBuildLoad2(builder, state->counter_type, state->counter_var, "");
248bf215546Sopenharmony_ci}
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_civoid
252bf215546Sopenharmony_cilp_build_loop_end_cond(struct lp_build_loop_state *state,
253bf215546Sopenharmony_ci                       LLVMValueRef end,
254bf215546Sopenharmony_ci                       LLVMValueRef step,
255bf215546Sopenharmony_ci                       LLVMIntPredicate llvm_cond)
256bf215546Sopenharmony_ci{
257bf215546Sopenharmony_ci   LLVMBuilderRef builder = state->gallivm->builder;
258bf215546Sopenharmony_ci   LLVMValueRef next;
259bf215546Sopenharmony_ci   LLVMValueRef cond;
260bf215546Sopenharmony_ci   LLVMBasicBlockRef after_block;
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci   if (!step)
263bf215546Sopenharmony_ci      step = LLVMConstInt(LLVMTypeOf(end), 1, 0);
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci   next = LLVMBuildAdd(builder, state->counter, step, "");
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   LLVMBuildStore(builder, next, state->counter_var);
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci   cond = LLVMBuildICmp(builder, llvm_cond, next, end, "");
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci   after_block = lp_build_insert_new_block(state->gallivm, "loop_end");
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci   LLVMBuildCondBr(builder, cond, after_block, state->block);
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(builder, after_block);
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   state->counter = LLVMBuildLoad2(builder, state->counter_type, state->counter_var, "");
278bf215546Sopenharmony_ci}
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_civoid
281bf215546Sopenharmony_cilp_build_loop_force_set_counter(struct lp_build_loop_state *state,
282bf215546Sopenharmony_ci                          LLVMValueRef end)
283bf215546Sopenharmony_ci{
284bf215546Sopenharmony_ci   LLVMBuilderRef builder = state->gallivm->builder;
285bf215546Sopenharmony_ci   LLVMBuildStore(builder, end, state->counter_var);
286bf215546Sopenharmony_ci}
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_civoid
289bf215546Sopenharmony_cilp_build_loop_force_reload_counter(struct lp_build_loop_state *state)
290bf215546Sopenharmony_ci{
291bf215546Sopenharmony_ci   LLVMBuilderRef builder = state->gallivm->builder;
292bf215546Sopenharmony_ci   state->counter = LLVMBuildLoad2(builder, state->counter_type, state->counter_var, "");
293bf215546Sopenharmony_ci}
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_civoid
296bf215546Sopenharmony_cilp_build_loop_end(struct lp_build_loop_state *state,
297bf215546Sopenharmony_ci                  LLVMValueRef end,
298bf215546Sopenharmony_ci                  LLVMValueRef step)
299bf215546Sopenharmony_ci{
300bf215546Sopenharmony_ci   lp_build_loop_end_cond(state, end, step, LLVMIntNE);
301bf215546Sopenharmony_ci}
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci/**
304bf215546Sopenharmony_ci * Creates a c-style for loop,
305bf215546Sopenharmony_ci * contrasts lp_build_loop as this checks condition on entry
306bf215546Sopenharmony_ci * e.g. for(i = start; i cmp_op end; i += step)
307bf215546Sopenharmony_ci * \param state      the for loop state, initialized here
308bf215546Sopenharmony_ci * \param gallivm    the gallivm state
309bf215546Sopenharmony_ci * \param start      starting value of iterator
310bf215546Sopenharmony_ci * \param cmp_op     comparison operator used for comparing current value with end value
311bf215546Sopenharmony_ci * \param end        value used to compare against iterator
312bf215546Sopenharmony_ci * \param step       value added to iterator at end of each loop
313bf215546Sopenharmony_ci */
314bf215546Sopenharmony_civoid
315bf215546Sopenharmony_cilp_build_for_loop_begin(struct lp_build_for_loop_state *state,
316bf215546Sopenharmony_ci                        struct gallivm_state *gallivm,
317bf215546Sopenharmony_ci                        LLVMValueRef start,
318bf215546Sopenharmony_ci                        LLVMIntPredicate cmp_op,
319bf215546Sopenharmony_ci                        LLVMValueRef end,
320bf215546Sopenharmony_ci                        LLVMValueRef step)
321bf215546Sopenharmony_ci{
322bf215546Sopenharmony_ci   LLVMBuilderRef builder = gallivm->builder;
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci   assert(LLVMTypeOf(start) == LLVMTypeOf(end));
325bf215546Sopenharmony_ci   assert(LLVMTypeOf(start) == LLVMTypeOf(step));
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci   state->begin = lp_build_insert_new_block(gallivm, "loop_begin");
328bf215546Sopenharmony_ci   state->step  = step;
329bf215546Sopenharmony_ci   state->counter_type = LLVMTypeOf(start);
330bf215546Sopenharmony_ci   state->counter_var = lp_build_alloca(gallivm, state->counter_type, "loop_counter");
331bf215546Sopenharmony_ci   state->gallivm = gallivm;
332bf215546Sopenharmony_ci   state->cond = cmp_op;
333bf215546Sopenharmony_ci   state->end = end;
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci   LLVMBuildStore(builder, start, state->counter_var);
336bf215546Sopenharmony_ci   LLVMBuildBr(builder, state->begin);
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(builder, state->begin);
339bf215546Sopenharmony_ci   state->counter = LLVMBuildLoad2(builder, state->counter_type, state->counter_var, "");
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci   state->body = lp_build_insert_new_block(gallivm, "loop_body");
342bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(builder, state->body);
343bf215546Sopenharmony_ci}
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci/**
346bf215546Sopenharmony_ci * End the for loop.
347bf215546Sopenharmony_ci */
348bf215546Sopenharmony_civoid
349bf215546Sopenharmony_cilp_build_for_loop_end(struct lp_build_for_loop_state *state)
350bf215546Sopenharmony_ci{
351bf215546Sopenharmony_ci   LLVMValueRef next, cond;
352bf215546Sopenharmony_ci   LLVMBuilderRef builder = state->gallivm->builder;
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   next = LLVMBuildAdd(builder, state->counter, state->step, "");
355bf215546Sopenharmony_ci   LLVMBuildStore(builder, next, state->counter_var);
356bf215546Sopenharmony_ci   LLVMBuildBr(builder, state->begin);
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci   state->exit = lp_build_insert_new_block(state->gallivm, "loop_exit");
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci   /*
361bf215546Sopenharmony_ci    * We build the comparison for the begin block here,
362bf215546Sopenharmony_ci    * if we build it earlier the output llvm ir is not human readable
363bf215546Sopenharmony_ci    * as the code produced is not in the standard begin -> body -> end order.
364bf215546Sopenharmony_ci    */
365bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(builder, state->begin);
366bf215546Sopenharmony_ci   cond = LLVMBuildICmp(builder, state->cond, state->counter, state->end, "");
367bf215546Sopenharmony_ci   LLVMBuildCondBr(builder, cond, state->body, state->exit);
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(builder, state->exit);
370bf215546Sopenharmony_ci}
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci/*
374bf215546Sopenharmony_ci  Example of if/then/else building:
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci     int x;
377bf215546Sopenharmony_ci     if (cond) {
378bf215546Sopenharmony_ci        x = 1 + 2;
379bf215546Sopenharmony_ci     }
380bf215546Sopenharmony_ci     else {
381bf215546Sopenharmony_ci        x = 2 + 3;
382bf215546Sopenharmony_ci     }
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci  Is built with:
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci     // x needs an alloca variable
387bf215546Sopenharmony_ci     x = lp_build_alloca(builder, type, "x");
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci     lp_build_if(ctx, builder, cond);
391bf215546Sopenharmony_ci        LLVMBuildStore(LLVMBuildAdd(1, 2), x);
392bf215546Sopenharmony_ci     lp_build_else(ctx);
393bf215546Sopenharmony_ci        LLVMBuildStore(LLVMBuildAdd(2, 3). x);
394bf215546Sopenharmony_ci     lp_build_endif(ctx);
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci */
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci/**
401bf215546Sopenharmony_ci * Begin an if/else/endif construct.
402bf215546Sopenharmony_ci */
403bf215546Sopenharmony_civoid
404bf215546Sopenharmony_cilp_build_if(struct lp_build_if_state *ifthen,
405bf215546Sopenharmony_ci            struct gallivm_state *gallivm,
406bf215546Sopenharmony_ci            LLVMValueRef condition)
407bf215546Sopenharmony_ci{
408bf215546Sopenharmony_ci   LLVMBasicBlockRef block = LLVMGetInsertBlock(gallivm->builder);
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci   memset(ifthen, 0, sizeof *ifthen);
411bf215546Sopenharmony_ci   ifthen->gallivm = gallivm;
412bf215546Sopenharmony_ci   ifthen->condition = condition;
413bf215546Sopenharmony_ci   ifthen->entry_block = block;
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci   /* create endif/merge basic block for the phi functions */
416bf215546Sopenharmony_ci   ifthen->merge_block = lp_build_insert_new_block(gallivm, "endif-block");
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci   /* create/insert true_block before merge_block */
419bf215546Sopenharmony_ci   ifthen->true_block =
420bf215546Sopenharmony_ci      LLVMInsertBasicBlockInContext(gallivm->context,
421bf215546Sopenharmony_ci                                    ifthen->merge_block,
422bf215546Sopenharmony_ci                                    "if-true-block");
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci   /* successive code goes into the true block */
425bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(gallivm->builder, ifthen->true_block);
426bf215546Sopenharmony_ci}
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci/**
430bf215546Sopenharmony_ci * Begin else-part of a conditional
431bf215546Sopenharmony_ci */
432bf215546Sopenharmony_civoid
433bf215546Sopenharmony_cilp_build_else(struct lp_build_if_state *ifthen)
434bf215546Sopenharmony_ci{
435bf215546Sopenharmony_ci   LLVMBuilderRef builder = ifthen->gallivm->builder;
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci   /* Append an unconditional Br(anch) instruction on the true_block */
438bf215546Sopenharmony_ci   LLVMBuildBr(builder, ifthen->merge_block);
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   /* create/insert false_block before the merge block */
441bf215546Sopenharmony_ci   ifthen->false_block =
442bf215546Sopenharmony_ci      LLVMInsertBasicBlockInContext(ifthen->gallivm->context,
443bf215546Sopenharmony_ci                                    ifthen->merge_block,
444bf215546Sopenharmony_ci                                    "if-false-block");
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci   /* successive code goes into the else block */
447bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(builder, ifthen->false_block);
448bf215546Sopenharmony_ci}
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci/**
452bf215546Sopenharmony_ci * End a conditional.
453bf215546Sopenharmony_ci */
454bf215546Sopenharmony_civoid
455bf215546Sopenharmony_cilp_build_endif(struct lp_build_if_state *ifthen)
456bf215546Sopenharmony_ci{
457bf215546Sopenharmony_ci   LLVMBuilderRef builder = ifthen->gallivm->builder;
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   /* Insert branch to the merge block from current block */
460bf215546Sopenharmony_ci   LLVMBuildBr(builder, ifthen->merge_block);
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   /*
463bf215546Sopenharmony_ci    * Now patch in the various branch instructions.
464bf215546Sopenharmony_ci    */
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_ci   /* Insert the conditional branch instruction at the end of entry_block */
467bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(builder, ifthen->entry_block);
468bf215546Sopenharmony_ci   if (ifthen->false_block) {
469bf215546Sopenharmony_ci      /* we have an else clause */
470bf215546Sopenharmony_ci      LLVMBuildCondBr(builder, ifthen->condition,
471bf215546Sopenharmony_ci                      ifthen->true_block, ifthen->false_block);
472bf215546Sopenharmony_ci   }
473bf215546Sopenharmony_ci   else {
474bf215546Sopenharmony_ci      /* no else clause */
475bf215546Sopenharmony_ci      LLVMBuildCondBr(builder, ifthen->condition,
476bf215546Sopenharmony_ci                      ifthen->true_block, ifthen->merge_block);
477bf215546Sopenharmony_ci   }
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   /* Resume building code at end of the ifthen->merge_block */
480bf215546Sopenharmony_ci   LLVMPositionBuilderAtEnd(builder, ifthen->merge_block);
481bf215546Sopenharmony_ci}
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_cistatic LLVMBuilderRef
485bf215546Sopenharmony_cicreate_builder_at_entry(struct gallivm_state *gallivm)
486bf215546Sopenharmony_ci{
487bf215546Sopenharmony_ci   LLVMBuilderRef builder = gallivm->builder;
488bf215546Sopenharmony_ci   LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder);
489bf215546Sopenharmony_ci   LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
490bf215546Sopenharmony_ci   LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function);
491bf215546Sopenharmony_ci   LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block);
492bf215546Sopenharmony_ci   LLVMBuilderRef first_builder = LLVMCreateBuilderInContext(gallivm->context);
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci   if (first_instr) {
495bf215546Sopenharmony_ci      LLVMPositionBuilderBefore(first_builder, first_instr);
496bf215546Sopenharmony_ci   } else {
497bf215546Sopenharmony_ci      LLVMPositionBuilderAtEnd(first_builder, first_block);
498bf215546Sopenharmony_ci   }
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_ci   return first_builder;
501bf215546Sopenharmony_ci}
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci/**
505bf215546Sopenharmony_ci * Allocate a scalar (or vector) variable.
506bf215546Sopenharmony_ci *
507bf215546Sopenharmony_ci * Although not strictly part of control flow, control flow has deep impact in
508bf215546Sopenharmony_ci * how variables should be allocated.
509bf215546Sopenharmony_ci *
510bf215546Sopenharmony_ci * The mem2reg optimization pass is the recommended way to dealing with mutable
511bf215546Sopenharmony_ci * variables, and SSA. It looks for allocas and if it can handle them, it
512bf215546Sopenharmony_ci * promotes them, but only looks for alloca instructions in the entry block of
513bf215546Sopenharmony_ci * the function. Being in the entry block guarantees that the alloca is only
514bf215546Sopenharmony_ci * executed once, which makes analysis simpler.
515bf215546Sopenharmony_ci *
516bf215546Sopenharmony_ci * See also:
517bf215546Sopenharmony_ci * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory
518bf215546Sopenharmony_ci */
519bf215546Sopenharmony_ciLLVMValueRef
520bf215546Sopenharmony_cilp_build_alloca(struct gallivm_state *gallivm,
521bf215546Sopenharmony_ci                LLVMTypeRef type,
522bf215546Sopenharmony_ci                const char *name)
523bf215546Sopenharmony_ci{
524bf215546Sopenharmony_ci   LLVMBuilderRef builder = gallivm->builder;
525bf215546Sopenharmony_ci   LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
526bf215546Sopenharmony_ci   LLVMValueRef res;
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci   res = LLVMBuildAlloca(first_builder, type, name);
529bf215546Sopenharmony_ci   LLVMBuildStore(builder, LLVMConstNull(type), res);
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci   LLVMDisposeBuilder(first_builder);
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci   return res;
534bf215546Sopenharmony_ci}
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_ci/**
538bf215546Sopenharmony_ci * Like lp_build_alloca, but do not zero-initialize the variable.
539bf215546Sopenharmony_ci */
540bf215546Sopenharmony_ciLLVMValueRef
541bf215546Sopenharmony_cilp_build_alloca_undef(struct gallivm_state *gallivm,
542bf215546Sopenharmony_ci                      LLVMTypeRef type,
543bf215546Sopenharmony_ci                      const char *name)
544bf215546Sopenharmony_ci{
545bf215546Sopenharmony_ci   LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
546bf215546Sopenharmony_ci   LLVMValueRef res;
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci   res = LLVMBuildAlloca(first_builder, type, name);
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci   LLVMDisposeBuilder(first_builder);
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci   return res;
553bf215546Sopenharmony_ci}
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci/**
557bf215546Sopenharmony_ci * Allocate an array of scalars/vectors.
558bf215546Sopenharmony_ci *
559bf215546Sopenharmony_ci * mem2reg pass is not capable of promoting structs or arrays to registers, but
560bf215546Sopenharmony_ci * we still put it in the first block anyway as failure to put allocas in the
561bf215546Sopenharmony_ci * first block may prevent the X86 backend from successfully align the stack as
562bf215546Sopenharmony_ci * required.
563bf215546Sopenharmony_ci *
564bf215546Sopenharmony_ci * Also the scalarrepl pass is supposedly more powerful and can promote
565bf215546Sopenharmony_ci * arrays in many cases.
566bf215546Sopenharmony_ci *
567bf215546Sopenharmony_ci * See also:
568bf215546Sopenharmony_ci * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory
569bf215546Sopenharmony_ci */
570bf215546Sopenharmony_ciLLVMValueRef
571bf215546Sopenharmony_cilp_build_array_alloca(struct gallivm_state *gallivm,
572bf215546Sopenharmony_ci                      LLVMTypeRef type,
573bf215546Sopenharmony_ci                      LLVMValueRef count,
574bf215546Sopenharmony_ci                      const char *name)
575bf215546Sopenharmony_ci{
576bf215546Sopenharmony_ci   LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
577bf215546Sopenharmony_ci   LLVMValueRef res;
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   res = LLVMBuildArrayAlloca(first_builder, type, count, name);
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci   LLVMDisposeBuilder(first_builder);
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci   return res;
584bf215546Sopenharmony_ci}
585