Hi Richard,

On Thu, 2025-08-07 at 13:56 +0200, Richard Biener wrote:
> The following handles value-numbering of a BIT_FIELD_REF of
> a register that's defined by a load by looking up a subset
> load similar to how we handle bit-and masked loads.  This
> allows the testcase to be simplified by two FRE passes,
> the first one will create the BIT_FIELD_REF.
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
> 
>       PR tree-optimization/121405
>       * tree-ssa-sccvn.cc (visit_nary_op): Handle BIT_FIELD_REF
>       with reference def by looking up a combination of both.
> 
>       * gcc.dg/tree-ssa/ssa-fre-107.c: New testcase.
>       * gcc.target/i386/pr90579.c: Adjust.

Looks like that broke building of libgo:
https://builder.sourceware.org/buildbot/#/builders/312/builds/1759

during GIMPLE pass: fre
../../../../gcc/libgo/go/crypto/elliptic/elliptic.go: In function 
‘crypto/elliptic.CurveParams.ScalarMult’:
../../../../gcc/libgo/go/crypto/elliptic/elliptic.go:295:1: internal compiler 
error: in nonoverlapping_refs_since_match_p, at tree-ssa-alias.cc:1684
  295 | func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) 
(*big.Int, *big.Int) {
      | ^
0x3034bfb internal_error(char const*, ...)
        ../../gcc/gcc/diagnostic-global-context.cc:534
0x101ab65 fancy_abort(char const*, int, char const*)
        ../../gcc/gcc/diagnostics/context.cc:1640
0x9ba3bc nonoverlapping_refs_since_match_p
        ../../gcc/gcc/tree-ssa-alias.cc:1684
0x195d17c decl_refs_may_alias_p
        ../../gcc/gcc/tree-ssa-alias.cc:2073
0x195d17c refs_may_alias_p_2
        ../../gcc/gcc/tree-ssa-alias.cc:2467
0x195d17c refs_may_alias_p_1(ao_ref*, ao_ref*, bool)
        ../../gcc/gcc/tree-ssa-alias.cc:2576
0x19600e3 stmt_may_clobber_ref_p_1(gimple*, ao_ref*, bool)
        ../../gcc/gcc/tree-ssa-alias.cc:3299
0x1960673 walk_non_aliased_vuses(ao_ref*, tree_node*, bool, void* (*)(ao_ref*, 
tree_node*, void*), void* (*)(ao_ref*, tree_node*, void*, translate_flags*), 
tree_node* (*)(tree_node*), unsigned int&, void*)
        ../../gcc/gcc/tree-ssa-alias.cc:3966
0x1a798a2 vn_reference_lookup(tree_node*, tree_node*, vn_lookup_kind, 
vn_reference_s**, bool, tree_node**, tree_node*, bool)
        ../../gcc/gcc/tree-ssa-sccvn.cc:4198
0x1a7d07e visit_nary_op
        ../../gcc/gcc/tree-ssa-sccvn.cc:5649
0x1a7e820 process_bb
        ../../gcc/gcc/tree-ssa-sccvn.cc:8331
0x1a80e64 do_rpo_vn_1
        ../../gcc/gcc/tree-ssa-sccvn.cc:8917
0x1a81e5b execute
        ../../gcc/gcc/tree-ssa-sccvn.cc:9078
Please submit a full bug report, with preprocessed source (by using 
-freport-bug).
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.

> ---
>  gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c | 29 +++++++++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr90579.c     |  7 ++---
>  gcc/tree-ssa-sccvn.cc                       | 22 ++++++++++++++++
>  3 files changed, 53 insertions(+), 5 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c
> 
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c
> new file mode 100644
> index 00000000000..f80baf3ca8d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c
> @@ -0,0 +1,29 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O -fdump-tree-optimized" } */
> +
> +struct vec_char_16
> +{
> +  unsigned char raw[2];
> +};
> +
> +static inline struct vec_char_16
> +Dup128VecFromValues(unsigned char t0, unsigned char t1)
> +{
> +  struct vec_char_16 result;
> +  result.raw[0] = t0;
> +  result.raw[1] = t1;
> +  return result;
> +}
> +
> +int f(unsigned char t0, unsigned char t1)
> +{
> +  struct vec_char_16 a = Dup128VecFromValues(t0, t1);
> +  struct vec_char_16 b;
> +  __builtin_memcpy(&b, &a, sizeof(a));
> +  return b.raw[0] + b.raw[1];
> +}
> +
> +/* Ideally we'd optimize this at FRE1 time but we only replace
> +   the loads from b.raw[] with BIT_FIELD_REFs which get optimized
> +   only later in the next FRE.  */
> +/* { dg-final { scan-tree-dump-not "MEM" "optimized" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr90579.c 
> b/gcc/testsuite/gcc.target/i386/pr90579.c
> index ab48a44063c..bd2fd3378e1 100644
> --- a/gcc/testsuite/gcc.target/i386/pr90579.c
> +++ b/gcc/testsuite/gcc.target/i386/pr90579.c
> @@ -16,8 +16,5 @@ loop (int k, double x)
>    return t;
>  }
>  
> -/* Verify we end up with scalar loads from r for the final sum.  */
> -/* { dg-final { scan-assembler "vaddsd\tr\\\+40" } } */
> -/* { dg-final { scan-assembler "vaddsd\tr\\\+32" } } */
> -/* { dg-final { scan-assembler "vaddsd\tr\\\+24" } } */
> -/* { dg-final { scan-assembler "vaddsd\tr\\\+16" } } */
> +/* Verify we end up with no loads from r.  */
> +/* { dg-final { scan-assembler-not "v\[ma\]\[^\t \]+\tr" } } */
> diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
> index 00315d154e4..1c113f848eb 100644
> --- a/gcc/tree-ssa-sccvn.cc
> +++ b/gcc/tree-ssa-sccvn.cc
> @@ -5633,6 +5633,28 @@ visit_nary_op (tree lhs, gassign *stmt)
>           }
>       }
>        break;
> +    case BIT_FIELD_REF:
> +      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME)
> +     {
> +       tree op0 = TREE_OPERAND (rhs1, 0);
> +       gassign *ass = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op0));
> +       if (ass
> +           && !gimple_has_volatile_ops (ass)
> +           && vn_get_stmt_kind (ass) == VN_REFERENCE)
> +         {
> +           tree last_vuse = gimple_vuse (ass);
> +           tree op = build3 (BIT_FIELD_REF, TREE_TYPE (rhs1),
> +                             gimple_assign_rhs1 (ass),
> +                             TREE_OPERAND (rhs1, 1), TREE_OPERAND (rhs1, 2));
> +           tree result = vn_reference_lookup (op, gimple_vuse (ass),
> +                                              default_vn_walk_kind,
> +                                              NULL, true, &last_vuse);
> +           if (result
> +               && useless_type_conversion_p (type, TREE_TYPE (result)))
> +             return set_ssa_val_to (lhs, result);
> +         }
> +     }
> +      break;
>      case TRUNC_DIV_EXPR:
>        if (TYPE_UNSIGNED (type))
>       break;

Reply via email to