]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fab: Manaully build gimple rather than depend on gimplifier for stdarg functions
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Mon, 22 Sep 2025 05:30:18 +0000 (22:30 -0700)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Fri, 3 Oct 2025 14:01:03 +0000 (07:01 -0700)
This code dates before gimple tuples was around. So it uses both MODIFY_EXPR and
INDIRECT_REF :).
For `__builtin_va_start(ptr, 0)` it exands into:
```
_t = __builtin_next_arg (0);
*ptr = _t;
```
We need to get a new VDEF for the next arg call so we don't need to do a
ssa update too.

For `__builtin_va_copy(ptr, b)`, it expands into:
```
*ptr = b;
```
Which is still a store.

For `__builtin_va_end(ptr)`, we change it into a GIMPLE_NOP.

Before optimize_stdarg_builtin would return a tree and then
pass_fold_builtins::execute would set todo to include
TODO_update_address_taken for a non-null result.
Since now optimize_stdarg_builtin returns a bool, the path that had
set the todo is no longer taken (the result variable is still NULL).
Setting the todo to include TODO_update_address_taken when the call to
optimize_stdarg_builtin succeeds to be able to get the same effect as
before.

That is:
before we had:
```
result = optimize_stdarg_builtin(...);
...
if (!result) continue;
todo |= TODO_update_address_taken;
```
Now after this change we have:
result = NULL_TREE;
...
if (optimize_stdarg_builtin(...))
  todo |= TODO_update_address_taken;
if (!result) continue;
```
Also since optimize_stdarg_builtin will remove the part of taking an
address of a local variable and in this case fab is the last pass
where this happens, TODO_update_address_taken is needed to change the
va args in some cases to not forced to memory variables.

Note this code will be moved into gimple_fold later on. This is part of the
reason for updating this code. The other side is this simplifies the code
too.

Changes since v1:
* v2: expand commit message.

gcc/ChangeLog:

* tree-ssa-ccp.cc (optimize_stdarg_builtin): Mannually create the
gimple statements instead of depending on the gimplifier.
(pass_fold_builtins::execute): Handle updated call to optimize_stdarg_builtin.

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

index 1fbc3de2bfe74ab61d71f1751297bdfa9766359b..c9ffd2af85c29249f2b590337f0bbcbff62aa180 100644 (file)
@@ -3175,14 +3175,16 @@ optimize_stack_restore (gimple_stmt_iterator i)
 /* 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.  */
+   pointer assignment.  Returns true if a change happened.  */
 
-static tree
-optimize_stdarg_builtin (gimple *call)
+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);
 
@@ -3197,48 +3199,90 @@ optimize_stdarg_builtin (gimple *call)
       if (!va_list_simple_ptr
          || targetm.expand_builtin_va_start != NULL
          || !builtin_decl_explicit_p (BUILT_IN_NEXT_ARG))
-       return NULL_TREE;
+       return false;
 
       if (gimple_call_num_args (call) != 2)
-       return NULL_TREE;
+       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 NULL_TREE;
+       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);
 
-      lhs = build_fold_indirect_ref_loc (loc, lhs);
-      rhs = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_NEXT_ARG),
-                             1, integer_zero_node);
-      rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
-      return build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
+      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 NULL_TREE;
+       return false;
 
       if (gimple_call_num_args (call) != 2)
-       return NULL_TREE;
+       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 NULL_TREE;
-
-      lhs = build_fold_indirect_ref_loc (loc, lhs);
+       return false;
       rhs = gimple_call_arg (call, 1);
       if (TYPE_MAIN_VARIANT (TREE_TYPE (rhs))
          != TYPE_MAIN_VARIANT (cfun_va_list))
-       return NULL_TREE;
+       return false;
 
-      rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
-      return build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
+      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.  */
-      return integer_zero_node;
+      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 ();
@@ -4426,7 +4470,8 @@ pass_fold_builtins::execute (function *fun)
                case BUILT_IN_VA_END:
                case BUILT_IN_VA_COPY:
                  /* These shouldn't be folded before pass_stdarg.  */
-                 result = optimize_stdarg_builtin (stmt);
+                 if (optimize_stdarg_builtin (&i, stmt))
+                   todoflags |= TODO_update_address_taken;
                  break;
 
                default:;