[Mesa-dev] [PATCH] gallivm: fix return opcode handling in main function of a shader

Jose Fonseca jfonseca at vmware.com
Mon Mar 18 08:53:10 PDT 2013


Looks good to me.  Please add all necessary test cases to cover all these code paths.

Good stuff guys. Very subtle code indeed.

Jose

----- Original Message -----
> From: Roland Scheidegger <sroland at vmware.com>
> 
> If we're in some conditional or loop we must not return, or the code
> after the condition is never executed.
> (v2): And, we also can't just continue as nothing happened, since the
> mask update code would later check if we actually have a mask, so we
> need to remember that there was a return in main where we didn't exit
> (to illustrate this, a ret in a if clause would cause a mask update
> which is still ok as we're in a conditional, but after the endif the
> mask update code would drop the mask hence bringing execution back to
> pixels which should have their execution mask set to zero by the ret).
> Thanks to Christoph Bumiller for figuring this out.
> 
> This fixes https://bugs.freedesktop.org/show_bug.cgi?id=62357.
> 
> Note: This is a candidate for the stable branches.
> ---
>  src/gallium/auxiliary/gallivm/lp_bld_tgsi.h     |    1 +
>  src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c |   20 +++++++++++++++++---
>  2 files changed, 18 insertions(+), 3 deletions(-)
> 
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> index dac97c3..6e65e12 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> @@ -243,6 +243,7 @@ struct lp_exec_mask {
>     struct lp_build_context *bld;
>  
>     boolean has_mask;
> +   boolean ret_in_main;
>  
>     LLVMTypeRef int_vec_type;
>  
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> index 0dc26b5..965255a 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> @@ -73,6 +73,7 @@ static void lp_exec_mask_init(struct lp_exec_mask *mask,
> struct lp_build_context
>  
>     mask->bld = bld;
>     mask->has_mask = FALSE;
> +   mask->ret_in_main = FALSE;
>     mask->cond_stack_size = 0;
>     mask->loop_stack_size = 0;
>     mask->call_stack_size = 0;
> @@ -108,7 +109,7 @@ static void lp_exec_mask_update(struct lp_exec_mask
> *mask)
>     } else
>        mask->exec_mask = mask->cond_mask;
>  
> -   if (mask->call_stack_size) {
> +   if (mask->call_stack_size || mask->ret_in_main) {
>        mask->exec_mask = LLVMBuildAnd(builder,
>                                       mask->exec_mask,
>                                       mask->ret_mask,
> @@ -117,7 +118,8 @@ static void lp_exec_mask_update(struct lp_exec_mask
> *mask)
>  
>     mask->has_mask = (mask->cond_stack_size > 0 ||
>                       mask->loop_stack_size > 0 ||
> -                     mask->call_stack_size > 0);
> +                     mask->call_stack_size > 0 ||
> +                     mask->ret_in_main);
>  }
>  
>  static void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
> @@ -348,11 +350,23 @@ static void lp_exec_mask_ret(struct lp_exec_mask *mask,
> int *pc)
>     LLVMBuilderRef builder = mask->bld->gallivm->builder;
>     LLVMValueRef exec_mask;
>  
> -   if (mask->call_stack_size == 0) {
> +   if (mask->cond_stack_size == 0 &&
> +       mask->loop_stack_size == 0 &&
> +       mask->call_stack_size == 0) {
>        /* returning from main() */
>        *pc = -1;
>        return;
>     }
> +
> +   if (mask->call_stack_size == 0) {
> +      /*
> +       * This requires special handling since we need to ensure
> +       * we don't drop the mask even if we have no call stack
> +       * (e.g. after a ret in a if clause after the endif)
> +       */
> +      mask->ret_in_main = TRUE;
> +   }
> +
>     exec_mask = LLVMBuildNot(builder,
>                              mask->exec_mask,
>                              "ret");
> --
> 1.7.9.5
>


More information about the mesa-dev mailing list