[Committed] S/390: PR 43635: Turn direct into indirect call for 31bit pic sibcall

Andreas Krebbel krebbel@linux.vnet.ibm.com
Tue Apr 20 09:23:00 GMT 2010


Hi,

building 32 bit pic code we have to care about calling via PLT for
sibcalls since the PLT entries will use register 12 (GOT pointer) when
linking with -shared.  Since r12 is call-saved sibling call
optimization has to be prevented in that case.  However it is always
safe to do an indirect call since the PLT slot is not used here.

In the testcase below we start with an indirect call and
s390_function_ok_for_siball correctly enables the optimization.
During RTL expansion the symbol ref is propagated into the call
turning it into a direct call.  Since that would be illegal due to the
potential r12 usage in the PLT slot we have to rewind that
optimization and force the address into a register.

Bootstrapped on s390 and s390x. No regressions.

Committed to mainline and 4.5. The testcase runs fine on 4.4

Bye,

-Andreas-


2010-04-20  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	PR target/43635
	* config/s390/s390.c (s390_emit_call): Turn direct into indirect
	calls for -fpic -m31 if they have been sibcall optimized.


2010-04-20  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	PR target/43635
	* gcc.c-torture/compile/pr43635.c: New testcase.


Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig
--- gcc/config/s390/s390.c
*************** s390_emit_call (rtx addr_location, rtx t
*** 9539,9549 ****
           replace the symbol itself with the PLT stub.  */
        if (flag_pic && !SYMBOL_REF_LOCAL_P (addr_location))
          {
! 	  addr_location = gen_rtx_UNSPEC (Pmode,
! 					  gen_rtvec (1, addr_location),
! 					  UNSPEC_PLT);
! 	  addr_location = gen_rtx_CONST (Pmode, addr_location);
! 	  plt_call = true;
          }
  
        /* Unless we can use the bras(l) insn, force the
--- 9539,9563 ----
           replace the symbol itself with the PLT stub.  */
        if (flag_pic && !SYMBOL_REF_LOCAL_P (addr_location))
          {
! 	  if (retaddr_reg != NULL_RTX)
! 	    {
! 	      addr_location = gen_rtx_UNSPEC (Pmode,
! 					      gen_rtvec (1, addr_location),
! 					      UNSPEC_PLT);
! 	      addr_location = gen_rtx_CONST (Pmode, addr_location);
! 	      plt_call = true;
! 	    }
! 	  else
! 	    /* For -fpic code the PLT entries might use r12 which is
! 	       call-saved.  Therefore we cannot do a sibcall when
! 	       calling directly using a symbol ref.  When reaching
! 	       this point we decided (in s390_function_ok_for_sibcall)
! 	       to do a sibcall for a function pointer but one of the
! 	       optimizers was able to get rid of the function pointer
! 	       by propagating the symbol ref into the call.  This
! 	       optimization is illegal for S/390 so we turn the direct
! 	       call into a indirect call again.  */
! 	    addr_location = force_reg (Pmode, addr_location);
          }
  
        /* Unless we can use the bras(l) insn, force the
Index: gcc/testsuite/gcc.c-torture/compile/pr43635.c
===================================================================
*** /dev/null
--- gcc/testsuite/gcc.c-torture/compile/pr43635.c
***************
*** 0 ****
--- 1,7 ----
+ extern void d (void);
+ 
+ void (*foo (void)) (float)
+ {
+   void (*(*x) (void)) (float) = d;
+   return (*x) ();
+ }



More information about the Gcc-patches mailing list