]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-sra: Avoid SRAing arguments to a function returning_twice (PR 117142)
authorMartin Jambor <mjambor@suse.cz>
Wed, 23 Oct 2024 09:30:32 +0000 (11:30 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Wed, 23 Oct 2024 09:35:56 +0000 (11:35 +0200)
PR 117142 shows that the current SRA probably never worked reliably
with arguments passed to a function returning twice, because it then
creates statements before the call which however needs to be at the
beginning of a basic block.

While it should be possible to make at least the case of passing
arguments by value work with SRA (the statements would need to be put
just on the non-abnormal edges leading to the BB), this would mean
large surgery of function sra_modify_expr and I guess the time would
better be spent re-organizing the whole pass.

gcc/ChangeLog:

2024-10-21  Martin Jambor  <mjambor@suse.cz>

PR tree-optimization/117142
* tree-sra.cc (build_access_from_call_arg): Disqualify any
candidate passed to a function returning twice.

gcc/testsuite/ChangeLog:

2024-10-21  Martin Jambor  <mjambor@suse.cz>

PR tree-optimization/117142
* gcc.dg/tree-ssa/pr117142.c: New test.

gcc/testsuite/gcc.dg/tree-ssa/pr117142.c [new file with mode: 0644]
gcc/tree-sra.cc

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr117142.c b/gcc/testsuite/gcc.dg/tree-ssa/pr117142.c
new file mode 100644 (file)
index 0000000..fc62c1e
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+struct a {
+  int b;
+};
+void c(int, int);
+void __attribute__((returns_twice))
+bar1(struct a);
+void bar(struct a) {
+  struct a d;
+  bar1(d);
+  c(d.b, d.b);
+}
index 64e2f007d6805cbac3b50858d80f17f66f27f37f..c0915dce5c4a4baaf17533172d454aec3903e7a8 100644 (file)
@@ -1397,6 +1397,15 @@ static bool
 build_access_from_call_arg (tree expr, gimple *stmt, bool can_be_returned,
                            enum out_edge_check *oe_check)
 {
+  if (gimple_call_flags (stmt) & ECF_RETURNS_TWICE)
+    {
+      tree base = expr;
+      if (TREE_CODE (expr) == ADDR_EXPR)
+       base = get_base_address (TREE_OPERAND (expr, 0));
+      disqualify_base_of_expr (base, "Passed to a returns_twice call.");
+      return false;
+    }
+
   if (TREE_CODE (expr) == ADDR_EXPR)
     {
       tree base = get_base_address (TREE_OPERAND (expr, 0));