mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-31 15:40:24 +01:00
gallivm: Cleanup the rest of the flow module.
This commit is contained in:
parent
d0ea464159
commit
307df6a858
3 changed files with 39 additions and 211 deletions
|
|
@ -38,146 +38,6 @@
|
|||
#include "lp_bld_flow.h"
|
||||
|
||||
|
||||
#define LP_BUILD_FLOW_MAX_VARIABLES 64
|
||||
#define LP_BUILD_FLOW_MAX_DEPTH 32
|
||||
|
||||
/**
|
||||
* Enumeration of all possible flow constructs.
|
||||
*/
|
||||
enum lp_build_flow_construct_kind {
|
||||
LP_BUILD_FLOW_SKIP,
|
||||
LP_BUILD_FLOW_IF
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Early exit. Useful to skip to the end of a function or block when
|
||||
* the execution mask becomes zero or when there is an error condition.
|
||||
*/
|
||||
struct lp_build_flow_skip
|
||||
{
|
||||
/** Block to skip to */
|
||||
LLVMBasicBlockRef block;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Union of all possible flow constructs' data
|
||||
*/
|
||||
union lp_build_flow_construct_data
|
||||
{
|
||||
struct lp_build_flow_skip skip;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Element of the flow construct stack.
|
||||
*/
|
||||
struct lp_build_flow_construct
|
||||
{
|
||||
enum lp_build_flow_construct_kind kind;
|
||||
union lp_build_flow_construct_data data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* All necessary data to generate LLVM control flow constructs.
|
||||
*
|
||||
* Besides keeping track of the control flow construct themselves we also
|
||||
* need to keep track of variables in order to generate SSA Phi values.
|
||||
*/
|
||||
struct lp_build_flow_context
|
||||
{
|
||||
LLVMBuilderRef builder;
|
||||
|
||||
/**
|
||||
* Control flow stack.
|
||||
*/
|
||||
struct lp_build_flow_construct constructs[LP_BUILD_FLOW_MAX_DEPTH];
|
||||
unsigned num_constructs;
|
||||
};
|
||||
|
||||
|
||||
struct lp_build_flow_context *
|
||||
lp_build_flow_create(LLVMBuilderRef builder)
|
||||
{
|
||||
struct lp_build_flow_context *flow;
|
||||
|
||||
flow = CALLOC_STRUCT(lp_build_flow_context);
|
||||
if(!flow)
|
||||
return NULL;
|
||||
|
||||
flow->builder = builder;
|
||||
|
||||
return flow;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_flow_destroy(struct lp_build_flow_context *flow)
|
||||
{
|
||||
assert(flow->num_constructs == 0);
|
||||
FREE(flow);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begin/push a new flow control construct, such as a loop, skip block
|
||||
* or variable scope.
|
||||
*/
|
||||
static union lp_build_flow_construct_data *
|
||||
lp_build_flow_push(struct lp_build_flow_context *flow,
|
||||
enum lp_build_flow_construct_kind kind)
|
||||
{
|
||||
assert(flow->num_constructs < LP_BUILD_FLOW_MAX_DEPTH);
|
||||
if(flow->num_constructs >= LP_BUILD_FLOW_MAX_DEPTH)
|
||||
return NULL;
|
||||
|
||||
flow->constructs[flow->num_constructs].kind = kind;
|
||||
return &flow->constructs[flow->num_constructs++].data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the current/top flow control construct on the stack.
|
||||
* \param kind the expected type of the top-most construct
|
||||
*/
|
||||
static union lp_build_flow_construct_data *
|
||||
lp_build_flow_peek(struct lp_build_flow_context *flow,
|
||||
enum lp_build_flow_construct_kind kind)
|
||||
{
|
||||
assert(flow->num_constructs);
|
||||
if(!flow->num_constructs)
|
||||
return NULL;
|
||||
|
||||
assert(flow->constructs[flow->num_constructs - 1].kind == kind);
|
||||
if(flow->constructs[flow->num_constructs - 1].kind != kind)
|
||||
return NULL;
|
||||
|
||||
return &flow->constructs[flow->num_constructs - 1].data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* End/pop the current/top flow control construct on the stack.
|
||||
* \param kind the expected type of the top-most construct
|
||||
*/
|
||||
static union lp_build_flow_construct_data *
|
||||
lp_build_flow_pop(struct lp_build_flow_context *flow,
|
||||
enum lp_build_flow_construct_kind kind)
|
||||
{
|
||||
assert(flow->num_constructs);
|
||||
if(!flow->num_constructs)
|
||||
return NULL;
|
||||
|
||||
assert(flow->constructs[flow->num_constructs - 1].kind == kind);
|
||||
if(flow->constructs[flow->num_constructs - 1].kind != kind)
|
||||
return NULL;
|
||||
|
||||
return &flow->constructs[--flow->num_constructs].data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Note: this function has no dependencies on the flow code and could
|
||||
* be used elsewhere.
|
||||
|
|
@ -208,34 +68,18 @@ lp_build_insert_new_block(LLVMBuilderRef builder, const char *name)
|
|||
}
|
||||
|
||||
|
||||
static LLVMBasicBlockRef
|
||||
lp_build_flow_insert_block(struct lp_build_flow_context *flow)
|
||||
{
|
||||
return lp_build_insert_new_block(flow->builder, "");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begin a "skip" block. Inside this block we can test a condition and
|
||||
* skip to the end of the block if the condition is false.
|
||||
*/
|
||||
void
|
||||
lp_build_flow_skip_begin(struct lp_build_flow_context *flow)
|
||||
lp_build_flow_skip_begin(struct lp_build_skip_context *skip,
|
||||
LLVMBuilderRef builder)
|
||||
{
|
||||
struct lp_build_flow_skip *skip;
|
||||
LLVMBuilderRef builder;
|
||||
|
||||
skip = &lp_build_flow_push(flow, LP_BUILD_FLOW_SKIP)->skip;
|
||||
if(!skip)
|
||||
return;
|
||||
skip->builder = builder;
|
||||
|
||||
/* create new basic block */
|
||||
skip->block = lp_build_flow_insert_block(flow);
|
||||
|
||||
builder = LLVMCreateBuilder();
|
||||
LLVMPositionBuilderAtEnd(builder, skip->block);
|
||||
|
||||
LLVMDisposeBuilder(builder);
|
||||
skip->block = lp_build_insert_new_block(skip->builder, "skip");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -244,37 +88,26 @@ lp_build_flow_skip_begin(struct lp_build_flow_context *flow)
|
|||
* skip block if the condition is true.
|
||||
*/
|
||||
void
|
||||
lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow,
|
||||
lp_build_flow_skip_cond_break(struct lp_build_skip_context *skip,
|
||||
LLVMValueRef cond)
|
||||
{
|
||||
struct lp_build_flow_skip *skip;
|
||||
LLVMBasicBlockRef new_block;
|
||||
|
||||
skip = &lp_build_flow_peek(flow, LP_BUILD_FLOW_SKIP)->skip;
|
||||
if(!skip)
|
||||
return;
|
||||
|
||||
new_block = lp_build_flow_insert_block(flow);
|
||||
new_block = lp_build_insert_new_block(skip->builder, "");
|
||||
|
||||
/* if cond is true, goto skip->block, else goto new_block */
|
||||
LLVMBuildCondBr(flow->builder, cond, skip->block, new_block);
|
||||
LLVMBuildCondBr(skip->builder, cond, skip->block, new_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(flow->builder, new_block);
|
||||
LLVMPositionBuilderAtEnd(skip->builder, new_block);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_flow_skip_end(struct lp_build_flow_context *flow)
|
||||
lp_build_flow_skip_end(struct lp_build_skip_context *skip)
|
||||
{
|
||||
struct lp_build_flow_skip *skip;
|
||||
|
||||
skip = &lp_build_flow_pop(flow, LP_BUILD_FLOW_SKIP)->skip;
|
||||
if(!skip)
|
||||
return;
|
||||
|
||||
/* goto block */
|
||||
LLVMBuildBr(flow->builder, skip->block);
|
||||
LLVMPositionBuilderAtEnd(flow->builder, skip->block);
|
||||
LLVMBuildBr(skip->builder, skip->block);
|
||||
LLVMPositionBuilderAtEnd(skip->builder, skip->block);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -284,7 +117,7 @@ lp_build_flow_skip_end(struct lp_build_flow_context *flow)
|
|||
void
|
||||
lp_build_mask_check(struct lp_build_mask_context *mask)
|
||||
{
|
||||
LLVMBuilderRef builder = mask->flow->builder;
|
||||
LLVMBuilderRef builder = mask->skip.builder;
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef cond;
|
||||
|
||||
|
|
@ -298,7 +131,7 @@ lp_build_mask_check(struct lp_build_mask_context *mask)
|
|||
"");
|
||||
|
||||
/* if cond, goto end of block */
|
||||
lp_build_flow_skip_cond_break(mask->flow, cond);
|
||||
lp_build_flow_skip_cond_break(&mask->skip, cond);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -311,28 +144,27 @@ lp_build_mask_check(struct lp_build_mask_context *mask)
|
|||
*/
|
||||
void
|
||||
lp_build_mask_begin(struct lp_build_mask_context *mask,
|
||||
struct lp_build_flow_context *flow,
|
||||
LLVMBuilderRef builder,
|
||||
struct lp_type type,
|
||||
LLVMValueRef value)
|
||||
{
|
||||
memset(mask, 0, sizeof *mask);
|
||||
|
||||
mask->flow = flow;
|
||||
mask->reg_type = LLVMIntType(type.width * type.length);
|
||||
mask->var = lp_build_alloca(flow->builder,
|
||||
mask->var = lp_build_alloca(builder,
|
||||
lp_build_int_vec_type(type),
|
||||
"execution_mask");
|
||||
|
||||
LLVMBuildStore(flow->builder, value, mask->var);
|
||||
LLVMBuildStore(builder, value, mask->var);
|
||||
|
||||
lp_build_flow_skip_begin(flow);
|
||||
lp_build_flow_skip_begin(&mask->skip, builder);
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_mask_value(struct lp_build_mask_context *mask)
|
||||
{
|
||||
return LLVMBuildLoad(mask->flow->builder, mask->var, "");
|
||||
return LLVMBuildLoad(mask->skip.builder, mask->var, "");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -345,10 +177,10 @@ void
|
|||
lp_build_mask_update(struct lp_build_mask_context *mask,
|
||||
LLVMValueRef value)
|
||||
{
|
||||
value = LLVMBuildAnd(mask->flow->builder,
|
||||
value = LLVMBuildAnd(mask->skip.builder,
|
||||
lp_build_mask_value(mask),
|
||||
value, "");
|
||||
LLVMBuildStore(mask->flow->builder, value, mask->var);
|
||||
LLVMBuildStore(mask->skip.builder, value, mask->var);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -358,7 +190,7 @@ lp_build_mask_update(struct lp_build_mask_context *mask,
|
|||
LLVMValueRef
|
||||
lp_build_mask_end(struct lp_build_mask_context *mask)
|
||||
{
|
||||
lp_build_flow_skip_end(mask->flow);
|
||||
lp_build_flow_skip_end(&mask->skip);
|
||||
return lp_build_mask_value(mask);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,29 +41,33 @@
|
|||
struct lp_type;
|
||||
|
||||
|
||||
struct lp_build_flow_context;
|
||||
/**
|
||||
* Early exit. Useful to skip to the end of a function or block when
|
||||
* the execution mask becomes zero or when there is an error condition.
|
||||
*/
|
||||
struct lp_build_skip_context
|
||||
{
|
||||
LLVMBuilderRef builder;
|
||||
|
||||
|
||||
struct lp_build_flow_context *
|
||||
lp_build_flow_create(LLVMBuilderRef builder);
|
||||
/** Block to skip to */
|
||||
LLVMBasicBlockRef block;
|
||||
};
|
||||
|
||||
void
|
||||
lp_build_flow_destroy(struct lp_build_flow_context *flow);
|
||||
lp_build_flow_skip_begin(struct lp_build_skip_context *ctx,
|
||||
LLVMBuilderRef builder);
|
||||
|
||||
void
|
||||
lp_build_flow_skip_begin(struct lp_build_flow_context *flow);
|
||||
|
||||
void
|
||||
lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow,
|
||||
lp_build_flow_skip_cond_break(struct lp_build_skip_context *ctx,
|
||||
LLVMValueRef cond);
|
||||
|
||||
void
|
||||
lp_build_flow_skip_end(struct lp_build_flow_context *flow);
|
||||
lp_build_flow_skip_end(struct lp_build_skip_context *ctx);
|
||||
|
||||
|
||||
struct lp_build_mask_context
|
||||
{
|
||||
struct lp_build_flow_context *flow;
|
||||
struct lp_build_skip_context skip;
|
||||
|
||||
LLVMTypeRef reg_type;
|
||||
|
||||
|
|
@ -73,7 +77,7 @@ struct lp_build_mask_context
|
|||
|
||||
void
|
||||
lp_build_mask_begin(struct lp_build_mask_context *mask,
|
||||
struct lp_build_flow_context *flow,
|
||||
LLVMBuilderRef builder,
|
||||
struct lp_type type,
|
||||
LLVMValueRef value);
|
||||
|
||||
|
|
|
|||
|
|
@ -237,7 +237,6 @@ generate_fs(struct llvmpipe_context *lp,
|
|||
LLVMValueRef z;
|
||||
LLVMValueRef zs_value = NULL;
|
||||
LLVMValueRef stencil_refs[2];
|
||||
struct lp_build_flow_context *flow;
|
||||
struct lp_build_mask_context mask;
|
||||
boolean simple_shader = (shader->info.file_count[TGSI_FILE_SAMPLER] == 0 &&
|
||||
shader->info.num_inputs < 3 &&
|
||||
|
|
@ -286,8 +285,6 @@ generate_fs(struct llvmpipe_context *lp,
|
|||
|
||||
consts_ptr = lp_jit_context_constants(builder, context_ptr);
|
||||
|
||||
flow = lp_build_flow_create(builder);
|
||||
|
||||
memset(outputs, 0, sizeof outputs);
|
||||
|
||||
/* Declare the color and z variables */
|
||||
|
|
@ -307,7 +304,7 @@ generate_fs(struct llvmpipe_context *lp,
|
|||
}
|
||||
|
||||
/* 'mask' will control execution based on quad's pixel alive/killed state */
|
||||
lp_build_mask_begin(&mask, flow, type, *pmask);
|
||||
lp_build_mask_begin(&mask, builder, type, *pmask);
|
||||
|
||||
if (!(depth_mode & EARLY_DEPTH_TEST) && !simple_shader)
|
||||
lp_build_mask_check(&mask);
|
||||
|
|
@ -424,8 +421,6 @@ generate_fs(struct llvmpipe_context *lp,
|
|||
lp_build_mask_value(&mask), counter);
|
||||
|
||||
*pmask = lp_build_mask_end(&mask);
|
||||
|
||||
lp_build_flow_destroy(flow);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -450,7 +445,6 @@ generate_blend(const struct pipe_blend_state *blend,
|
|||
boolean do_branch)
|
||||
{
|
||||
struct lp_build_context bld;
|
||||
struct lp_build_flow_context *flow;
|
||||
struct lp_build_mask_context mask_ctx;
|
||||
LLVMTypeRef vec_type;
|
||||
LLVMValueRef const_ptr;
|
||||
|
|
@ -461,8 +455,7 @@ generate_blend(const struct pipe_blend_state *blend,
|
|||
|
||||
lp_build_context_init(&bld, builder, type);
|
||||
|
||||
flow = lp_build_flow_create(builder);
|
||||
lp_build_mask_begin(&mask_ctx, flow, type, mask);
|
||||
lp_build_mask_begin(&mask_ctx, builder, type, mask);
|
||||
if (do_branch)
|
||||
lp_build_mask_check(&mask_ctx);
|
||||
|
||||
|
|
@ -497,7 +490,6 @@ generate_blend(const struct pipe_blend_state *blend,
|
|||
}
|
||||
|
||||
lp_build_mask_end(&mask_ctx);
|
||||
lp_build_flow_destroy(flow);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue