gallivm: Fix BREAK/CONT translation.
The cont_mask must be restored and exec mask recomputed in order to decide whether to repeat the loop or not. Unlike the continue mask, the break_mask must be preserved across loop iterations. Fixes several VShader DCT cases, and no regressions with glean.
This commit is contained in:
parent
852f735236
commit
2d91903882
|
@ -93,18 +93,17 @@ struct lp_exec_mask {
|
||||||
int cond_stack_size;
|
int cond_stack_size;
|
||||||
LLVMValueRef cond_mask;
|
LLVMValueRef cond_mask;
|
||||||
|
|
||||||
LLVMValueRef break_stack[LP_MAX_TGSI_NESTING];
|
|
||||||
int break_stack_size;
|
|
||||||
LLVMValueRef break_mask;
|
|
||||||
|
|
||||||
LLVMValueRef cont_stack[LP_MAX_TGSI_NESTING];
|
|
||||||
int cont_stack_size;
|
|
||||||
LLVMValueRef cont_mask;
|
|
||||||
|
|
||||||
LLVMBasicBlockRef loop_stack[LP_MAX_TGSI_NESTING];
|
|
||||||
int loop_stack_size;
|
|
||||||
LLVMBasicBlockRef loop_block;
|
LLVMBasicBlockRef loop_block;
|
||||||
|
LLVMValueRef cont_mask;
|
||||||
|
LLVMValueRef break_mask;
|
||||||
|
LLVMValueRef break_var;
|
||||||
|
struct {
|
||||||
|
LLVMBasicBlockRef loop_block;
|
||||||
|
LLVMValueRef cont_mask;
|
||||||
|
LLVMValueRef break_mask;
|
||||||
|
LLVMValueRef break_var;
|
||||||
|
} loop_stack[LP_MAX_TGSI_NESTING];
|
||||||
|
int loop_stack_size;
|
||||||
|
|
||||||
LLVMValueRef exec_mask;
|
LLVMValueRef exec_mask;
|
||||||
};
|
};
|
||||||
|
@ -167,10 +166,10 @@ static void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context
|
||||||
mask->has_mask = FALSE;
|
mask->has_mask = FALSE;
|
||||||
mask->cond_stack_size = 0;
|
mask->cond_stack_size = 0;
|
||||||
mask->loop_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);
|
mask->int_vec_type = lp_build_int_vec_type(mask->bld->type);
|
||||||
|
mask->break_mask = mask->cont_mask = mask->cond_mask =
|
||||||
|
LLVMConstAllOnes(mask->int_vec_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lp_exec_mask_update(struct lp_exec_mask *mask)
|
static void lp_exec_mask_update(struct lp_exec_mask *mask)
|
||||||
|
@ -199,25 +198,29 @@ static void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
|
||||||
LLVMValueRef val)
|
LLVMValueRef val)
|
||||||
{
|
{
|
||||||
assert(mask->cond_stack_size < LP_MAX_TGSI_NESTING);
|
assert(mask->cond_stack_size < LP_MAX_TGSI_NESTING);
|
||||||
|
if (mask->cond_stack_size == 0) {
|
||||||
|
assert(mask->cond_mask == LLVMConstAllOnes(mask->int_vec_type));
|
||||||
|
}
|
||||||
mask->cond_stack[mask->cond_stack_size++] = mask->cond_mask;
|
mask->cond_stack[mask->cond_stack_size++] = mask->cond_mask;
|
||||||
mask->cond_mask = LLVMBuildBitCast(mask->bld->builder, val,
|
assert(LLVMTypeOf(val) == mask->int_vec_type);
|
||||||
mask->int_vec_type, "");
|
mask->cond_mask = val;
|
||||||
|
|
||||||
lp_exec_mask_update(mask);
|
lp_exec_mask_update(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lp_exec_mask_cond_invert(struct lp_exec_mask *mask)
|
static void lp_exec_mask_cond_invert(struct lp_exec_mask *mask)
|
||||||
{
|
{
|
||||||
LLVMValueRef prev_mask = mask->cond_stack[mask->cond_stack_size - 1];
|
LLVMValueRef prev_mask;
|
||||||
LLVMValueRef inv_mask = LLVMBuildNot(mask->bld->builder,
|
LLVMValueRef inv_mask;
|
||||||
mask->cond_mask, "");
|
|
||||||
|
|
||||||
/* means that we didn't have any mask before and that
|
assert(mask->cond_stack_size);
|
||||||
* we were fully enabled */
|
prev_mask = mask->cond_stack[mask->cond_stack_size - 1];
|
||||||
if (mask->cond_stack_size <= 1) {
|
if (mask->cond_stack_size == 1) {
|
||||||
prev_mask = LLVMConstAllOnes(mask->int_vec_type);
|
assert(prev_mask == LLVMConstAllOnes(mask->int_vec_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inv_mask = LLVMBuildNot(mask->bld->builder, mask->cond_mask, "");
|
||||||
|
|
||||||
mask->cond_mask = LLVMBuildAnd(mask->bld->builder,
|
mask->cond_mask = LLVMBuildAnd(mask->bld->builder,
|
||||||
inv_mask,
|
inv_mask,
|
||||||
prev_mask, "");
|
prev_mask, "");
|
||||||
|
@ -226,31 +229,37 @@ static void lp_exec_mask_cond_invert(struct lp_exec_mask *mask)
|
||||||
|
|
||||||
static void lp_exec_mask_cond_pop(struct lp_exec_mask *mask)
|
static void lp_exec_mask_cond_pop(struct lp_exec_mask *mask)
|
||||||
{
|
{
|
||||||
|
assert(mask->cond_stack_size);
|
||||||
mask->cond_mask = mask->cond_stack[--mask->cond_stack_size];
|
mask->cond_mask = mask->cond_stack[--mask->cond_stack_size];
|
||||||
lp_exec_mask_update(mask);
|
lp_exec_mask_update(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lp_exec_bgnloop(struct lp_exec_mask *mask)
|
static void lp_exec_bgnloop(struct lp_exec_mask *mask)
|
||||||
{
|
{
|
||||||
|
if (mask->loop_stack_size == 0) {
|
||||||
|
assert(mask->loop_block == NULL);
|
||||||
|
assert(mask->cont_mask == LLVMConstAllOnes(mask->int_vec_type));
|
||||||
|
assert(mask->break_mask == LLVMConstAllOnes(mask->int_vec_type));
|
||||||
|
assert(mask->break_var == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (mask->cont_stack_size == 0)
|
assert(mask->loop_stack_size < LP_MAX_TGSI_NESTING);
|
||||||
mask->cont_mask = LLVMConstAllOnes(mask->int_vec_type);
|
|
||||||
if (mask->break_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);
|
|
||||||
|
|
||||||
assert(mask->break_stack_size < LP_MAX_TGSI_NESTING);
|
mask->loop_stack[mask->loop_stack_size].loop_block = mask->loop_block;
|
||||||
assert(mask->cont_stack_size < LP_MAX_TGSI_NESTING);
|
mask->loop_stack[mask->loop_stack_size].cont_mask = mask->cont_mask;
|
||||||
assert(mask->break_stack_size < LP_MAX_TGSI_NESTING);
|
mask->loop_stack[mask->loop_stack_size].break_mask = mask->break_mask;
|
||||||
|
mask->loop_stack[mask->loop_stack_size].break_var = mask->break_var;
|
||||||
|
++mask->loop_stack_size;
|
||||||
|
|
||||||
|
mask->break_var = lp_build_alloca(mask->bld->builder, mask->int_vec_type, "");
|
||||||
|
LLVMBuildStore(mask->bld->builder, mask->break_mask, mask->break_var);
|
||||||
|
|
||||||
mask->break_stack[mask->break_stack_size++] = mask->break_mask;
|
|
||||||
mask->cont_stack[mask->cont_stack_size++] = mask->cont_mask;
|
|
||||||
mask->loop_stack[mask->loop_stack_size++] = mask->loop_block;
|
|
||||||
mask->loop_block = lp_build_insert_new_block(mask->bld->builder, "bgnloop");
|
mask->loop_block = lp_build_insert_new_block(mask->bld->builder, "bgnloop");
|
||||||
LLVMBuildBr(mask->bld->builder, mask->loop_block);
|
LLVMBuildBr(mask->bld->builder, mask->loop_block);
|
||||||
LLVMPositionBuilderAtEnd(mask->bld->builder, mask->loop_block);
|
LLVMPositionBuilderAtEnd(mask->bld->builder, mask->loop_block);
|
||||||
|
|
||||||
|
mask->break_mask = LLVMBuildLoad(mask->bld->builder, mask->break_var, "");
|
||||||
|
|
||||||
lp_exec_mask_update(mask);
|
lp_exec_mask_update(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,11 +299,24 @@ static void lp_exec_endloop(struct lp_exec_mask *mask)
|
||||||
|
|
||||||
assert(mask->break_mask);
|
assert(mask->break_mask);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore the cont_mask, but don't pop
|
||||||
|
*/
|
||||||
|
assert(mask->loop_stack_size);
|
||||||
|
mask->cont_mask = mask->loop_stack[mask->loop_stack_size - 1].cont_mask;
|
||||||
|
lp_exec_mask_update(mask);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unlike the continue mask, the break_mask must be preserved across loop
|
||||||
|
* iterations
|
||||||
|
*/
|
||||||
|
LLVMBuildStore(mask->bld->builder, mask->break_mask, mask->break_var);
|
||||||
|
|
||||||
/* i1cond = (mask == 0) */
|
/* i1cond = (mask == 0) */
|
||||||
i1cond = LLVMBuildICmp(
|
i1cond = LLVMBuildICmp(
|
||||||
mask->bld->builder,
|
mask->bld->builder,
|
||||||
LLVMIntNE,
|
LLVMIntNE,
|
||||||
LLVMBuildBitCast(mask->bld->builder, mask->break_mask, reg_type, ""),
|
LLVMBuildBitCast(mask->bld->builder, mask->exec_mask, reg_type, ""),
|
||||||
LLVMConstNull(reg_type), "");
|
LLVMConstNull(reg_type), "");
|
||||||
|
|
||||||
endloop = lp_build_insert_new_block(mask->bld->builder, "endloop");
|
endloop = lp_build_insert_new_block(mask->bld->builder, "endloop");
|
||||||
|
@ -304,15 +326,12 @@ static void lp_exec_endloop(struct lp_exec_mask *mask)
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(mask->bld->builder, endloop);
|
LLVMPositionBuilderAtEnd(mask->bld->builder, endloop);
|
||||||
|
|
||||||
mask->loop_block = mask->loop_stack[--mask->loop_stack_size];
|
assert(mask->loop_stack_size);
|
||||||
/* pop the cont mask */
|
--mask->loop_stack_size;
|
||||||
if (mask->cont_stack_size) {
|
mask->loop_block = mask->loop_stack[mask->loop_stack_size].loop_block;
|
||||||
mask->cont_mask = mask->cont_stack[--mask->cont_stack_size];
|
mask->cont_mask = mask->loop_stack[mask->loop_stack_size].cont_mask;
|
||||||
}
|
mask->break_mask = mask->loop_stack[mask->loop_stack_size].break_mask;
|
||||||
/* pop the break mask */
|
mask->break_var = mask->loop_stack[mask->loop_stack_size].break_var;
|
||||||
if (mask->break_stack_size) {
|
|
||||||
mask->break_mask = mask->break_stack[--mask->break_stack_size];
|
|
||||||
}
|
|
||||||
|
|
||||||
lp_exec_mask_update(mask);
|
lp_exec_mask_update(mask);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue