diff mbox series

[v3,4/5] Add tests for C/C++ musttail attributes

Message ID 20240131021808.151575-5-ak@linux.intel.com
State New
Headers show
Series [v3,1/5] Improve must tail in RTL backend | expand

Commit Message

Andi Kleen Jan. 31, 2024, 2:17 a.m. UTC
Mostly adopted from the existing C musttail plugin tests.
---
 gcc/testsuite/c-c++-common/musttail1.c  | 17 ++++++++++++
 gcc/testsuite/c-c++-common/musttail2.c  | 36 +++++++++++++++++++++++++
 gcc/testsuite/c-c++-common/musttail3.c  | 31 +++++++++++++++++++++
 gcc/testsuite/c-c++-common/musttail4.c  | 19 +++++++++++++
 gcc/testsuite/gcc.dg/musttail-invalid.c | 17 ++++++++++++
 5 files changed, 120 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/musttail1.c
 create mode 100644 gcc/testsuite/c-c++-common/musttail2.c
 create mode 100644 gcc/testsuite/c-c++-common/musttail3.c
 create mode 100644 gcc/testsuite/c-c++-common/musttail4.c
 create mode 100644 gcc/testsuite/gcc.dg/musttail-invalid.c

Comments

Prathamesh Kulkarni Jan. 31, 2024, 12:44 p.m. UTC | #1
On Wed, 31 Jan 2024 at 07:49, Andi Kleen <ak@linux.intel.com> wrote:
>
> Mostly adopted from the existing C musttail plugin tests.
> ---
>  gcc/testsuite/c-c++-common/musttail1.c  | 17 ++++++++++++
>  gcc/testsuite/c-c++-common/musttail2.c  | 36 +++++++++++++++++++++++++
>  gcc/testsuite/c-c++-common/musttail3.c  | 31 +++++++++++++++++++++
>  gcc/testsuite/c-c++-common/musttail4.c  | 19 +++++++++++++
>  gcc/testsuite/gcc.dg/musttail-invalid.c | 17 ++++++++++++
>  5 files changed, 120 insertions(+)
>  create mode 100644 gcc/testsuite/c-c++-common/musttail1.c
>  create mode 100644 gcc/testsuite/c-c++-common/musttail2.c
>  create mode 100644 gcc/testsuite/c-c++-common/musttail3.c
>  create mode 100644 gcc/testsuite/c-c++-common/musttail4.c
>  create mode 100644 gcc/testsuite/gcc.dg/musttail-invalid.c
>
> diff --git a/gcc/testsuite/c-c++-common/musttail1.c b/gcc/testsuite/c-c++-common/musttail1.c
> new file mode 100644
> index 000000000000..476185e3ed4b
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/musttail1.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile { target tail_call } } */
> +/* { dg-options "-O2" } */
> +/* { dg-additional-options "-std=c++11" { target c++ } } */
> +/* { dg-additional-options "-std=c23" { target c } } */
> +/* { dg-additional-options "-fdelayed-branch" { target sparc*-*-* } } */
> +
> +int __attribute__((noinline,noclone))
Hi,
Sorry to nitpick -- Just wondering if it'd be slightly better to use
noipa attribute instead, assuming the intent is to disable IPA opts ?

Thanks,
Prathamesh


> +callee (int i)
> +{
> +  return i * i;
> +}
> +
> +int __attribute__((noinline,noclone))
> +caller (int i)
> +{
> +  [[gnu::musttail]] return callee (i + 1);
> +}
> diff --git a/gcc/testsuite/c-c++-common/musttail2.c b/gcc/testsuite/c-c++-common/musttail2.c
> new file mode 100644
> index 000000000000..28f2f68ef13d
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/musttail2.c
> @@ -0,0 +1,36 @@
> +/* { dg-do compile { target tail_call } } */
> +/* { dg-additional-options "-std=c++11" { target c++ } } */
> +/* { dg-additional-options "-std=c23" { target c } } */
> +
> +struct box { char field[256]; int i; };
> +
> +int __attribute__((noinline,noclone))
> +test_2_callee (int i, struct box b)
> +{
> +  if (b.field[0])
> +    return 5;
> +  return i * i;
> +}
> +
> +int __attribute__((noinline,noclone))
> +test_2_caller (int i)
> +{
> +  struct box b;
> +  [[gnu::musttail]] return test_2_callee (i + 1, b); /* { dg-error "cannot tail-call: " } */
> +}
> +
> +extern void setjmp (void);
> +void
> +test_3 (void)
> +{
> +  [[gnu::musttail]] return setjmp (); /* { dg-error "cannot tail-call: " } */
> +}
> +
> +typedef void (fn_ptr_t) (void);
> +volatile fn_ptr_t fn_ptr;
> +
> +void
> +test_5 (void)
> +{
> +  [[gnu::musttail]] return fn_ptr (); /* { dg-error "cannot tail-call: " } */
> +}
> diff --git a/gcc/testsuite/c-c++-common/musttail3.c b/gcc/testsuite/c-c++-common/musttail3.c
> new file mode 100644
> index 000000000000..fdbb292944ad
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/musttail3.c
> @@ -0,0 +1,31 @@
> +/* { dg-do compile { target tail_call } } */
> +/* { dg-additional-options "-std=c++11" { target c++ } } */
> +/* { dg-additional-options "-std=c23" { target c } } */
> +
> +extern int foo2 (int x, ...);
> +
> +struct str
> +{
> +  int a, b;
> +};
> +
> +struct str
> +cstruct (int x)
> +{
> +  if (x < 10)
> +    [[clang::musttail]] return cstruct (x + 1);
> +  return ((struct str){ x, 0 });
> +}
> +
> +int
> +foo (int x)
> +{
> +  if (x < 10)
> +    [[clang::musttail]] return foo2 (x, 29);
> +  if (x < 100)
> +    {
> +      int k = foo (x + 1);
> +      [[clang::musttail]] return k;    /* { dg-error "cannot tail-call: " } */
> +    }
> +  return x;
> +}
> diff --git a/gcc/testsuite/c-c++-common/musttail4.c b/gcc/testsuite/c-c++-common/musttail4.c
> new file mode 100644
> index 000000000000..7bf44816f14a
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/musttail4.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target tail_call } } */
> +/* { dg-additional-options "-std=c++11" { target c++ } } */
> +/* { dg-additional-options "-std=c23" { target c } } */
> +
> +struct box { char field[64]; int i; };
> +
> +struct box __attribute__((noinline,noclone))
> +returns_struct (int i)
> +{
> +  struct box b;
> +  b.i = i * i;
> +  return b;
> +}
> +
> +int __attribute__((noinline,noclone))
> +test_1 (int i)
> +{
> +  [[gnu::musttail]] return returns_struct (i * 5).i; /* { dg-error "cannot tail-call: " } */
> +}
> diff --git a/gcc/testsuite/gcc.dg/musttail-invalid.c b/gcc/testsuite/gcc.dg/musttail-invalid.c
> new file mode 100644
> index 000000000000..c4725b4b8226
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/musttail-invalid.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +/* { dg-options "-std=c23" } */
> +
> +[[musttail]] int j; /* { dg-warning "attribute ignored" } */
> +__attribute__((musttail)) int k; /* { dg-warning "attribute directive ignored" } */
> +
> +void foo(void)
> +{
> +       [[musttail]] j++; /* { dg-warning "attribute ignored" } */
> +       [[musttail]] if (k > 0) /* { dg-warning "attribute ignored" } */
> +               [[musttail]] k++; /* { dg-warning "attribute ignored" } */
> +}
> +
> +int foo2(int p)
> +{
> +       [[gnu::musttail(1)]] return foo2(p + 1); /* { dg-error "has arguments" } */
> +}
> --
> 2.43.0
>
Marek Polacek Jan. 31, 2024, 8:11 p.m. UTC | #2
On Tue, Jan 30, 2024 at 06:17:17PM -0800, Andi Kleen wrote:
> Mostly adopted from the existing C musttail plugin tests.

Please add a ChangeLog entry.

> ---
>  gcc/testsuite/c-c++-common/musttail1.c  | 17 ++++++++++++
>  gcc/testsuite/c-c++-common/musttail2.c  | 36 +++++++++++++++++++++++++
>  gcc/testsuite/c-c++-common/musttail3.c  | 31 +++++++++++++++++++++
>  gcc/testsuite/c-c++-common/musttail4.c  | 19 +++++++++++++
>  gcc/testsuite/gcc.dg/musttail-invalid.c | 17 ++++++++++++
>  5 files changed, 120 insertions(+)
>  create mode 100644 gcc/testsuite/c-c++-common/musttail1.c
>  create mode 100644 gcc/testsuite/c-c++-common/musttail2.c
>  create mode 100644 gcc/testsuite/c-c++-common/musttail3.c
>  create mode 100644 gcc/testsuite/c-c++-common/musttail4.c
>  create mode 100644 gcc/testsuite/gcc.dg/musttail-invalid.c
> 
> diff --git a/gcc/testsuite/c-c++-common/musttail1.c b/gcc/testsuite/c-c++-common/musttail1.c
> new file mode 100644
> index 000000000000..476185e3ed4b
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/musttail1.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile { target tail_call } } */
> +/* { dg-options "-O2" } */
> +/* { dg-additional-options "-std=c++11" { target c++ } } */

This will run the test only once with -std=c++11.  We'll get better coverage
with dropping the line above and using

/* { dg-do compile { target { tail_call && { c || c++11 } } } } */

but here it may not matter.

> +/* { dg-additional-options "-std=c23" { target c } } */
> +/* { dg-additional-options "-fdelayed-branch" { target sparc*-*-* } } */
> +
> +int __attribute__((noinline,noclone))
> +callee (int i)
> +{
> +  return i * i;
> +}
> +
> +int __attribute__((noinline,noclone))
> +caller (int i)
> +{
> +  [[gnu::musttail]] return callee (i + 1);
> +}
> diff --git a/gcc/testsuite/c-c++-common/musttail2.c b/gcc/testsuite/c-c++-common/musttail2.c
> new file mode 100644
> index 000000000000..28f2f68ef13d
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/musttail2.c
> @@ -0,0 +1,36 @@
> +/* { dg-do compile { target tail_call } } */
> +/* { dg-additional-options "-std=c++11" { target c++ } } */
> +/* { dg-additional-options "-std=c23" { target c } } */
> +
> +struct box { char field[256]; int i; };
> +
> +int __attribute__((noinline,noclone))
> +test_2_callee (int i, struct box b)
> +{
> +  if (b.field[0])
> +    return 5;
> +  return i * i;
> +}
> +
> +int __attribute__((noinline,noclone))
> +test_2_caller (int i)
> +{
> +  struct box b;
> +  [[gnu::musttail]] return test_2_callee (i + 1, b); /* { dg-error "cannot tail-call: " } */
> +}
> +
> +extern void setjmp (void);
> +void
> +test_3 (void)
> +{
> +  [[gnu::musttail]] return setjmp (); /* { dg-error "cannot tail-call: " } */
> +}
> +
> +typedef void (fn_ptr_t) (void);
> +volatile fn_ptr_t fn_ptr;
> +
> +void
> +test_5 (void)
> +{
> +  [[gnu::musttail]] return fn_ptr (); /* { dg-error "cannot tail-call: " } */
> +}
> diff --git a/gcc/testsuite/c-c++-common/musttail3.c b/gcc/testsuite/c-c++-common/musttail3.c
> new file mode 100644
> index 000000000000..fdbb292944ad
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/musttail3.c
> @@ -0,0 +1,31 @@
> +/* { dg-do compile { target tail_call } } */
> +/* { dg-additional-options "-std=c++11" { target c++ } } */
> +/* { dg-additional-options "-std=c23" { target c } } */
> +
> +extern int foo2 (int x, ...);
> +
> +struct str
> +{
> +  int a, b;
> +};
> +
> +struct str
> +cstruct (int x)
> +{
> +  if (x < 10)
> +    [[clang::musttail]] return cstruct (x + 1);
> +  return ((struct str){ x, 0 });
> +}
> +
> +int
> +foo (int x)
> +{
> +  if (x < 10)
> +    [[clang::musttail]] return foo2 (x, 29);
> +  if (x < 100)
> +    {
> +      int k = foo (x + 1);
> +      [[clang::musttail]] return k;	/* { dg-error "cannot tail-call: " } */
> +    }
> +  return x;
> +}
> diff --git a/gcc/testsuite/c-c++-common/musttail4.c b/gcc/testsuite/c-c++-common/musttail4.c
> new file mode 100644
> index 000000000000..7bf44816f14a
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/musttail4.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target tail_call } } */
> +/* { dg-additional-options "-std=c++11" { target c++ } } */
> +/* { dg-additional-options "-std=c23" { target c } } */
> +
> +struct box { char field[64]; int i; };
> +
> +struct box __attribute__((noinline,noclone))
> +returns_struct (int i)
> +{
> +  struct box b;
> +  b.i = i * i;
> +  return b;
> +}
> +
> +int __attribute__((noinline,noclone))
> +test_1 (int i)
> +{
> +  [[gnu::musttail]] return returns_struct (i * 5).i; /* { dg-error "cannot tail-call: " } */
> +}
> diff --git a/gcc/testsuite/gcc.dg/musttail-invalid.c b/gcc/testsuite/gcc.dg/musttail-invalid.c
> new file mode 100644
> index 000000000000..c4725b4b8226
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/musttail-invalid.c

Is there a C++ test for the invalid cases?

> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +/* { dg-options "-std=c23" } */
> +
> +[[musttail]] int j; /* { dg-warning "attribute ignored" } */
> +__attribute__((musttail)) int k; /* { dg-warning "attribute directive ignored" } */
> +
> +void foo(void)
> +{
> +	[[musttail]] j++; /* { dg-warning "attribute ignored" } */
> +	[[musttail]] if (k > 0) /* { dg-warning "attribute ignored" } */
> +		[[musttail]] k++; /* { dg-warning "attribute ignored" } */
> +}
> +
> +int foo2(int p)
> +{
> +	[[gnu::musttail(1)]] return foo2(p + 1); /* { dg-error "has arguments" } */
> +}
> -- 
> 2.43.0
> 

Marek
Andi Kleen Feb. 1, 2024, 7:39 a.m. UTC | #3
> This will run the test only once with -std=c++11.  We'll get better coverage
> with dropping the line above and using
> 
> /* { dg-do compile { target { tail_call && { c || c++11 } } } } */
> 
> but here it may not matter.

The problem is that older C/C++ standards don't support [[]] attributes.
It would make sense to say >= gnu++11 || >= c23 but I don't know how to
express that.
Marek Polacek Feb. 1, 2024, 2:03 p.m. UTC | #4
On Wed, Jan 31, 2024 at 11:39:56PM -0800, Andi Kleen wrote:
> > This will run the test only once with -std=c++11.  We'll get better coverage
> > with dropping the line above and using
> > 
> > /* { dg-do compile { target { tail_call && { c || c++11 } } } } */
> > 
> > but here it may not matter.
> 
> The problem is that older C/C++ standards don't support [[]] attributes.
> It would make sense to say >= gnu++11 || >= c23 but I don't know how to
> express that.
 
That's what the c++11 target does.  Unfortunately for C we don't have
anything like that, hence the additional-options adding c23.

Marek
Joseph Myers Feb. 1, 2024, 5:33 p.m. UTC | #5
On Thu, 1 Feb 2024, Marek Polacek wrote:

> On Wed, Jan 31, 2024 at 11:39:56PM -0800, Andi Kleen wrote:
> > > This will run the test only once with -std=c++11.  We'll get better coverage
> > > with dropping the line above and using
> > > 
> > > /* { dg-do compile { target { tail_call && { c || c++11 } } } } */
> > > 
> > > but here it may not matter.
> > 
> > The problem is that older C/C++ standards don't support [[]] attributes.
> > It would make sense to say >= gnu++11 || >= c23 but I don't know how to
> > express that.
>  
> That's what the c++11 target does.  Unfortunately for C we don't have
> anything like that, hence the additional-options adding c23.

For C we don't loop over the testsuite building with different standard 
options - such a conditional only makes sense for C++ in the context of 
building the same tests several times for different standards, when some 
tests need to be conditional on the standard for which they are built.
diff mbox series

Patch

diff --git a/gcc/testsuite/c-c++-common/musttail1.c b/gcc/testsuite/c-c++-common/musttail1.c
new file mode 100644
index 000000000000..476185e3ed4b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/musttail1.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile { target tail_call } } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+/* { dg-additional-options "-std=c23" { target c } } */
+/* { dg-additional-options "-fdelayed-branch" { target sparc*-*-* } } */
+
+int __attribute__((noinline,noclone))
+callee (int i)
+{
+  return i * i;
+}
+
+int __attribute__((noinline,noclone))
+caller (int i)
+{
+  [[gnu::musttail]] return callee (i + 1);
+}
diff --git a/gcc/testsuite/c-c++-common/musttail2.c b/gcc/testsuite/c-c++-common/musttail2.c
new file mode 100644
index 000000000000..28f2f68ef13d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/musttail2.c
@@ -0,0 +1,36 @@ 
+/* { dg-do compile { target tail_call } } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+/* { dg-additional-options "-std=c23" { target c } } */
+
+struct box { char field[256]; int i; };
+
+int __attribute__((noinline,noclone))
+test_2_callee (int i, struct box b)
+{
+  if (b.field[0])
+    return 5;
+  return i * i;
+}
+
+int __attribute__((noinline,noclone))
+test_2_caller (int i)
+{
+  struct box b;
+  [[gnu::musttail]] return test_2_callee (i + 1, b); /* { dg-error "cannot tail-call: " } */
+}
+
+extern void setjmp (void);
+void
+test_3 (void)
+{
+  [[gnu::musttail]] return setjmp (); /* { dg-error "cannot tail-call: " } */
+}
+
+typedef void (fn_ptr_t) (void);
+volatile fn_ptr_t fn_ptr;
+
+void
+test_5 (void)
+{
+  [[gnu::musttail]] return fn_ptr (); /* { dg-error "cannot tail-call: " } */
+}
diff --git a/gcc/testsuite/c-c++-common/musttail3.c b/gcc/testsuite/c-c++-common/musttail3.c
new file mode 100644
index 000000000000..fdbb292944ad
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/musttail3.c
@@ -0,0 +1,31 @@ 
+/* { dg-do compile { target tail_call } } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+/* { dg-additional-options "-std=c23" { target c } } */
+
+extern int foo2 (int x, ...);
+
+struct str
+{
+  int a, b;
+};
+
+struct str
+cstruct (int x)
+{
+  if (x < 10)
+    [[clang::musttail]] return cstruct (x + 1);
+  return ((struct str){ x, 0 });
+}
+
+int
+foo (int x)
+{
+  if (x < 10)
+    [[clang::musttail]] return foo2 (x, 29);
+  if (x < 100)
+    {
+      int k = foo (x + 1);
+      [[clang::musttail]] return k;	/* { dg-error "cannot tail-call: " } */
+    }
+  return x;
+}
diff --git a/gcc/testsuite/c-c++-common/musttail4.c b/gcc/testsuite/c-c++-common/musttail4.c
new file mode 100644
index 000000000000..7bf44816f14a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/musttail4.c
@@ -0,0 +1,19 @@ 
+/* { dg-do compile { target tail_call } } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+/* { dg-additional-options "-std=c23" { target c } } */
+
+struct box { char field[64]; int i; };
+
+struct box __attribute__((noinline,noclone))
+returns_struct (int i)
+{
+  struct box b;
+  b.i = i * i;
+  return b;
+}
+
+int __attribute__((noinline,noclone))
+test_1 (int i)
+{
+  [[gnu::musttail]] return returns_struct (i * 5).i; /* { dg-error "cannot tail-call: " } */
+}
diff --git a/gcc/testsuite/gcc.dg/musttail-invalid.c b/gcc/testsuite/gcc.dg/musttail-invalid.c
new file mode 100644
index 000000000000..c4725b4b8226
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/musttail-invalid.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile } */
+/* { dg-options "-std=c23" } */
+
+[[musttail]] int j; /* { dg-warning "attribute ignored" } */
+__attribute__((musttail)) int k; /* { dg-warning "attribute directive ignored" } */
+
+void foo(void)
+{
+	[[musttail]] j++; /* { dg-warning "attribute ignored" } */
+	[[musttail]] if (k > 0) /* { dg-warning "attribute ignored" } */
+		[[musttail]] k++; /* { dg-warning "attribute ignored" } */
+}
+
+int foo2(int p)
+{
+	[[gnu::musttail(1)]] return foo2(p + 1); /* { dg-error "has arguments" } */
+}