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