Tree-level sibcalls & callee-copied arguments

Richard Sandiford rsandifo@redhat.com
Sun May 16 10:28:00 GMT 2004


After the tree-ssa merge, some structure-passing tests have started
failing when using the MIPS EABI.  The problem is that we're now
allowing sibcalls in functions like g1() and g2() below:

    struct s { int i, j, k; };
    void f (struct s);
    void g1 (void)
    {
      struct s s = { 1, 2, 3 };
      f (s);
    }
    void g2 (struct s s)
    {
      f (s);
    }

even though the structures being passed are in the caller's stack frame.
(Note that assign_parms() causes g2() to copy its argument unconditionally.
There's no code to detect when the copy is redundant.)

Caller-copied ABIs don't have this problem because
calls.c:initialize_argument_information() will set *may_tailcall to false.
It seems that we should do the same thing for callee-copied arguments
if the argument is in the current function's frame.  Unfortunately,
I don't really know how to check that.  Is there an easy way?

The patch below just tries to look for things in static storage,
assuming that X is in static storage if:

        DECL_P (x) && TREE_STATIC (x)

But again, I'm not sure whether this is the right or best condition.
Please suggest something better. ;)

After the patch, we still allow sibcalls for things like:

    void g3 (void)
    {
      f ((const struct s) { 1, 2, 3 });
    }

where the structure being passed is a static object in the read-only
data section.

This isn't directly related to the patch (same behaviour before and after),
but I notice that we pass the addresses of non-constant, non-local objects
directly.  E.g.:

    struct s gs;
    void g4 (void)
    {
      f (gs);
    }

will pass the address of gs to f().  OTOH, the documention for
FUNCTION_ARG_CALLEE_COPIES says:

    The called function must not modify this value.  If it can be
    determined that the value won't be modified, it need not make a copy;
    otherwise a copy must be made.

What happens if f() doesn't modify its argument, but does modify gs?
Is it supposed to copy the argument in that case?  It isn't really
clear to me from the documentation above.

Anyway, this won't cause problems with MIPS EABI because (a) I think
gcc is the only compiler to implement it and (b) as mentioned above,
gcc always copies the argument anyway.  Just thought I'd ask...

Patch tested on mips64vrel-elf with:

    {-march=vr4130}{-mabi=eabi}{-mgp32,-mgp64}{-mlong32,-mlong64}

Fixes several c-torture tests, no regressions.  OK to install,
or is there a better way?

Richard


	* calls.c (initialize_argument_information): Forbid sibcalls if a
	callee-copied argument is stored in the current function's frame.

Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.332
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.332 calls.c
*** calls.c	13 May 2004 06:39:30 -0000	1.332
--- calls.c	16 May 2004 07:25:14 -0000
*************** initialize_argument_information (int num
*** 1131,1136 ****
--- 1131,1143 ----
  		  && ! REG_P (DECL_RTL (TREE_OPERAND (args[i].tree_value, 1))))
  		args[i].tree_value = TREE_OPERAND (args[i].tree_value, 1);
  
+ 	      /* We can't use sibcalls if a callee-copied argument is stored
+ 		 in the current function's frame.  */
+ 	      if (!call_from_thunk_p
+ 		  && (!DECL_P (args[i].tree_value)
+ 		      || !TREE_STATIC (args[i].tree_value)))
+ 		*may_tailcall = false;
+ 
  	      args[i].tree_value = build1 (ADDR_EXPR,
  					   build_pointer_type (type),
  					   args[i].tree_value);



More information about the Gcc-patches mailing list