On 17/10/14 09:21, Eric Botcazou wrote:
> Hi,
> 
> some OSes, for example VxWorks 6, still use DWARF unwinding on the ARM, which 
> means that they use __builtin_eh_return (EABI unwinding doesn't).  The 
> builtin 
> is implemented by means of {arm|thumb}_set_return_address, which can generate 
> a store if LR has been stored on function entry.  The problem is that, if 
> this 
> store is FP-based, it is not seen by the RTL DSE pass as being consumed by 
> the 
> SP-based load at the same address on function exit.
> 
> That's by design in the RTL DSE pass: FP and SP are never substituted for 
> each 
> other by cselib, see for example this comment:
> 
>             /* The only thing that we are not willing to do (this
>                is requirement of dse and if others potential uses
>                need this function we should add a parm to control
>                it) is that we will not substitute the
>                STACK_POINTER_REGNUM, FRAME_POINTER or the
>                HARD_FRAME_POINTER.
> 
>                These expansions confuses the code that notices that
>                stores into the frame go dead at the end of the
>                function and that the frame is not effected by calls
>                to subroutines.  If you allow the
>                STACK_POINTER_REGNUM substitution, then dse will
>                think that parameter pushing also goes dead which is
>                wrong.  If you allow the FRAME_POINTER or the
>                HARD_FRAME_POINTER then you lose the opportunity to
>                make the frame assumptions.  */
>             if (regno == STACK_POINTER_REGNUM
>                 || regno == FRAME_POINTER_REGNUM
>                 || regno == HARD_FRAME_POINTER_REGNUM
>                 || regno == cfa_base_preserved_regno)
>               return orig;
> 
> so a FP-based store and a SP-based load are never seen as a RAW dependency.
> 
> This nevertheless used to work because the blockage insn emitted by the RTL 
> epilogue was acting as a "wild load" but this got broken by Richard's patch:
> 
> 2014-03-11  Richard Sandiford  <rdsandif...@googlemail.com>
> 
>       * builtins.c (expand_builtin_setjmp_receiver): Use and clobber
>       hard_frame_pointer_rtx.
>       * cse.c (cse_insn): Remove volatile check.
>       * cselib.c (cselib_process_insn): Likewise.
>       * dse.c (scan_insn): Likewise.
> 
> which removed the "wild load" trick.  This is visible at -O2 for:
> 
> void
> foo (void *c1, void *t1, void *ra)
> {
>     long offset = uw_install_context_1 (c1, t1);
>     void *handler = __builtin_frob_return_addr (ra);
>     __builtin_unwind_init ();
>     __builtin_eh_return (offset, handler);
> }
> 
> The attached patch fixes the breakage by marking the stores as frame related.
> 
> Tested on ARM/VxWorks, OK for mainline and 4.9 branch?
> 
> 
> 2014-10-17  Eric Botcazou  <ebotca...@adacore.com>
> 
>       * config/arm/arm.c (arm_set_return_address): Mark the store as frame
>       related, if any.
>       (thumb_set_return_address): Likewise.
> 
> 

OK.

R.

> 
> arm_eh_return-2.diff
> 
> 
> Index: config/arm/arm.c
> ===================================================================
> --- config/arm/arm.c  (revision 216252)
> +++ config/arm/arm.c  (working copy)
> @@ -28952,7 +28952,11 @@ arm_set_return_address (rtx source, rtx
>  
>         addr = plus_constant (Pmode, addr, delta);
>       }
> -      emit_move_insn (gen_frame_mem (Pmode, addr), source);
> +      /* The store needs to be marked as frame related in order to prevent
> +      DSE from deleting it as dead if it is based on fp.  */
> +      rtx insn = emit_move_insn (gen_frame_mem (Pmode, addr), source);
> +      RTX_FRAME_RELATED_P (insn) = 1;
> +      add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (Pmode, LR_REGNUM));
>      }
>  }
>  
> @@ -29004,7 +29008,11 @@ thumb_set_return_address (rtx source, rt
>        else
>       addr = plus_constant (Pmode, addr, delta);
>  
> -      emit_move_insn (gen_frame_mem (Pmode, addr), source);
> +      /* The store needs to be marked as frame related in order to prevent
> +      DSE from deleting it as dead if it is based on fp.  */
> +      rtx insn = emit_move_insn (gen_frame_mem (Pmode, addr), source);
> +      RTX_FRAME_RELATED_P (insn) = 1;
> +      add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (Pmode, LR_REGNUM));
>      }
>    else
>      emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
> 


Reply via email to