On Mon, Sep 22, 2025 at 9:57 AM <[email protected]> wrote:
>
> From: Pan Li <[email protected]>
>
> The previous refinement in build_and_insert_cast will convert 2
> cast into one, aka:
>
> uint16_t _3;
>
> From:
> int16_t _4 = (uint16_t)_3; // no-extend
> int32_t _5 = (int32_t)_4   // sign-extend 16 => 32
>
> To:
> int32_t _5 = (int32_t)_3;  // zero-extend 16 => 32
>
> That will have a problem for sign-extend, the highest bits may be all 1s
> but will be loss after convert to zero-extend.  Thus, there will be more
> cases if the convert has different types.  Case 1 as above and Case 2,
> 3, and 4 as following.
>
> Case 2:
>   int16_t _3;
>
>   From:
>   uint32_t _4 = (uint32_t)_3; // zero-extend 16 => 32
>   uint64_t _5 = (uint64_t)_4; // zero-extend 32 => 64
>
>   To:
>   uint64_t _5 = (uint32_t)_3; // zero-extend 16 => 64
>
> Case 3:
>   uint8_t _3;
>
>   From:
>   uint16_t _4 = (uint16_t)_3; // zero-extend 8 => 16
>   int32_t _5 = (int32_t)_4;   // zero-extend 16 => 32
>
>   To:
>   int32_t _5 = (int32_t)_3;   // zero-extend 8 => 32
>
> Case 4:
>   int8_t _3;
>
>   From:
>   int16_t _4 = (int16_t)_3;   // sign-extend 8 => 16
>   uint32_t _5 = (uint32_t)_4; // zero-extend 16 => 32
>   To:
>   uint32_t _5 = (uint32_t)_3; // zero-extend 8 => 32
>
> Then, we can see, there will be mis-compile if and only if there is
> a cast from small to big size with sign extend.  Thus, restrict the
> check and stop prop if there is sign extend cast.
>
> The below test suites are passed for this patch:
> 1. The rv64gcv fully regression tests.
> 2. The x86 bootstrap tests.
> 3. The x86 fully regression tests.

OK.

Thanks,
Richard.

>         PR middle-end/122021
>
> gcc/ChangeLog:
>
>         * tree-ssa-math-opts.cc (build_and_insert_cast): Add sign-extend
>         check before prop.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/i386/pr122021-0.c: New test.
>
> Signed-off-by: Pan Li <[email protected]>
> ---
>  gcc/testsuite/gcc.target/i386/pr122021-0.c | 22 ++++++++++++++++++++++
>  gcc/tree-ssa-math-opts.cc                  | 18 +++++++++++++++---
>  2 files changed, 37 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr122021-0.c
>
> diff --git a/gcc/testsuite/gcc.target/i386/pr122021-0.c 
> b/gcc/testsuite/gcc.target/i386/pr122021-0.c
> new file mode 100644
> index 00000000000..de17734523c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr122021-0.c
> @@ -0,0 +1,22 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -m32" } */
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +
> +__attribute__ ((noipa)) static void
> +vp9_build_inter_predictor (int a)
> +{
> +  int16_t row = a * 2;
> +  int32_t row_w = (int)((int64_t)row * 16384 >> 14);
> +
> +  if (row_w != -544)
> +    __builtin_abort ();
> +}
> +
> +int
> +main ()
> +{
> +  vp9_build_inter_predictor (-272);
> +  return 0;
> +}
> diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
> index 344ffddd385..80d10d26f67 100644
> --- a/gcc/tree-ssa-math-opts.cc
> +++ b/gcc/tree-ssa-math-opts.cc
> @@ -1642,12 +1642,24 @@ build_and_insert_cast (gimple_stmt_iterator *gsi, 
> location_t loc,
>           && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)))
>         {
>           tree cast_rhs = gimple_assign_rhs1 (def);
> -         unsigned rhs_prec = TYPE_PRECISION (TREE_TYPE (cast_rhs));
> +         tree cast_rhs_type = TREE_TYPE (cast_rhs);
> +         tree val_type = TREE_TYPE (val);
> +
> +         bool unsigned_p = TYPE_UNSIGNED (type);
> +         bool unsigned_rhs_p = TYPE_UNSIGNED (cast_rhs_type);
> +         bool unsigned_val_p = TYPE_UNSIGNED (val_type);
> +
> +         unsigned rhs_prec = TYPE_PRECISION (cast_rhs_type);
>           unsigned type_prec = TYPE_PRECISION (type);
> -         unsigned val_prec = TYPE_PRECISION (TREE_TYPE (val));
> +         unsigned val_prec = TYPE_PRECISION (val_type);
>
>           if (type_prec >= rhs_prec && val_prec >= rhs_prec)
> -           rhs = cast_rhs;
> +           {
> +             /* Aka any sign extend from small to big size */
> +             if (!((val_prec > rhs_prec && !unsigned_val_p && 
> !unsigned_rhs_p)
> +                 || (type_prec > val_prec && !unsigned_p && 
> !unsigned_val_p)))
> +               rhs = rhs;
> +           }
>         }
>      }
>
> --
> 2.43.0
>

Reply via email to