[RFA:] Test-cases for sibling calls.

Hans-Peter Nilsson hp@bitrange.com
Sat Sep 28 07:01:00 GMT 2002


There are a few test-cases that check that code generating
sibcalls don't ICE and similarly don't emit obviously incorrect
code.  But as Fergus Henderson pointed out, there are no
regression tests (tsk, tsk) checking that sibcalls work, as in
doing "jump" not "call". Here are four (or two, depending on
your definition), following my suggestion at
<URL: http://gcc.gnu.org/ml/gcc-patches/2002-09/msg01567.html >.

Note that the tests don't work (do not fail) for targets where
the return-address ends up elsewhere than the same stack as
local variables, like MMIX with its register stack (and ia64?)
Also, no tests for sibcall_value; could supposedly trivially
follow the same pattern as these tests.  The xfails match
missing matches for "grep sibcall config/*/*.md" adjusted for
target names and seem to work (marked correctly) for simulator
targets; CRIS, ARM, v850 and SH tested.  Also tested native on
i686-pc-linux-gnu.

Ok to commit?

	* gcc.dg/sibcall-1.c, gcc.dg/sibcall-2.c, gcc.dg/sibcall-3.c,
	gcc.dg/sibcall-4.c: New tests.

*** /dev/null	Tue Jan  1 05:00:00 1980
--- sibcall-1.c	Fri Sep 27 22:22:40 2002
***************
*** 0 ****
--- 1,46 ----
+ /* Simple check that sibling calls are performed from a
+    void non-leaf-function taking one int argument calling itself.
+
+    Copyright (C) 2002 Free Software Foundation Inc.
+    Contributed by Hans-Peter Nilsson  <hp@bitrange.com>  */
+
+ /* { dg-do run } */
+ /* { dg-options "-O2 -foptimize-sibling-calls" } */
+
+ /* The option -foptimize-sibling-calls is the default, but serves as
+    marker.  Self-recursion tail calls are optimized for all targets,
+    regardless of presence of sibcall patterns.  */
+
+ extern void recurser_void (int);
+ extern void track (int);
+
+ int main ()
+ {
+   recurser_void (0);
+   exit (0);
+ }
+
+ void
+ recurser_void (int n)
+ {
+   if (n == 0 || n == 7)
+     track (n);
+
+   if (n == 10)
+     return;
+
+   recurser_void (n + 1);
+ }
+
+ void *trackpoint;
+
+ void
+ track (int n)
+ {
+   char stackpos[1];
+
+   if (n == 0)
+     trackpoint = stackpos;
+   else if (n != 7 || trackpoint != stackpos)
+     abort ();
+ }
*** /dev/null	Tue Jan  1 05:00:00 1980
--- sibcall-2.c	Fri Sep 27 22:22:39 2002
***************
*** 0 ****
--- 1,47 ----
+ /* Simple check that sibling calls are performed from a
+    void non-leaf-function taking no arguments calling itself.
+
+    Copyright (C) 2002 Free Software Foundation Inc.
+    Contributed by Hans-Peter Nilsson  <hp@bitrange.com>  */
+
+ /* { dg-do run } */
+ /* { dg-options "-O2 -foptimize-sibling-calls" } */
+
+ /* The option -foptimize-sibling-calls is the default, but serves as
+    marker.  Self-recursion tail calls are optimized for all targets,
+    regardless of presence of sibcall patterns.  */
+
+ extern void recurser_void (void);
+ extern void track (void);
+
+ int n = 0;
+ int main ()
+ {
+   recurser_void ();
+   exit (0);
+ }
+
+ void
+ recurser_void (void)
+ {
+   if (n == 0 || n == 7)
+     track ();
+
+   if (n == 10)
+     return;
+   n++;
+   recurser_void ();
+ }
+
+ void *trackpoint;
+
+ void
+ track ()
+ {
+   char stackpos[1];
+
+   if (n == 0)
+     trackpoint = stackpos;
+   else if (n != 7 || trackpoint != stackpos)
+     abort ();
+ }
*** /dev/null	Tue Jan  1 05:00:00 1980
--- sibcall-3.c	Fri Sep 27 22:19:36 2002
***************
*** 0 ****
--- 1,65 ----
+ /* Simple check that sibling calls are performed from a
+    void non-leaf-function taking one int argument calling a function which
+    is about the same as itself.
+
+    Copyright (C) 2002 Free Software Foundation Inc.
+    Contributed by Hans-Peter Nilsson  <hp@bitrange.com>  */
+
+ /* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* i370-*-* i960-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10?00-*-* ns32k-*-* s390*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
+ /* { dg-options "-O2 -foptimize-sibling-calls" } */
+
+ /* The option -foptimize-sibling-calls is the default, but serves as
+    marker.  This test is xfailed on targets without sibcall patterns
+    (except targets where the test does not work due to the return address
+    not saved on the regular stack).  */
+
+ static void recurser_void1 (int);
+ static void recurser_void2 (int);
+ extern void track (int);
+
+ int main ()
+ {
+   recurser_void1 (0);
+   exit (0);
+ }
+
+ /* The functions should get the same stack-frame, and best way to make it
+    reasonably sure is to make them have the same contents (regarding the
+    n tests).  */
+
+ static void
+ recurser_void1 (int n)
+ {
+   if (n == 0 || n == 7 || n == 8)
+     track (n);
+
+   if (n == 10)
+     return;
+
+   recurser_void2 (n + 1);
+ }
+
+ static void
+ recurser_void2 (int n)
+ {
+   if (n == 0 || n == 7 || n == 8)
+     track (n);
+
+   if (n == 10)
+     return;
+
+   recurser_void1 (n + 1);
+ }
+
+ void *trackpoint;
+
+ void
+ track (int n)
+ {
+   char stackpos[1];
+
+   if (n == 0)
+     trackpoint = stackpos;
+   else if ((n != 7 && n != 8) || trackpoint != stackpos)
+     abort ();
+ }
*** /dev/null	Tue Jan  1 05:00:00 1980
--- sibcall-4.c	Fri Sep 27 22:19:40 2002
***************
*** 0 ****
--- 1,66 ----
+ /* Simple check that sibling calls are performed from a
+    void non-leaf-function taking no arguments calling a function which
+    is about the same as itself.
+
+    Copyright (C) 2002 Free Software Foundation Inc.
+    Contributed by Hans-Peter Nilsson  <hp@bitrange.com>  */
+
+ /* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* i370-*-* i960-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10?00-*-* ns32k-*-* s390*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
+ /* { dg-options "-O2 -foptimize-sibling-calls" } */
+
+ /* The option -foptimize-sibling-calls is the default, but serves as
+    marker.  This test is xfailed on targets without sibcall patterns
+    (except targets where the test does not work due to the return address
+    not saved on the regular stack).  */
+
+ static void recurser_void1 (void);
+ static void recurser_void2 (void);
+ extern void track (void);
+
+ int n = 0;
+ int main ()
+ {
+   recurser_void1 ();
+   exit (0);
+ }
+
+ /* The functions should get the same stack-frame, and best way to make it
+    reasonably sure is to make them have the same contents (regarding the
+    n tests).  */
+
+ static void
+ recurser_void1 (void)
+ {
+   if (n == 0 || n == 7 || n == 8)
+     track ();
+
+   if (n == 10)
+     return;
+   n++;
+   recurser_void2 ();
+ }
+
+ static void
+ recurser_void2 (void)
+ {
+   if (n == 0 || n == 7 || n == 8)
+     track ();
+
+   if (n == 10)
+     return;
+   n++;
+   recurser_void1 ();
+ }
+
+ void *trackpoint;
+
+ void
+ track ()
+ {
+   char stackpos[1];
+
+   if (n == 0)
+     trackpoint = stackpos;
+   else if ((n != 7 && n != 8) || trackpoint != stackpos)
+     abort ();
+ }

brgds, H-P



More information about the Gcc-patches mailing list