diff options
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_bld_flow.c')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_bld_flow.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_flow.c b/src/gallium/drivers/llvmpipe/lp_bld_flow.c index 5fc85a19b8..d94af0dea4 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_flow.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_flow.c @@ -31,9 +31,93 @@ * @author Jose Fonseca <jfonseca@vmware.com> */ +#include "util/u_debug.h" + +#include "lp_bld_type.h" #include "lp_bld_flow.h" +void +lp_build_mask_begin(struct lp_build_mask_context *mask, + LLVMBuilderRef builder, + union lp_type type, + LLVMValueRef value) +{ + memset(mask, 0, sizeof *mask); + + mask->builder = builder; + mask->reg_type = LLVMIntType(type.width * type.length); + mask->value = value; +} + + +void +lp_build_mask_update(struct lp_build_mask_context *mask, + LLVMValueRef value) +{ + + LLVMValueRef cond; + LLVMBasicBlockRef current_block; + LLVMBasicBlockRef next_block; + LLVMBasicBlockRef new_block; + + if(mask->value) + mask->value = LLVMBuildAnd(mask->builder, mask->value, value, ""); + else + mask->value = value; + + cond = LLVMBuildICmp(mask->builder, + LLVMIntEQ, + LLVMBuildBitCast(mask->builder, mask->value, mask->reg_type, ""), + LLVMConstNull(mask->reg_type), + ""); + + current_block = LLVMGetInsertBlock(mask->builder); + + if(!mask->skip_block) { + LLVMValueRef function = LLVMGetBasicBlockParent(current_block); + mask->skip_block = LLVMAppendBasicBlock(function, "skip"); + + mask->phi = LLVMBuildPhi(mask->builder, LLVMTypeOf(mask->value), ""); + } + + next_block = LLVMGetNextBasicBlock(current_block); + assert(next_block); + if(next_block) { + new_block = LLVMInsertBasicBlock(next_block, ""); + } + else { + LLVMValueRef function = LLVMGetBasicBlockParent(current_block); + new_block = LLVMAppendBasicBlock(function, ""); + } + + LLVMAddIncoming(mask->phi, &mask->value, ¤t_block, 1); + LLVMBuildCondBr(mask->builder, cond, mask->skip_block, new_block); + + LLVMPositionBuilderAtEnd(mask->builder, new_block); +} + + +LLVMValueRef +lp_build_mask_end(struct lp_build_mask_context *mask) +{ + if(mask->skip_block) { + LLVMBasicBlockRef current_block = LLVMGetInsertBlock(mask->builder); + + LLVMAddIncoming(mask->phi, &mask->value, ¤t_block, 1); + LLVMBuildBr(mask->builder, mask->skip_block); + + LLVMPositionBuilderAtEnd(mask->builder, mask->skip_block); + + mask->value = mask->phi; + mask->phi = NULL; + mask->skip_block = NULL; + } + + return mask->value; +} + + void lp_build_loop_begin(LLVMBuilderRef builder, |