The attached change fixes PR middle-end/64242 on hppa. The nonlocal_goto and builtin_longjmp expanders are reworked to restore the frame pointer last. Clobbers and a blockage are added to ensure the restored frame pointer is not used to restore the stack pointer and the branch address.
Tested on hppa-unknown-linux-gnu and hppa2.0w-hp-hpux11.11. Committed to trunk. Dave -- John David Anglin dave.ang...@bell.net 2019-06-16 John David Anglin <dang...@gcc.gnu.org> PR middle-end/64242 * config/pa/pa.md (nonlocal_goto): Restore frame pointer last. Add frame clobbers and schedule block. (builtin_longjmp): Likewise. Index: config/pa/pa.md =================================================================== --- config/pa/pa.md (revision 272327) +++ config/pa/pa.md (working copy) @@ -6904,21 +6904,24 @@ rtx stack = operands[2]; rtx fp = operands[3]; - lab = copy_to_reg (lab); - emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); - /* Restore the frame pointer. The virtual_stack_vars_rtx is saved - instead of the hard_frame_pointer_rtx in the save area. As a - result, an extra instruction is needed to adjust for the offset + lab = copy_to_reg (lab); + + /* Restore the stack and frame pointers. The virtual_stack_vars_rtx + is saved instead of the hard_frame_pointer_rtx in the save area. + As a result, an extra instruction is needed to adjust for the offset of the virtual stack variables and the hard frame pointer. */ - if (GET_CODE (fp) != REG) - fp = force_reg (Pmode, fp); + fp = copy_to_reg (fp); + emit_stack_restore (SAVE_NONLOCAL, stack); + + /* Ensure the frame pointer move is not optimized. */ + emit_insn (gen_blockage ()); + emit_clobber (hard_frame_pointer_rtx); + emit_clobber (frame_pointer_rtx); emit_move_insn (hard_frame_pointer_rtx, plus_constant (Pmode, fp, -8)); - emit_stack_restore (SAVE_NONLOCAL, stack); - emit_use (hard_frame_pointer_rtx); emit_use (stack_pointer_rtx); @@ -8695,23 +8698,26 @@ emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); - /* Restore the frame pointer. The virtual_stack_vars_rtx is saved - instead of the hard_frame_pointer_rtx in the save area. We need - to adjust for the offset between these two values. */ - if (GET_CODE (fp) != REG) - fp = force_reg (Pmode, fp); + /* Load the label we are jumping through into r1 so that we know + where to look for it when we get back to setjmp's function for + restoring the gp. */ + emit_move_insn (pv, lab); + + /* Restore the stack and frame pointers. The virtual_stack_vars_rtx + is saved instead of the hard_frame_pointer_rtx in the save area. + We need to adjust for the offset between these two values. */ + fp = copy_to_reg (fp); + emit_stack_restore (SAVE_NONLOCAL, stack); + + /* Ensure the frame pointer move is not optimized. */ + emit_insn (gen_blockage ()); + emit_clobber (hard_frame_pointer_rtx); + emit_clobber (frame_pointer_rtx); emit_move_insn (hard_frame_pointer_rtx, plus_constant (Pmode, fp, -8)); - /* This bit is the same as expand_builtin_longjmp. */ - emit_stack_restore (SAVE_NONLOCAL, stack); emit_use (hard_frame_pointer_rtx); emit_use (stack_pointer_rtx); - /* Load the label we are jumping through into r1 so that we know - where to look for it when we get back to setjmp's function for - restoring the gp. */ - emit_move_insn (pv, lab); - /* Prevent the insns above from being scheduled into the delay slot of the interspace jump because the space register could change. */ emit_insn (gen_blockage ());