On 31/08/16 16:35, Eric Botcazou wrote:
> Hi,
> 
> this is a regression present on the mainline and 6 branch and introduced by:
> 
> 2014-04-25  Jiong Wang  <jiong.w...@arm.com>
> 
>       * config/arm/predicates.md (call_insn_operand): Add long_call check.
>       * config/arm/arm.md (sibcall, sibcall_value): Force the address to
>       reg for long_call.
>       * config/arm/arm.c (arm_function_ok_for_sibcall): Remove long_call
>       restriction.
> 
> For a longcall, any sibcall becomes an indirect sibcall and therefore 
> requires 
> a register to hold the target address.  Now if all the argument registers are 
>  
> taken, this register will be IP but, for APCS frames and VFP, IP can be used 
> in the sibcall epilogue to restore the VFP registers, so the target address 
> is 
> overwritten and the call goes astray.  Testcase attached, compile it with 
> e.g. 
> -mapcs-frame -mfloat-abi=soft -O -foptimize-sibling-calls -ffunction-sections
> and you'll see for arm-eabi:
> 
>       sub     ip, fp, #36
>       vldm    ip!, {d8}
>       sub     sp, fp, #28
>       ldmfd   sp, {r4, r5, r6, r7, fp, sp, lr}
>       bx      ip
> 
> The attached patch reinstates the restriction for APCS frames and VFP.  This 
> might be deemed a big hammer, but isn't a regression from earlier releases of 
> the compiler and APCS frames are deprecated in any case (we still support 
> them 
> for VxWorks 6 but VxWorks 7 switched to AAPCS).
> 
> Tested on ARM/VxWorks 6 and ARM/EABI, OK for mainline and 6 branch?
> 
> 

Since you're going to need a back-port there should be a PR filed for this.


> 2016-08-31  Eric Botcazou  <ebotca...@adacore.com>
> 
>         * config/arm/arm.c (arm_function_ok_for_sibcall): Add back restriction
>         for long calls with APCS frame and VFP.
> 
> 
> 2016-08-31  Eric Botcazou  <ebotca...@adacore.com>
> 
>       * gcc.target/arm/vfp-longcall-apcs.c: New test.
> 

Have you checked that this works with multi-lib dejagnu runs and on
hard-float systems?  I doubt this will work in armhf-linux, for example.

R.

> 
> p.diff
> 
> 
> Index: config/arm/arm.c
> ===================================================================
> --- config/arm/arm.c  (revision 239888)
> +++ config/arm/arm.c  (working copy)
> @@ -6773,6 +6773,14 @@ arm_function_ok_for_sibcall (tree decl, tree exp)
>    if (TARGET_VXWORKS_RTP && flag_pic && decl && !targetm.binds_local_p 
> (decl))
>      return false;
>  
> +  /* ??? Cannot tail-call to long calls with APCS frame and VFP, because IP
> +     may be used both as target of the call and base register for restoring
> +     the VFP registers  */
> +  if (TARGET_APCS_FRAME && TARGET_ARM
> +      && TARGET_HARD_FLOAT && TARGET_VFP
> +      && decl && arm_is_long_call_p (decl))
> +    return false;
> +
>    /* If we are interworking and the function is not declared static
>       then we can't tail-call it unless we know that it exists in this
>       compilation unit (since it might be a Thumb routine).  */
> 
> 
> vfp-longcall-apcs.c
> 
> 
> /* { dg-do run } */
> /* { dg-require-effective-target arm_vfp_ok } */
> /* { dg-options "-mapcs-frame -mfpu=vfp -mfloat-abi=softfp -O 
> -foptimize-sibling-calls -ffunction-sections" } */
> 
> extern void abort (void);
> 
> static __attribute__((noclone, noinline, long_call))
> int foo (int a, int b, int c, int d, double i)
> {
>   return a;
> }
> 
> static __attribute__((noclone, noinline))
> double baz (double i)
> {
>   return i;
> }
> 
> static __attribute__((noclone, noinline))
> int bar (int a, int b, int c, int d, double i, double j)
> {
>   double l = baz (i) * j;
>   return foo (a, b, c, d, l);
> }
> 
> int
> main (void)
> {
>   if (bar (0, 0, 0, 0, 0.0, 0.0) != 0)
>     abort ();
> 
>   return 0;
> }
> 

Reply via email to