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
