aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-12-31 14:47:03 +0100
committerRichard Biener <rguenth@gcc.gnu.org>2025-01-01 15:31:43 +0100
commitf8b559626025d2466c2780af6b62560dda468647 (patch)
tree654341b19c48164d01d723acd774501805510669
parentf8cd181e2d1d5541681ea7e3e92c8da46b048979 (diff)
downloadgcc-f8b559626025d2466c2780af6b62560dda468647.zip
gcc-f8b559626025d2466c2780af6b62560dda468647.tar.gz
gcc-f8b559626025d2466c2780af6b62560dda468647.tar.bz2
middle-end/118174 - bogus TER of tailcall
The following avoids applying TER to direct internal functions that are tailcall since the involved expansion code path doesn't honor TER constraints. PR middle-end/118174 * tree-outof-ssa.cc (ssa_is_replaceable_p): Exclude tailcalls. * gcc.dg/torture/pr118174.c: New testcase.
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr118174.c24
-rw-r--r--gcc/tree-outof-ssa.cc11
2 files changed, 31 insertions, 4 deletions
diff --git a/gcc/testsuite/gcc.dg/torture/pr118174.c b/gcc/testsuite/gcc.dg/torture/pr118174.c
new file mode 100644
index 0000000..faacef2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr118174.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+
+int __attribute__((noipa))
+foo (signed char *p1, signed char *p2)
+{
+ int sum = 0;
+ for (int i = 0; i < 32; i++)
+ sum += __builtin_abs (p1[i] - p2[i]);
+ return sum;
+}
+
+int
+main()
+{
+ signed char a[32], b[32];
+ for (int i = 0; i < 32; ++i)
+ {
+ a[i] = i;
+ b[i] = 16 - i;
+ }
+ if (foo (a, b) != 624)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/tree-outof-ssa.cc b/gcc/tree-outof-ssa.cc
index e51d5e0..cbe572f 100644
--- a/gcc/tree-outof-ssa.cc
+++ b/gcc/tree-outof-ssa.cc
@@ -61,11 +61,14 @@ ssa_is_replaceable_p (gimple *stmt)
tree def;
gimple *use_stmt;
- /* Only consider modify stmts and direct internal fn calls. */
+ /* Only consider modify stmts and direct internal fn calls that are
+ not also tail-calls. */
+ gcall *call;
if (!is_gimple_assign (stmt)
- && (!is_gimple_call (stmt)
- || !gimple_call_internal_p (stmt)
- || !direct_internal_fn_p (gimple_call_internal_fn (stmt))))
+ && (!(call = dyn_cast <gcall *> (stmt))
+ || gimple_call_tail_p (call)
+ || !gimple_call_internal_p (call)
+ || !direct_internal_fn_p (gimple_call_internal_fn (call))))
return false;
/* If the statement may throw an exception, it cannot be replaced. */