public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PATCH for sibcalls on i386
@ 2002-09-22 21:11 Andreas Bauer
  2002-09-23  3:03 ` Fergus Henderson
  2002-09-23 15:12 ` Richard Henderson
  0 siblings, 2 replies; 26+ messages in thread
From: Andreas Bauer @ 2002-09-22 21:11 UTC (permalink / raw)
  To: gcc-patches; +Cc: pizka, jason.ozolins

[-- Attachment #1: Type: text/plain, Size: 1722 bytes --]

Dear gcc hackers,

This patch is a follow-up to a discussion I had with several people on
the main gcc list not too long ago.

    (See also http://gcc.gnu.org/ml/gcc/2002-09/threads.html#00298)

I'm trying to make sibcall optimisation more general and I'm starting out
with the very common i386 platform.

Attached is a patch to gcc-3.2 that adds a few new call patterns to the
i386 machine description which allow sibcall optimisation for indirect
calls.  For example, it is possible to optimise the following code:

 extern int bar (int, int);
 void (*ptr) (int, int);
 void foo (int a, int b)
 {
   ptr = bar;
   return (*ptr) (a, b);
 }

Also, possible is:

 extern int bar (int, int);
 int (*ptr) (int, int);
 int foo (int a, int b)
 {
   ptr = bar;
   return (*ptr) (a, b);
 }

Etc.  I hope the idea is clear.

BRIEF OUTLINE:
--------------
I'm overriding the "fndecl == NULL_TREE" check in "calls.c" and cover it
in FUNCTION_OK_FOR_SIBCALL instead.  The macro will decide whether an
indirect call is a candidate for sibcall optimisation and if so, the
changed machine descriptions may be put into place at the end of
compilation.  Non-i386 architectures, however, still check for fndecl in
"calls.c", because they do not yet allow any indirect calls at all!  So,
the patch doesn't break anthing, as far as I know.

I'm aware that the patch is too small to actually make a huge difference
on gcc as a whole, but if the concept proves useful, then it could be
applied to other architectures as well and we could remove the test
"fndecl == NULL_TREE" totally from the file "calls.c".

However, it's a starting point and hopefully someone's able to give me
at least some feedback on this.

Thanks in advance,
Andreas.

[-- Attachment #2: sibcall_patch.diff --]
[-- Type: text/plain, Size: 7661 bytes --]

diff -r -b -w -B -d -p -c /home/baueran/Development/gcc-3.2/gcc/calls.c /home/baueran/Development/gcc-3.2-testing/gcc/calls.c
*** /home/baueran/Development/gcc-3.2/gcc/calls.c	Fri Apr  5 09:28:47 2002
--- /home/baueran/Development/gcc-3.2-testing/gcc/calls.c	Mon Sep 23 13:24:57 2002
*************** expand_call (exp, target, ignore)
*** 2455,2463 ****
  	 use a register class that is all call-clobbered.  Any
  	 reload insns generated to fix things up would appear
  	 before the sibcall_epilogue.  */
        || fndecl == NULL_TREE
        || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP))
!       || TREE_THIS_VOLATILE (fndecl)
        || !FUNCTION_OK_FOR_SIBCALL (fndecl)
        /* If this function requires more stack slots than the current
  	 function, we cannot change it into a sibling call.  */
--- 2455,2474 ----
  	 use a register class that is all call-clobbered.  Any
  	 reload insns generated to fix things up would appear
  	 before the sibcall_epilogue.  */
+ 
+       /* Additional call patterns in i386.md allow i386 to do
+ 	 optimized indirect calls.  Other platforms may/should
+ 	 follow this example.
+ 	 In fact, it is sufficient on i386 to merely test with the
+ 	 FUNCTION_OK_FOR_SIBCALL macro, as it contains certain
+ 	 conditionals for handling indirect calls.  */
+ 
+ #ifndef __i386
        || fndecl == NULL_TREE
+ #endif
+ 
        || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP))
!       || (fndecl != NULL_TREE && TREE_THIS_VOLATILE (fndecl))
        || !FUNCTION_OK_FOR_SIBCALL (fndecl)
        /* If this function requires more stack slots than the current
  	 function, we cannot change it into a sibling call.  */
diff -r -b -w -B -d -p -c /home/baueran/Development/gcc-3.2/gcc/config/i386/i386.c /home/baueran/Development/gcc-3.2-testing/gcc/config/i386/i386.c
*** /home/baueran/Development/gcc-3.2/gcc/config/i386/i386.c	Thu Aug  8 04:10:57 2002
--- /home/baueran/Development/gcc-3.2-testing/gcc/config/i386/i386.c	Mon Sep 23 13:27:11 2002
*************** static enum x86_64_reg_class merge_class
*** 822,827 ****
--- 822,865 ----
  
  struct gcc_target targetm = TARGET_INITIALIZER;
  \f
+ /* If PIC, we cannot make sibling calls to global functions
+    because the PLT requires %ebx live.
+    If we are returning floats on the register stack, we cannot make
+    sibling calls to functions that return floats.  (The stack adjust
+    instruction will wind up after the sibcall jump, and not be executed.) */
+ 
+ int
+ i386_function_ok_for_sibcall (decl, exp)
+      tree decl, exp;
+ {
+   /* Check whether it's legal to optimize this _direct_ call.  */
+   if (decl)
+     {
+       if ((! flag_pic || ! TREE_PUBLIC (decl))
+ 	  && (! TARGET_FLOAT_RETURNS_IN_80387
+ 	      || ! FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (decl))))
+ 	      || FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (cfun->decl))))))
+ 	return 1;
+     }
+   /* Check whether it's legal to optimize this _indirect_ call.  */
+   /* TODO: currently only 32 bit targets are supported by the machine
+            descriptions.  */
+   else
+     {
+       if (! TARGET_64BIT
+ 	  && (! flag_pic
+ 	      && (! TARGET_FLOAT_RETURNS_IN_80387
+ 		  || ! FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (exp)))
+ 		  || FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (cfun->decl)))))))
+ 	return 1;
+     }
+   
+   /* Function call can not be optimized.  */
+   warning ("function not ok for tail call optimization");
+ 
+   return 0;
+ }
+ 
  /* Sometimes certain combinations of command options do not make
     sense on a particular target machine.  You can define a macro
     `OVERRIDE_OPTIONS' to take account of this.  This macro, if
diff -r -b -w -B -d -p -c /home/baueran/Development/gcc-3.2/gcc/config/i386/i386.h /home/baueran/Development/gcc-3.2-testing/gcc/config/i386/i386.h
*** /home/baueran/Development/gcc-3.2/gcc/config/i386/i386.h	Mon Jul 15 16:54:36 2002
--- /home/baueran/Development/gcc-3.2-testing/gcc/config/i386/i386.h	Mon Sep 23 13:26:30 2002
*************** typedef struct ix86_args {
*** 1710,1726 ****
  
  #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
  
! /* If PIC, we cannot make sibling calls to global functions
!    because the PLT requires %ebx live.
!    If we are returning floats on the register stack, we cannot make
!    sibling calls to functions that return floats.  (The stack adjust
!    instruction will wind up after the sibcall jump, and not be executed.) */
! #define FUNCTION_OK_FOR_SIBCALL(DECL)					\
!   ((DECL)								\
!    && (! flag_pic || ! TREE_PUBLIC (DECL))				\
!    && (! TARGET_FLOAT_RETURNS_IN_80387					\
!        || ! FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (DECL))))	\
!        || FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (cfun->decl))))))
  
  /* Perform any needed actions needed for a function that is receiving a
     variable number of arguments.
--- 1710,1719 ----
  
  #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
  
! /* Conditions why sibcall optimization might fail as well as the function
!    to check, are defined in i386.c.  */
! 
! #define FUNCTION_OK_FOR_SIBCALL(DECL) i386_function_ok_for_sibcall (DECL, exp)
  
  /* Perform any needed actions needed for a function that is receiving a
     variable number of arguments.
diff -r -b -w -B -d -p -c /home/baueran/Development/gcc-3.2/gcc/config/i386/i386.md /home/baueran/Development/gcc-3.2-testing/gcc/config/i386/i386.md
*** /home/baueran/Development/gcc-3.2/gcc/config/i386/i386.md	Mon Jul 15 16:54:36 2002
--- /home/baueran/Development/gcc-3.2-testing/gcc/config/i386/i386.md	Mon Sep 23 13:28:25 2002
***************
*** 13573,13578 ****
--- 13573,13609 ----
  }
    [(set_attr "type" "call")])
  
+ (define_insn "*sibcall_0"
+   [(call (mem:QI (match_operand 0 "constant_call_address_operand" "s,c,d,a"))
+ 	 (match_operand 1 "" ""))]
+   "SIBLING_CALL_P (insn)"
+ {
+   if (SIBLING_CALL_P (insn))
+     return "jmp\t%P0";
+   else
+     return "call\t%P0";
+ }
+   [(set_attr "type" "call")])
+ 
+ (define_insn "*sibcall_1"
+   [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "s,c,d,a"))
+ 	 (match_operand 1 "" ""))]
+   "SIBLING_CALL_P (insn) && !TARGET_64BIT"
+ {
+   if (constant_call_address_operand (operands[0], QImode))
+     {
+       if (SIBLING_CALL_P (insn))
+ 	return "jmp\t%P0";
+       else
+ 	return "call\t%P0";
+     }
+   if (SIBLING_CALL_P (insn))
+     return "jmp\t%A0";
+   else
+     return "call\t%A0";
+ }
+   [(set_attr "type" "call")])
+ 
  (define_insn "*call_1"
    [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
  	 (match_operand 1 "" ""))]
***************
*** 17760,17765 ****
--- 17791,17828 ----
  }
    [(set_attr "type" "callv")])
  
+ (define_insn "*sibcall_value_0"
+   [(set (match_operand 0 "" "")
+ 	(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" "s,c,d,a"))
+ 	      (match_operand:SI 2 "" "")))]
+   "SIBLING_CALL_P (insn) && !TARGET_64BIT"
+ {
+   if (SIBLING_CALL_P (insn))
+     return "jmp\t%P1";
+   else
+     return "call\t%P1";
+ }
+   [(set_attr "type" "callv")])
+ 
+ (define_insn "*sibcall_value_1"
+   [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "s,c,d,a"))
+ 	 (match_operand 1 "" ""))]
+   "SIBLING_CALL_P (insn) && !TARGET_64BIT"
+ {
+   if (constant_call_address_operand (operands[0], QImode))
+     {
+       if (SIBLING_CALL_P (insn))
+ 	return "jmp\t%P0";
+       else
+ 	return "call\t%P0";
+     }
+   if (SIBLING_CALL_P (insn))
+     return "jmp\t%A0";
+   else
+     return "call\t%A0";
+ }
+   [(set_attr "type" "call")])
+ 
  (define_insn "*call_value_1"
    [(set (match_operand 0 "" "")
  	(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))

^ permalink raw reply	[flat|nested] 26+ messages in thread
* Re: PATCH for sibcalls on i386
@ 2002-09-30  9:21 John David Anglin
  2002-09-30 13:29 ` Hans-Peter Nilsson
  0 siblings, 1 reply; 26+ messages in thread
From: John David Anglin @ 2002-09-30  9:21 UTC (permalink / raw)
  To: gcc-patches

> Perhaps, in view of the comment,
> 
>         /* Sibcalls, stubs, and elf sections don't play well.  */
> 
> the macro should be named TARGET_HAS_STUBS_AND_ELF_SECTIONS
> rather than TARGET_PA_LINUX?

That seems reasonable.  Sibcalls are not ok on hppa64-hp-hpux* for
the same reason.  This was expressed as "! TARGET_64BIT" in the define
for FUNCTION_OK_FOR_SIBCALL in pa.h.  This should be changed to
use the above macro if the patch is approved.

All the new sibcall tests fail on hppa64-hp-hpux*.  The last two
fail on hppa-linux.  For sibcall-1.c, I see that the statement
"Self-recursion tail calls are optimized for all targets, regardless
of presence of sibcall patterns." is incorrect when it comes to
hppa64-hp-hpux*, although it does happen under hppa-linux.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6605)

^ permalink raw reply	[flat|nested] 26+ messages in thread
[parent not found: <no.id>]

end of thread, other threads:[~2002-09-30 21:03 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-22 21:11 PATCH for sibcalls on i386 Andreas Bauer
2002-09-23  3:03 ` Fergus Henderson
2002-09-23 12:25   ` Zack Weinberg
2002-09-23 16:52     ` Andreas Bauer
2002-09-23 17:10     ` Fergus Henderson
2002-09-23 21:27     ` Andreas Bauer
2002-09-23 21:37       ` Andrew Pinski
2002-09-23 21:44         ` Andreas Bauer
2002-09-23 21:48       ` Zack Weinberg
2002-09-23 22:14       ` Richard Henderson
2002-09-23 22:24       ` Richard Henderson
2002-09-24 22:24         ` Andreas Bauer
2002-09-24 23:28           ` Fergus Henderson
2002-09-25 16:47           ` Richard Henderson
2002-09-30  1:43             ` Andreas Bauer
2002-09-30  8:11               ` Fergus Henderson
2002-09-23 16:46   ` Andreas Bauer
2002-09-23 17:09     ` Richard Henderson
2002-09-23 15:12 ` Richard Henderson
2002-09-30  9:21 John David Anglin
2002-09-30 13:29 ` Hans-Peter Nilsson
2002-09-30 14:08   ` John David Anglin
2002-09-30 15:00     ` Hans-Peter Nilsson
2002-09-30 17:06     ` Richard Henderson
2002-09-30 17:44       ` John David Anglin
     [not found] <no.id>
2002-09-30 21:03 ` John David Anglin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).