diff options
author | Richard Biener <rguenther@suse.de> | 2024-12-31 14:47:03 +0100 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2025-01-01 15:31:43 +0100 |
commit | f8b559626025d2466c2780af6b62560dda468647 (patch) | |
tree | 654341b19c48164d01d723acd774501805510669 /gcc | |
parent | f8cd181e2d1d5541681ea7e3e92c8da46b048979 (diff) | |
download | gcc-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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr118174.c | 24 | ||||
-rw-r--r-- | gcc/tree-outof-ssa.cc | 11 |
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. */ |