aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/pr119493-1.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gcc.dg/pr119493-1.c')
-rw-r--r--gcc/testsuite/gcc.dg/pr119493-1.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/pr119493-1.c b/gcc/testsuite/gcc.dg/pr119493-1.c
new file mode 100644
index 0000000..edba61c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr119493-1.c
@@ -0,0 +1,55 @@
+/* PR tree-optimization/119493 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-tailr1" } */
+/* { dg-final { scan-tree-dump-times " = foo \\\(\[^\n\r;]*\\\);" 4 "tailr1" } } */
+/* { dg-final { scan-tree-dump-times " = bar \\\(\[^\n\r;]*\\\);" 4 "tailr1" } } */
+/* { dg-final { scan-tree-dump-not " = foo \\\(\[^\n\r;]*\\\); \\\[must tail call\\\]" "tailr1" } } */
+/* { dg-final { scan-tree-dump-not " = bar \\\(\[^\n\r;]*\\\); \\\[must tail call\\\]" "tailr1" } } */
+
+struct S { unsigned s; };
+struct T { struct S t[2]; };
+
+[[gnu::noinline, gnu::noclone]] struct S
+foo (struct S m)
+{
+ if (m.s == 0 || m.s == 42)
+ return m;
+ [[gnu::musttail]] return foo ((struct S) { m.s - 1 });
+}
+
+[[gnu::noinline, gnu::noclone]] struct S
+bar (struct T m, struct S n, int o, int p, int q)
+{
+ struct T r;
+ if (m.t[1].s != o || n.s != o)
+ __builtin_abort ();
+ if (o == 0 || o == 42)
+ return n;
+ r = m;
+ m.t[1].s -= p;
+ r.t[1].s -= q;
+ [[gnu::musttail]] return bar (r, m.t[1], o - 1, p, q);
+}
+
+int
+main ()
+{
+ if (foo ((struct S) { 0 }).s != 0)
+ __builtin_abort ();
+ if (foo ((struct S) { 4 }).s != 0)
+ __builtin_abort ();
+ if (foo ((struct S) { 42 }).s != 42)
+ __builtin_abort ();
+ if (foo ((struct S) { 51 }).s != 42)
+ __builtin_abort ();
+ if (bar ((struct T) { { { 0 }, { 0 } } }, (struct S) { 0 }, 0, 1, 1).s != 0)
+ __builtin_abort ();
+ if (bar ((struct T) { { { 7 }, { 7 } } }, (struct S) { 7 }, 7, 1, 1).s != 0)
+ __builtin_abort ();
+ if (bar ((struct T) { { { 42 }, { 42 } } },
+ (struct S) { 42 }, 42, 1, 1).s != 42)
+ __builtin_abort ();
+ if (bar ((struct T) { { { 48 }, { 48 } } },
+ (struct S) { 48 }, 48, 1, 1).s != 42)
+ __builtin_abort ();
+}