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