gallivm: implement loops

This commit is contained in:
Zack Rusin 2010-03-09 15:09:15 -05:00
parent 242893cce2
commit 18d406e8a8
3 changed files with 153 additions and 10 deletions

View File

@ -308,7 +308,7 @@ lp_build_flow_scope_end(struct lp_build_flow_context *flow)
* Note: this function has no dependencies on the flow code and could
* be used elsewhere.
*/
static LLVMBasicBlockRef
LLVMBasicBlockRef
lp_build_insert_new_block(LLVMBuilderRef builder, const char *name)
{
LLVMBasicBlockRef current_block;

View File

@ -145,7 +145,9 @@ lp_build_else(struct lp_build_if_state *ctx);
void
lp_build_endif(struct lp_build_if_state *ctx);
LLVMBasicBlockRef
lp_build_insert_new_block(LLVMBuilderRef builder, const char *name);
#endif /* !LP_BLD_FLOW_H */

View File

@ -95,6 +95,19 @@ struct lp_exec_mask {
int cond_stack_size;
LLVMValueRef cond_mask;
LLVMValueRef break_stack[LP_TGSI_MAX_NESTING];
int break_stack_size;
LLVMValueRef break_mask;
LLVMValueRef cont_stack[LP_TGSI_MAX_NESTING];
int cont_stack_size;
LLVMValueRef cont_mask;
LLVMBasicBlockRef loop_stack[LP_TGSI_MAX_NESTING];
int loop_stack_size;
LLVMBasicBlockRef loop_block;
LLVMValueRef exec_mask;
};
@ -145,14 +158,33 @@ static void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context
mask->bld = bld;
mask->has_mask = FALSE;
mask->cond_stack_size = 0;
mask->loop_stack_size = 0;
mask->break_stack_size = 0;
mask->cont_stack_size = 0;
mask->int_vec_type = lp_build_int_vec_type(mask->bld->type);
}
static void lp_exec_mask_update(struct lp_exec_mask *mask)
{
mask->exec_mask = mask->cond_mask;
mask->has_mask = (mask->cond_stack_size > 0);
if (mask->loop_stack_size) {
/*for loops we need to update the entire mask at
* runtime */
LLVMValueRef tmp;
tmp = LLVMBuildAnd(mask->bld->builder,
mask->cont_mask,
mask->break_mask,
"maskcb");
mask->exec_mask = LLVMBuildAnd(mask->bld->builder,
mask->cond_mask,
tmp,
"maskfull");
} else
mask->exec_mask = mask->cond_mask;
mask->has_mask = (mask->cond_stack_size > 0 ||
mask->loop_stack_size > 0);
}
static void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
@ -189,6 +221,102 @@ static void lp_exec_mask_cond_pop(struct lp_exec_mask *mask)
lp_exec_mask_update(mask);
}
static void lp_exec_bgnloop(struct lp_exec_mask *mask)
{
if (mask->cont_stack_size == 0)
mask->cont_mask = LLVMConstAllOnes(mask->int_vec_type);
if (mask->cont_stack_size == 0)
mask->break_mask = LLVMConstAllOnes(mask->int_vec_type);
if (mask->cond_stack_size == 0)
mask->cond_mask = LLVMConstAllOnes(mask->int_vec_type);
mask->loop_stack[mask->loop_stack_size++] = mask->loop_block;
mask->loop_block = lp_build_insert_new_block(mask->bld->builder, "bgnloop");
LLVMBuildBr(mask->bld->builder, mask->loop_block);
LLVMPositionBuilderAtEnd(mask->bld->builder, mask->loop_block);
lp_exec_mask_update(mask);
}
static void lp_exec_break(struct lp_exec_mask *mask)
{
LLVMValueRef exec_mask = LLVMBuildNot(mask->bld->builder,
mask->exec_mask,
"break");
mask->break_stack[mask->break_stack_size++] = mask->break_mask;
if (mask->break_stack_size > 1) {
mask->break_mask = LLVMBuildAnd(mask->bld->builder,
mask->break_mask,
exec_mask, "break_full");
} else
mask->break_mask = exec_mask;
lp_exec_mask_update(mask);
}
static void lp_exec_continue(struct lp_exec_mask *mask)
{
LLVMValueRef exec_mask = LLVMBuildNot(mask->bld->builder,
mask->exec_mask,
"");
mask->cont_stack[mask->cont_stack_size++] = mask->cont_mask;
if (mask->cont_stack_size > 1) {
mask->cont_mask = LLVMBuildAnd(mask->bld->builder,
mask->cont_mask,
exec_mask, "");
} else
mask->cont_mask = exec_mask;
lp_exec_mask_update(mask);
}
static void lp_exec_endloop(struct lp_exec_mask *mask)
{
LLVMBasicBlockRef endloop;
LLVMValueRef i1cond;
{ /* convert our soa vector into i1 */
int i;
LLVMValueRef packed = 0;
for (i = 0; i < mask->bld->type.length; ++i) {
LLVMValueRef component = LLVMBuildExtractElement(
mask->bld->builder,
mask->break_mask,
LLVMConstInt(LLVMInt32Type(), i, 0), "");
if (packed)
packed = LLVMBuildOr(mask->bld->builder,
packed, component, "");
else
packed = component;
}
i1cond = LLVMBuildICmp(mask->bld->builder, LLVMIntNE,
packed,
LLVMConstNull(LLVMTypeOf(packed)),
"");
}
endloop = lp_build_insert_new_block(mask->bld->builder, "endloop");
LLVMBuildCondBr(mask->bld->builder,
i1cond, endloop, mask->loop_block);
LLVMPositionBuilderAtEnd(mask->bld->builder, endloop);
mask->loop_block = mask->loop_stack[--mask->loop_stack_size];
/* pop the break mask */
if (mask->cont_stack_size) {
mask->cont_mask = mask->cont_stack[--mask->cont_stack_size];
}
if (mask->break_stack_size) {
mask->break_mask = mask->cont_stack[--mask->break_stack_size];
}
lp_exec_mask_update(mask);
}
static void lp_exec_mask_store(struct lp_exec_mask *mask,
LLVMValueRef val,
LLVMValueRef dst)
@ -1363,10 +1491,9 @@ emit_instruction(
case TGSI_OPCODE_TXP:
emit_tex( bld, inst, FALSE, TRUE, dst0 );
break;
case TGSI_OPCODE_BRK:
/* FIXME */
return 0;
lp_exec_break(&bld->exec_mask);
break;
case TGSI_OPCODE_IF:
@ -1380,6 +1507,10 @@ emit_instruction(
return 0;
break;
case TGSI_OPCODE_BGNLOOP:
lp_exec_bgnloop(&bld->exec_mask);
break;
case TGSI_OPCODE_REP:
/* deprecated */
assert(0);
@ -1400,6 +1531,10 @@ emit_instruction(
return 0;
break;
case TGSI_OPCODE_ENDLOOP:
lp_exec_endloop(&bld->exec_mask);
break;
case TGSI_OPCODE_ENDREP:
/* deprecated */
assert(0);
@ -1499,8 +1634,7 @@ emit_instruction(
break;
case TGSI_OPCODE_CONT:
/* FIXME */
return 0;
lp_exec_continue(&bld->exec_mask);
break;
case TGSI_OPCODE_EMIT:
@ -1603,7 +1737,14 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
assert( 0 );
}
}
if (0) {
LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
LLVMValueRef function = LLVMGetBasicBlockParent(block);
debug_printf("11111111111111111111111111111 \n");
tgsi_dump(tokens, 0);
LLVMDumpValue(function);
debug_printf("2222222222222222222222222222 \n");
}
tgsi_parse_free( &parse );
}