]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fab/gimple-fold/forwprop: Move va_args folding to gimple_fold [PR121762]
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Tue, 23 Sep 2025 19:58:37 +0000 (12:58 -0700)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Fri, 3 Oct 2025 14:29:08 +0000 (07:29 -0700)
This moves the va_args functions folding to gimple-fold. Right now this is still
kept for the last folding but later it can move sometime after stdargs pass is run by
checking PROP_gimple_lva instead.
Also for forwprop, if a folding happens for the last folding we need to maybe update the
variables as non-addressable like what is done in fab. It was originally added in fab for
__builtin_sincos->__builtin_cexpi folding (PR39643). After the removal of fab, this will
also be the last pass which updates address taken too.

PR tree-optimization/121762
gcc/ChangeLog:

* gimple-fold.cc (gimple_fold_builtin_stdarg): New function,
moved from tree-ssa-ccp.cc (optimize_stdarg_builtin).
(gimple_fold_builtin): Call gimple_fold_builtin_stdarg for
va_start, va_copy and va_end.
* tree-ssa-ccp.cc (optimize_stdarg_builtin): Remove.
(pass_fold_builtins::execute): Remove handling of
va_start, va_copy and va_end.
* tree-ssa-forwprop.cc (pass_forwprop::execute): Update
todos if fold_stmt return true if last forwprop to include
TODO_update_address_taken.

Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
gcc/gimple-fold.cc
gcc/tree-ssa-ccp.cc
gcc/tree-ssa-forwprop.cc

index a12fb5e8eab117da6e8d1199f94e3b4e96c70565..2f64de2fb4140a0562dc4fac0340f3fdc851d9e4 100644 (file)
@@ -5252,6 +5252,127 @@ gimple_fold_builtin_assume_aligned (gimple_stmt_iterator *gsi)
   return true;
 }
 
+/* If va_list type is a simple pointer and nothing special is needed,
+   optimize __builtin_va_start (&ap, 0) into ap = __builtin_next_arg (0),
+   __builtin_va_end (&ap) out as NOP and __builtin_va_copy into a simple
+   pointer assignment.  Returns true if a change happened.  */
+
+static bool
+gimple_fold_builtin_stdarg (gimple_stmt_iterator *gsi, gcall *call)
+{
+  /* These shouldn't be folded before pass_stdarg.  */
+  if (!(cfun->curr_properties & PROP_last_full_fold))
+    return false;
+
+  tree callee, lhs, rhs, cfun_va_list;
+  bool va_list_simple_ptr;
+  location_t loc = gimple_location (call);
+  gimple *nstmt0, *nstmt;
+  tree tlhs, oldvdef, newvdef;
+
+  callee = gimple_call_fndecl (call);
+
+  cfun_va_list = targetm.fn_abi_va_list (callee);
+  va_list_simple_ptr = POINTER_TYPE_P (cfun_va_list)
+                      && (TREE_TYPE (cfun_va_list) == void_type_node
+                          || TREE_TYPE (cfun_va_list) == char_type_node);
+
+  switch (DECL_FUNCTION_CODE (callee))
+    {
+    case BUILT_IN_VA_START:
+      if (!va_list_simple_ptr
+         || targetm.expand_builtin_va_start != NULL
+         || !builtin_decl_explicit_p (BUILT_IN_NEXT_ARG))
+       return false;
+
+      if (gimple_call_num_args (call) != 2)
+       return false;
+
+      lhs = gimple_call_arg (call, 0);
+      if (!POINTER_TYPE_P (TREE_TYPE (lhs))
+         || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs)))
+            != TYPE_MAIN_VARIANT (cfun_va_list))
+       return false;
+      /* Create `tlhs = __builtin_next_arg(0);`. */
+      tlhs = make_ssa_name (cfun_va_list);
+      nstmt0 = gimple_build_call (builtin_decl_explicit (BUILT_IN_NEXT_ARG), 1, integer_zero_node);
+      lhs = fold_build2 (MEM_REF, cfun_va_list, lhs, build_zero_cst (TREE_TYPE (lhs)));
+      gimple_call_set_lhs (nstmt0, tlhs);
+      gimple_set_location (nstmt0, loc);
+      gimple_move_vops (nstmt0, call);
+      gsi_replace (gsi, nstmt0, false);
+      oldvdef = gimple_vdef (nstmt0);
+      newvdef = make_ssa_name (gimple_vop (cfun), nstmt0);
+      gimple_set_vdef (nstmt0, newvdef);
+
+      /* Create `*lhs = tlhs;`.  */
+      nstmt = gimple_build_assign (lhs, tlhs);
+      gimple_set_location (nstmt, loc);
+      gimple_set_vuse (nstmt, newvdef);
+      gimple_set_vdef (nstmt, oldvdef);
+      SSA_NAME_DEF_STMT (oldvdef) = nstmt;
+      gsi_insert_after (gsi, nstmt, GSI_NEW_STMT);
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Simplified\n  ");
+         print_gimple_stmt (dump_file, call, 0, dump_flags);
+         fprintf (dump_file, "into\n  ");
+         print_gimple_stmt (dump_file, nstmt0, 0, dump_flags);
+         fprintf (dump_file, "  ");
+         print_gimple_stmt (dump_file, nstmt, 0, dump_flags);
+       }
+      return true;
+
+    case BUILT_IN_VA_COPY:
+      if (!va_list_simple_ptr)
+       return false;
+
+      if (gimple_call_num_args (call) != 2)
+       return false;
+
+      lhs = gimple_call_arg (call, 0);
+      if (!POINTER_TYPE_P (TREE_TYPE (lhs))
+         || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs)))
+            != TYPE_MAIN_VARIANT (cfun_va_list))
+       return false;
+      rhs = gimple_call_arg (call, 1);
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (rhs))
+         != TYPE_MAIN_VARIANT (cfun_va_list))
+       return false;
+
+      lhs = fold_build2 (MEM_REF, cfun_va_list, lhs, build_zero_cst (TREE_TYPE (lhs)));
+      nstmt = gimple_build_assign (lhs, rhs);
+      gimple_set_location (nstmt, loc);
+      gimple_move_vops (nstmt, call);
+      gsi_replace (gsi, nstmt, false);
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Simplified\n  ");
+         print_gimple_stmt (dump_file, call, 0, dump_flags);
+         fprintf (dump_file, "into\n  ");
+         print_gimple_stmt (dump_file, nstmt, 0, dump_flags);
+       }
+      return true;
+
+    case BUILT_IN_VA_END:
+      /* No effect, so the statement will be deleted.  */
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Removed\n  ");
+         print_gimple_stmt (dump_file, call, 0, dump_flags);
+       }
+      unlink_stmt_vdef (call);
+      release_defs (call);
+      gsi_replace (gsi, gimple_build_nop (), true);
+      return true;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Fold the non-target builtin at *GSI and return whether any simplification
    was made.  */
 
@@ -5270,6 +5391,10 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
   enum built_in_function fcode = DECL_FUNCTION_CODE (callee);
   switch (fcode)
     {
+    case BUILT_IN_VA_START:
+    case BUILT_IN_VA_END:
+    case BUILT_IN_VA_COPY:
+      return gimple_fold_builtin_stdarg (gsi, stmt);
     case BUILT_IN_BCMP:
       return gimple_fold_builtin_bcmp (gsi);
     case BUILT_IN_BCOPY:
index b69a8b64a61bcc7c8c2b8b620c7dde428541e76a..2d16395ac68e3f06d5df77c40fc91f5e4bc2325e 100644 (file)
@@ -3085,124 +3085,6 @@ make_pass_ccp (gcc::context *ctxt)
   return new pass_ccp (ctxt);
 }
 
-/* If va_list type is a simple pointer and nothing special is needed,
-   optimize __builtin_va_start (&ap, 0) into ap = __builtin_next_arg (0),
-   __builtin_va_end (&ap) out as NOP and __builtin_va_copy into a simple
-   pointer assignment.  Returns true if a change happened.  */
-
-static bool
-optimize_stdarg_builtin (gimple_stmt_iterator *gsi, gimple *call)
-{
-  tree callee, lhs, rhs, cfun_va_list;
-  bool va_list_simple_ptr;
-  location_t loc = gimple_location (call);
-  gimple *nstmt0, *nstmt;
-  tree tlhs, oldvdef, newvdef;
-
-  callee = gimple_call_fndecl (call);
-
-  cfun_va_list = targetm.fn_abi_va_list (callee);
-  va_list_simple_ptr = POINTER_TYPE_P (cfun_va_list)
-                      && (TREE_TYPE (cfun_va_list) == void_type_node
-                          || TREE_TYPE (cfun_va_list) == char_type_node);
-
-  switch (DECL_FUNCTION_CODE (callee))
-    {
-    case BUILT_IN_VA_START:
-      if (!va_list_simple_ptr
-         || targetm.expand_builtin_va_start != NULL
-         || !builtin_decl_explicit_p (BUILT_IN_NEXT_ARG))
-       return false;
-
-      if (gimple_call_num_args (call) != 2)
-       return false;
-
-      lhs = gimple_call_arg (call, 0);
-      if (!POINTER_TYPE_P (TREE_TYPE (lhs))
-         || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs)))
-            != TYPE_MAIN_VARIANT (cfun_va_list))
-       return false;
-      /* Create `tlhs = __builtin_next_arg(0);`. */
-      tlhs = make_ssa_name (cfun_va_list);
-      nstmt0 = gimple_build_call (builtin_decl_explicit (BUILT_IN_NEXT_ARG), 1, integer_zero_node);
-      lhs = fold_build2 (MEM_REF, cfun_va_list, lhs, build_zero_cst (TREE_TYPE (lhs)));
-      gimple_call_set_lhs (nstmt0, tlhs);
-      gimple_set_location (nstmt0, loc);
-      gimple_move_vops (nstmt0, call);
-      gsi_replace (gsi, nstmt0, false);
-      oldvdef = gimple_vdef (nstmt0);
-      newvdef = make_ssa_name (gimple_vop (cfun), nstmt0);
-      gimple_set_vdef (nstmt0, newvdef);
-
-      /* Create `*lhs = tlhs;`.  */
-      nstmt = gimple_build_assign (lhs, tlhs);
-      gimple_set_location (nstmt, loc);
-      gimple_set_vuse (nstmt, newvdef);
-      gimple_set_vdef (nstmt, oldvdef);
-      SSA_NAME_DEF_STMT (oldvdef) = nstmt;
-      gsi_insert_after (gsi, nstmt, GSI_NEW_STMT);
-
-      if (dump_file && (dump_flags & TDF_DETAILS))
-       {
-         fprintf (dump_file, "Simplified\n  ");
-         print_gimple_stmt (dump_file, call, 0, dump_flags);
-         fprintf (dump_file, "into\n  ");
-         print_gimple_stmt (dump_file, nstmt0, 0, dump_flags);
-         fprintf (dump_file, "  ");
-         print_gimple_stmt (dump_file, nstmt, 0, dump_flags);
-       }
-      return true;
-
-    case BUILT_IN_VA_COPY:
-      if (!va_list_simple_ptr)
-       return false;
-
-      if (gimple_call_num_args (call) != 2)
-       return false;
-
-      lhs = gimple_call_arg (call, 0);
-      if (!POINTER_TYPE_P (TREE_TYPE (lhs))
-         || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs)))
-            != TYPE_MAIN_VARIANT (cfun_va_list))
-       return false;
-      rhs = gimple_call_arg (call, 1);
-      if (TYPE_MAIN_VARIANT (TREE_TYPE (rhs))
-         != TYPE_MAIN_VARIANT (cfun_va_list))
-       return false;
-
-      lhs = fold_build2 (MEM_REF, cfun_va_list, lhs, build_zero_cst (TREE_TYPE (lhs)));
-      nstmt = gimple_build_assign (lhs, rhs);
-      gimple_set_location (nstmt, loc);
-      gimple_move_vops (nstmt, call);
-      gsi_replace (gsi, nstmt, false);
-
-      if (dump_file && (dump_flags & TDF_DETAILS))
-       {
-         fprintf (dump_file, "Simplified\n  ");
-         print_gimple_stmt (dump_file, call, 0, dump_flags);
-         fprintf (dump_file, "into\n  ");
-         print_gimple_stmt (dump_file, nstmt, 0, dump_flags);
-       }
-      return true;
-
-    case BUILT_IN_VA_END:
-      /* No effect, so the statement will be deleted.  */
-      if (dump_file && (dump_flags & TDF_DETAILS))
-       {
-         fprintf (dump_file, "Removed\n  ");
-         print_gimple_stmt (dump_file, call, 0, dump_flags);
-       }
-      unlink_stmt_vdef (call);
-      release_defs (call);
-      gsi_replace (gsi, gimple_build_nop (), true);
-      return true;
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-
 /* Convert
    _1 = __atomic_fetch_or_* (ptr_6, 1, _3);
    _7 = ~_1;
@@ -4339,14 +4221,6 @@ pass_fold_builtins::execute (function *fun)
                                                  false);
                  break;
 
-               case BUILT_IN_VA_START:
-               case BUILT_IN_VA_END:
-               case BUILT_IN_VA_COPY:
-                 /* These shouldn't be folded before pass_stdarg.  */
-                 if (optimize_stdarg_builtin (&i, stmt))
-                   todoflags |= TODO_update_address_taken;
-                 break;
-
                default:;
                }
 
index 9307e216207884696808c2a4187364a705026222..2c6e1eab9cdbfa27338963232e6bf1980acd46e0 100644 (file)
@@ -5463,6 +5463,11 @@ pass_forwprop::execute (function *fun)
              if (fold_stmt (&gsi, fwprop_ssa_val, simple_dce_worklist))
                {
                  changed = true;
+                 /* There is no updating of the address
+                    taken after the last forwprop so update
+                    the addresses when a folding happened. */
+                 if (last_p)
+                   todoflags |= TODO_update_address_taken;
                  stmt = gsi_stmt (gsi);
                  /* Cleanup the CFG if we simplified a condition to
                     true or false.  */