This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: Add new (ARM) sibcall test case


Hi Guys,

  I would like permission to add a new test case to
  gcc.c-torture/execute:

*** /dev/null	Sat Oct 19 15:41:17 2002
--- gcc/testsuite/gcc.c-torture/execute/20030117-1.c	Fri Jan 17 13:49:15 2003
***************
*** 0 ****
--- 1,23 ----
+ int foo (int, int, int);
+ int bar (int, int, int);
+ 
+ int main (void)
+ {
+   if (foo (5, 10, 21) != 12)
+     abort ();
+ 
+   if (bar (9, 12, 15) != 150)
+     abort ();
+ 
+   exit (0);
+ }
+ 
+ int foo (int x, int y, int z)
+ {
+   return (x + y + z) / 3;
+ }
+ 
+ int bar (int x, int y, int z)
+ {
+   return foo (x * x, y * y, z * z);
+ }

  The test reveals a bug in the ARM code generator when the program is
  compiled at -O3.  The problem is that gcc decides to compile 'bar'
  using a sibcall to 'foo', but it elects to use the link register as
  a temporary register for the result of one of the multiplications:

    bar:
	mul	ip, r1, r1
	mov	r1, ip
	mul	lr, r0, r0      <--- return address corrupted here
	mul	ip, r2, r2
	mov	r0, lr
	mov	r2, ip
	b	foo

  The problem is that although the "sibcall_epilogue" pattern
  generates an unspec_volatile, this only generates a USE of all of
  the hardware registers.  After reload, USEs are ignored, so the
  second flow pass marks the link register as dead after the
  prologue, and hence available for use in the body of the function.

  The solution I intend to apply is to add an unspec usage of the link
  register, using the UNSPEC_PROLOGUE_USE value, which is specifically
  intended to protect hard registers after reload.  Like this:

Index: gcc/config/arm/arm.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.md,v
retrieving revision 1.115
diff -c -3 -p -w -r1.115 arm.md
*** gcc/config/arm/arm.md	8 Jan 2003 11:55:50 -0000	1.115
--- gcc/config/arm/arm.md	17 Jan 2003 13:45:13 -0000
***************
*** 8430,8437 ****
    "
  )
  
  (define_insn "sibcall_epilogue"
!   [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
    "TARGET_ARM"
    "*
    if (USE_RETURN_INSN (FALSE))
--- 8430,8443 ----
    "
  )
  
+ ;; Note - although unspec_volatile's USE all hard registers,
+ ;; USEs are ignored after relaod has completed.  Thus we need
+ ;; to add an unspec of the link register to ensure that flow
+ ;; does not think that it is unused by the sibcall branch that
+ ;; will replace the standard function epilogue.
  (define_insn "sibcall_epilogue"
!   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
!               (unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)])]
    "TARGET_ARM"
    "*
    if (USE_RETURN_INSN (FALSE))

  So - may I add this test case ?

Cheers
        Nick

PS. Relevent ChangeLog entries:

gcc/testsuite/ChangeLog
2003-01-17  Nick Clifton  <nickc@redhat.com>

	* gcc.c-torture/execute/20030117-1.c: New test case.  Exposes
	problem with ARM sibcall code generation.

gcc/ChangeLog
2003-01-17  Nick Clifton  <nickc@redhat.com>

	* config/arm/arm.md (sibcall_epilogue): Add an
	UNSPEC_PROLOGUE_USE to prevent the link register from being
	considered dead.



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]