On Friday, February 27, 2015 11:34:06 AM Matt Turner wrote:
> We can safely propagate the conditional mod to an instruction with a
> different type if the conditional mod does not involve comparing for
> equality with zero (or probably NaN, but ignore that for now).
> 
> This is because -0.0 and +0.0 are both test equal to zero, but their
> integer representations do not.
> 
> Cc: 10.5 <mesa-sta...@lists.freedesktop.org>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89317
> ---
>  .../drivers/dri/i965/brw_fs_cmod_propagation.cpp   |  8 +++
>  .../drivers/dri/i965/test_fs_cmod_propagation.cpp  | 67 
> ++++++++++++++++++++++
>  2 files changed, 75 insertions(+)
> 
> diff --git a/src/mesa/drivers/dri/i965/brw_fs_cmod_propagation.cpp 
> b/src/mesa/drivers/dri/i965/brw_fs_cmod_propagation.cpp
> index c6384ab..a92eef6 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs_cmod_propagation.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs_cmod_propagation.cpp
> @@ -80,6 +80,14 @@ opt_cmod_propagation_local(fs_visitor *v, bblock_t *block)
>                  scan_inst->dst.reg_offset != inst->src[0].reg_offset)
>                 break;
>  
> +            /* Testing equality with zero is different for ints and floats */
> +            if (scan_inst->dst.type != inst->dst.type &&
> +                (inst->conditional_mod == BRW_CONDITIONAL_Z ||
> +                 inst->conditional_mod == BRW_CONDITIONAL_NZ ||
> +                 inst->conditional_mod == BRW_CONDITIONAL_GE ||
> +                 inst->conditional_mod == BRW_CONDITIONAL_LE))
> +               break;
> +
>              /* If the instruction generating inst's source also wrote the
>               * flag, and inst is doing a simple .nz comparison, then inst
>               * is redundant - the appropriate value is already in the flag
> diff --git a/src/mesa/drivers/dri/i965/test_fs_cmod_propagation.cpp 
> b/src/mesa/drivers/dri/i965/test_fs_cmod_propagation.cpp
> index fbe4fd9..0287161 100644
> --- a/src/mesa/drivers/dri/i965/test_fs_cmod_propagation.cpp
> +++ b/src/mesa/drivers/dri/i965/test_fs_cmod_propagation.cpp
> @@ -415,3 +415,70 @@ TEST_F(cmod_propagation_test, movnz)
>     EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
>     EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
>  }
> +
> +TEST_F(cmod_propagation_test, different_types)
> +{
> +   fs_reg dest = v->vgrf(glsl_type::int_type);
> +   fs_reg src0 = v->vgrf(glsl_type::int_type);
> +   fs_reg src1 = v->vgrf(glsl_type::int_type);
> +   fs_reg zero(0.0f);
> +   v->emit(BRW_OPCODE_ADD, dest, src0, src1);
> +   v->emit(BRW_OPCODE_CMP, v->reg_null_f, retype(dest, BRW_REGISTER_TYPE_F),
> +                                          zero)
> +      ->conditional_mod = BRW_CONDITIONAL_G;
> +
> +   /* = Before =
> +    *
> +    * 0: add(8)        dest:D  src0:D  src1:D
> +    * 1: cmp.g.f0(8)   null:F  dest:F  0.0f
> +    *
> +    * = After =
> +    * 0: add.g.f0(8)   dest:D  src0:D  src1:D
> +    */

This is wrong - you're adding two integers and doing an integer compare
with 0, rather than a float comparison.

I verified that in C, (-0.0 > 0.0) == false.  I then modified your
Piglit test to be:

        if (uintBitsToFloat(a + b) > 0.0)
                frag_color = vec4(1.0, 0.0, 0.0, 1.0);
        else
                frag_color = vec4(0.0, 1.0, 0.0, 1.0);

(> instead of ==, swap red/green).

This fails with your code, because it ends up doing:
      0x80000000 > 0x0
   => 0x80000000 - 0x0 > 0x0.
   => 0x80000000 > 0
   => True

It passes if you eliminate the conditional_mod checks and just do:

   if (scan_inst->dst.type != inst->dst.type)
      break;

Assuming you make that change, and drop/fix this unit test, you can put
my R-b on it.  Good find :)

> +
> +   v->calculate_cfg();
> +   bblock_t *block0 = v->cfg->blocks[0];
> +
> +   EXPECT_EQ(0, block0->start_ip);
> +   EXPECT_EQ(1, block0->end_ip);
> +
> +   EXPECT_TRUE(cmod_propagation(v));
> +   EXPECT_EQ(0, block0->start_ip);
> +   EXPECT_EQ(0, block0->end_ip);
> +   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
> +   EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
> +}
> +
> +TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
> +{
> +   fs_reg dest = v->vgrf(glsl_type::int_type);
> +   fs_reg src0 = v->vgrf(glsl_type::int_type);
> +   fs_reg src1 = v->vgrf(glsl_type::int_type);
> +   fs_reg zero(0.0f);
> +   v->emit(BRW_OPCODE_ADD, dest, src0, src1);
> +   v->emit(BRW_OPCODE_CMP, v->reg_null_f, retype(dest, BRW_REGISTER_TYPE_F),
> +                                          zero)
> +      ->conditional_mod = BRW_CONDITIONAL_GE;
> +
> +   /* = Before =
> +    *
> +    * 0: add(8)        dest:D  src0:D  src1:D
> +    * 1: cmp.ge.f0(8)  null:F  dest:F  0.0f
> +    *
> +    * = After =
> +    * (no changes)
> +    */
> +
> +   v->calculate_cfg();
> +   bblock_t *block0 = v->cfg->blocks[0];
> +
> +   EXPECT_EQ(0, block0->start_ip);
> +   EXPECT_EQ(1, block0->end_ip);
> +
> +   EXPECT_FALSE(cmod_propagation(v));
> +   EXPECT_EQ(0, block0->start_ip);
> +   EXPECT_EQ(1, block0->end_ip);
> +   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
> +   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
> +   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
> +}
> 

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to