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);
+}

        Jakub

Reply via email to