Hi Jakub,

Just a query regarding the test case below.

On Wed, 2026-02-18 at 22:32 +0100, Jakub Jelinek wrote:
> Hi!
> 
> The following testcase ICEs starting with the removal of
> NON_DEPENDENT_EXPR
> in GCC 14.  The problem is that while parsing templates if all the
> arguments
> of the overloaded builtins are non-dependent types,
> targetm.resolve_overloaded_builtin can be called on it.  And trying
> to
> fold_convert or fold_build2 subexpressions of such arguments can ICE,
> because they can contain various FE specific trees, or standard trees
> with NULL_TREE types, or e.g. type mismatches in binary tree operands
> etc.
> All that goes away later when the trees are instantiated and
> targetm.resolve_overloaded_builtin is called again, but if it ICEs
> while
> doing that, it won't reach that point.  And the reason to call that
> hook in that case if none of the arguments are type dependent is to
> figure
> out if the result type is also non-dependent.
> 
> Given the general desire to fold stuff in the FE during parsing as
> little
> as possible and fold it only during cp_fold later on and because from
> the
> target *-c.cc files it isn't easily possible to find out if it is
> processing_template_decl or not, the following patch just stops
> folding
> anything in the arguments, calls convert instead of fold_convert and
> just build2 instead of fold_build2 etc. when in C++ (and keeps doing
> what
> it did for C).
> 
> Bootstrapped/regtested on powerpc64le-linux, ok for trunk?
> 
> 2026-02-18  Jakub Jelinek  <[email protected]>
> 
>       PR target/124133
>       * config/rs6000/rs6000-c.cc (c_fold_convert): New function.
>       (c_fold_build2_loc): Likewise.
>       (fully_fold_convert): Use c_fold_convert instead of
> fold_convert.
>       (altivec_build_resolved_builtin): Likewise.  Use
> c_fold_build2_loc
>       instead of fold_build2.
>       (resolve_vec_mul, resolve_vec_adde_sube,
> resolve_vec_addec_subec):
>       Use c_fold_build2_loc instead of fold_build2_loc.
>       (resolve_vec_splats, resolve_vec_extract): Use
> c_fold_convert instead
>       of fold_convert.
>       (resolve_vec_insert): Use c_fold_build2_loc instead of
> fold_build2.
>       (altivec_resolve_overloaded_builtin): Use c_fold_convert
> instead
>       of fold_convert.
> 
>       * g++.target/powerpc/pr124133.C: New test.
> 
> --- gcc/config/rs6000/rs6000-c.cc.jj  2026-01-02
> 09:56:10.067338205 +0100
> +++ gcc/config/rs6000/rs6000-c.cc     2026-02-17
> 16:47:03.466183542 +0100
> @@ -835,14 +835,40 @@ rs6000_builtin_type_compatible (tree par
>    return lang_hooks.types_compatible_p (parmtype, argtype);
>  }
>  
> -/* In addition to calling fold_convert for EXPR of type TYPE, also
> +/* Return fold_convert (TYPE, EXPR) for C and convert (TYPE, EXPR)
> +   for C++.  The latter is needed because resolve_overloaded_builtin
> +   can be called when parsing templates too if they don't have type
> +   dependent operands, but the nested trees might not be usable in
> +   GENERIC folding.  */
> +
> +static tree
> +c_fold_convert (tree type, tree expr)
> +{
> +  return c_dialect_cxx () ? convert (type, expr) : fold_convert
> (type, expr);
> +}
> +
> +/* Similar wrapper for fold_build2_loc.  For C++ just call
> build2_loc.  */
> +
> +static tree
> +c_fold_build2_loc (location_t loc, enum tree_code code, tree type,
> tree arg0,
> +                tree arg1)
> +{
> +  if (!c_dialect_cxx ())
> +    return fold_build2_loc (loc, code, type, arg0, arg1);
> +  else if (loc != UNKNOWN_LOCATION)
> +    return build2_loc (loc, code, type, arg0, arg1);
> +  else
> +    return build2 (code, type, arg0, arg1);
> +}
> +
> +/* In addition to calling c_fold_convert for EXPR of type TYPE, also
>     call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be
>     hiding there (PR47197).  */
>  
>  static tree
>  fully_fold_convert (tree type, tree expr)
>  {
> -  tree result = fold_convert (type, expr);
> +  tree result = c_fold_convert (type, expr);
>    bool maybe_const = true;
>  
>    if (!c_dialect_cxx ())
> @@ -855,7 +881,7 @@ fully_fold_convert (tree type, tree expr
>     The overloaded builtin that matched the types and args is
> described
>     by DESC.  The N arguments are given in ARGS, respectively.
>  
> -   Actually the only thing it does is calling fold_convert on ARGS,
> with
> +   Actually the only thing it does is calling c_fold_convert on
> ARGS, with
>     a small exception for vec_{all,any}_{ge,le} predicates. */
>  
>  static tree
> @@ -891,8 +917,9 @@ altivec_build_resolved_builtin (tree *ar
>        std::swap (args[1], args[2]);
>        std::swap (arg_type[1], arg_type[2]);
>  
> -      args[0] = fold_build2 (BIT_XOR_EXPR, TREE_TYPE (args[0]),
> args[0],
> -                          build_int_cst (NULL_TREE, 2));
> +      args[0] = c_fold_build2_loc (UNKNOWN_LOCATION, BIT_XOR_EXPR,
> +                                TREE_TYPE (args[0]), args[0],
> +                                build_int_cst (NULL_TREE, 2));
>      }
>  
>    for (int j = 0; j < n; j++)
> @@ -923,7 +950,7 @@ altivec_build_resolved_builtin (tree *ar
>      default:
>        gcc_unreachable ();
>      }
> -  return fold_convert (ret_type, call);
> +  return c_fold_convert (ret_type, call);
>  }
>  
>  /* Enumeration of possible results from attempted overload
> resolution.
> @@ -964,8 +991,8 @@ resolve_vec_mul (resolution *res, tree *
>      case E_TImode:
>        /* For scalar types just use a multiply expression.  */
>        *res = resolved;
> -      return fold_build2_loc (loc, MULT_EXPR, types[0], args[0],
> -                           fold_convert (types[0], args[1]));
> +      return c_fold_build2_loc (loc, MULT_EXPR, types[0], args[0],
> +                             c_fold_convert (types[0], args[1]));
>      case E_SFmode:
>        {
>       /* For floats use the xvmulsp instruction directly.  */
> @@ -1108,8 +1135,8 @@ resolve_vec_adde_sube (resolution *res,
>                                                       params);
>       tree const1 = build_int_cstu (TREE_TYPE (types[0]), 1);
>       tree ones_vector = build_vector_from_val (types[0], const1);
> -     tree and_expr = fold_build2_loc (loc, BIT_AND_EXPR,
> types[0],
> -                                      args[2], ones_vector);
> +     tree and_expr = c_fold_build2_loc (loc, BIT_AND_EXPR,
> types[0],
> +                                        args[2], ones_vector);
>       params = make_tree_vector ();
>       vec_safe_push (params, call);
>       vec_safe_push (params, and_expr);
> @@ -1194,8 +1221,8 @@ resolve_vec_addec_subec (resolution *res
>                                                        params);
>       tree const1 = build_int_cstu (TREE_TYPE (types[0]), 1);
>       tree ones_vector = build_vector_from_val (types[0], const1);
> -     tree and_expr = fold_build2_loc (loc, BIT_AND_EXPR,
> types[0],
> -                                      args[2], ones_vector);
> +     tree and_expr = c_fold_build2_loc (loc, BIT_AND_EXPR,
> types[0],
> +                                        args[2], ones_vector);
>       params = make_tree_vector ();
>       vec_safe_push (params, call2);
>       vec_safe_push (params, and_expr);
> @@ -1303,7 +1330,7 @@ resolve_vec_splats (resolution *res, rs6
>        return error_mark_node;
>      }
>  
> -  arg = save_expr (fold_convert (TREE_TYPE (type), arg));
> +  arg = save_expr (c_fold_convert (TREE_TYPE (type), arg));
>    vec<constructor_elt, va_gc> *vec;
>    vec_alloc (vec, size);
>  
> @@ -1442,7 +1469,7 @@ resolve_vec_extract (resolution *res, ve
>         tree result = build_call_expr (call, 2, arg1, arg2);
>         /* Coerce the result to vector element type.  May be no-
> op.  */
>         arg1_inner_type = TREE_TYPE (arg1_type);
> -       result = fold_convert (arg1_inner_type, result);
> +       result = c_fold_convert (arg1_inner_type, result);
>         *res = resolved;
>         return result;
>       }
> @@ -1566,8 +1593,9 @@ resolve_vec_insert (resolution *res, vec
>    if (TARGET_VSX)
>      {
>        stmt = build_array_ref (loc, stmt, arg2);
> -      stmt = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg0), stmt,
> -                       convert (TREE_TYPE (stmt), arg0));
> +      stmt = c_fold_build2_loc (UNKNOWN_LOCATION, MODIFY_EXPR,
> +                             TREE_TYPE (arg0), stmt,
> +                             convert (TREE_TYPE (stmt), arg0));
>        stmt = build2 (COMPOUND_EXPR, arg1_type, stmt, decl);
>      }
>    else
> @@ -1791,7 +1819,7 @@ altivec_resolve_overloaded_builtin (loca
>                    "const");
>         type = build_qualified_type (TREE_TYPE (type), 0);
>         type = build_pointer_type (type);
> -       arg = fold_convert (type, arg);
> +       arg = c_fold_convert (type, arg);
>       }
>  
>        /* For RS6000_OVLD_VEC_LXVL, convert any const * to its non
> constant
> @@ -1802,7 +1830,7 @@ altivec_resolve_overloaded_builtin (loca
>       {
>         type = build_qualified_type (TREE_TYPE (type), 0);
>         type = build_pointer_type (type);
> -       arg = fold_convert (type, arg);
> +       arg = c_fold_convert (type, arg);
>       }
>  
>        args[n] = arg;
> --- gcc/testsuite/g++.target/powerpc/pr124133.C.jj    2026-02-17
> 16:50:11.004054635 +0100
> +++ gcc/testsuite/g++.target/powerpc/pr124133.C       2026-02-17
> 16:50:03.531179705 +0100
> @@ -0,0 +1,12 @@
> +// PR target/124133
> +// { dg-options "-mdejagnu-cpu=power8 -mvsx" }
> +// { dg-require-effective-target powerpc_vsx } */
> +
> +typedef __INTPTR_TYPE__ intptr_t;
> +
> +template <int>
> +void
> +foo (int x, short *y, intptr_t z)
> +{
> +  __builtin_vec_vsx_ld ((x + z) * 2, y);
> +}
> 
I tried this with and without the fix in rs6000-c.cc. It looks like it
does not ICE in either case in the current trunk. But the following
test ICE's without the fix


#include <altivec.h>
typedef unsigned char uint8_t;
typedef signed long int64_t;

typedef struct {
    float d;
    uint8_t qs[16];
} block_q4_0;

template <typename TA>
void packNormal_q4_fp16(const block_q4_0 * a) {
    vector signed char v_qs = (vector signed char)vec_xl(0, a->qs);
}

template <int>
void
foo (const block_q4_0 * a)
{
  vec_ld (0, (a->qs));
}

Also should we add more test cases for other overloaded builtins that
could ICE?

Thanks and regards,
Avinash Jayakar

>       Jakub

Reply via email to