diff options
-rw-r--r-- | gcc/ChangeLog | 28 | ||||
-rw-r--r-- | gcc/builtins.c | 27 | ||||
-rw-r--r-- | gcc/config/arc/arc.c | 24 | ||||
-rw-r--r-- | gcc/config/avr/avr.c | 16 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 14 | ||||
-rw-r--r-- | gcc/config/pa/pa.md | 7 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 12 | ||||
-rw-r--r-- | gcc/config/vax/vax.c | 10 | ||||
-rw-r--r-- | gcc/config/xtensa/xtensa.c | 2 | ||||
-rw-r--r-- | gcc/function.c | 2 | ||||
-rw-r--r-- | gcc/lra-eliminations.c | 92 | ||||
-rw-r--r-- | gcc/reload1.c | 90 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr84521.c | 53 |
14 files changed, 91 insertions, 291 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 922d1b5..b39712f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2019-06-19 Wilco Dijkstra <wdijkstr@arm.com> + + PR middle-end/84521 + * builtins.c (expand_builtin_setjmp_setup): Save + hard_frame_pointer_rtx. + (expand_builtin_setjmp_receiver): Do not emit sfp = fp move since we + restore fp. + * function.c (expand_function_start): Save hard_frame_pointer_rtx for + non-local goto. + * lra-eliminations.c (eliminate_regs_in_insn): Remove sfp = fp + elimination code. + (remove_reg_equal_offset_note): Remove unused function. + * reload1.c (eliminate_regs_in_insn): Remove sfp = hfp elimination + code. + * config/arc/arc.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove. + (arc_builtin_setjmp_frame_value): Remove function. + * config/avr/avr.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove. + (avr_builtin_setjmp_frame_value): Remove function. + * config/i386/i386.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove. + (ix86_builtin_setjmp_frame_value): Remove function. + * config/pa/pa.md (nonlocal_goto): Remove FP adjustment. + * config/sparc/sparc.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove. + (sparc_builtin_setjmp_frame_value): Remove function. + * config/vax/vax.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove. + (vax_builtin_setjmp_frame_value): Remove function. + * config/xtensa/xtensa.c (xtensa_frame_pointer_required): Force frame + pointer if has_nonlocal_label. + 2019-06-19 Jakub Jelinek <jakub@redhat.com> * doc/md.texi: Document vec_shl_<mode> pattern. diff --git a/gcc/builtins.c b/gcc/builtins.c index 3463ffb..4ecfd49 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -981,7 +981,7 @@ expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label) mem = gen_rtx_MEM (Pmode, buf_addr); set_mem_alias_set (mem, setjmp_alias_set); - emit_move_insn (mem, targetm.builtin_setjmp_frame_value ()); + emit_move_insn (mem, hard_frame_pointer_rtx); mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr, GET_MODE_SIZE (Pmode))), @@ -1023,31 +1023,6 @@ expand_builtin_setjmp_receiver (rtx receiver_label) if (chain && REG_P (chain)) emit_clobber (chain); - /* Now put in the code to restore the frame pointer, and argument - pointer, if needed. */ - if (! targetm.have_nonlocal_goto ()) - { - /* First adjust our frame pointer to its actual value. It was - previously set to the start of the virtual area corresponding to - the stacked variables when we branched here and now needs to be - adjusted to the actual hardware fp value. - - Assignments to virtual registers are converted by - instantiate_virtual_regs into the corresponding assignment - to the underlying register (fp in this case) that makes - the original assignment true. - So the following insn will actually be decrementing fp by - TARGET_STARTING_FRAME_OFFSET. */ - emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx); - - /* Restoring the frame pointer also modifies the hard frame pointer. - Mark it used (so that the previous assignment remains live once - the frame pointer is eliminated) and clobbered (to represent the - implicit update from the assignment). */ - emit_use (hard_frame_pointer_rtx); - emit_clobber (hard_frame_pointer_rtx); - } - if (!HARD_FRAME_POINTER_IS_ARG_POINTER && fixed_regs[ARG_POINTER_REGNUM]) { /* If the argument pointer can be eliminated in favor of the diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 2a530de..89f69c79 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -689,8 +689,6 @@ static rtx arc_legitimize_address_0 (rtx, rtx, machine_mode mode); #undef TARGET_MODES_TIEABLE_P #define TARGET_MODES_TIEABLE_P arc_modes_tieable_p -#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE -#define TARGET_BUILTIN_SETJMP_FRAME_VALUE arc_builtin_setjmp_frame_value /* Try to keep the (mov:DF _, reg) as early as possible so that the d<add/sub/mul>h-lr insns appear together and can @@ -10960,28 +10958,6 @@ compact_memory_operand_p (rtx op, machine_mode mode, return false; } -/* Return the frame pointer value to be backed up in the setjmp buffer. */ - -static rtx -arc_builtin_setjmp_frame_value (void) -{ - /* We always want to preserve whatever value is currently in the frame - pointer register. For frames that are using the frame pointer the new - value of the frame pointer register will have already been computed - (as part of the prologue). For frames that are not using the frame - pointer it is important that we backup whatever value is in the frame - pointer register, as earlier (more outer) frames may have placed a - value into the frame pointer register. It might be tempting to try - and use `frame_pointer_rtx` here, however, this is not what we want. - For frames that are using the frame pointer this will give the - correct value. However, for frames that are not using the frame - pointer this will still give the value that _would_ have been the - frame pointer value for this frame (if the use of the frame pointer - had not been removed). We really do want the raw frame pointer - register value. */ - return gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM); -} - /* Return nonzero if a jli call should be generated for a call from the current function to DECL. */ diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index a9f72b3..f3896f7 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -1302,22 +1302,6 @@ avr_build_builtin_va_list (void) } -/* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */ -/* Actual start of frame is virtual_stack_vars_rtx this is offset from - frame pointer by +TARGET_STARTING_FRAME_OFFSET. - Using saved frame = virtual_stack_vars_rtx - TARGET_STARTING_FRAME_OFFSET - avoids creating add/sub of offset in nonlocal goto and setjmp. */ - -static rtx -avr_builtin_setjmp_frame_value (void) -{ - rtx xval = gen_reg_rtx (Pmode); - emit_insn (gen_subhi3 (xval, virtual_stack_vars_rtx, - gen_int_mode (avr_starting_frame_offset (), Pmode))); - return xval; -} - - /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC). This is return address of function. */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 76ac5bb..649a7e4 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5788,17 +5788,6 @@ ix86_initial_elimination_offset (int from, int to) } } -/* In a dynamically-aligned function, we can't know the offset from - stack pointer to frame pointer, so we must ensure that setjmp - eliminates fp against the hard fp (%ebp) rather than trying to - index from %esp up to the top of the frame across a gap that is - of unknown (at compile-time) size. */ -static rtx -ix86_builtin_setjmp_frame_value (void) -{ - return stack_realign_fp ? hard_frame_pointer_rtx : virtual_stack_vars_rtx; -} - /* Emits a warning for unsupported msabi to sysv pro/epilogues. */ void warn_once_call_ms2sysv_xlogues (const char *feature) { @@ -22767,9 +22756,6 @@ ix86_run_selftests (void) #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG ix86_reorg -#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE -#define TARGET_BUILTIN_SETJMP_FRAME_VALUE ix86_builtin_setjmp_frame_value - #undef TARGET_BUILD_BUILTIN_VA_LIST #define TARGET_BUILD_BUILTIN_VA_LIST ix86_build_builtin_va_list diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 84630ad..a568e79 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -6909,10 +6909,7 @@ 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. */ + /* Restore the stack and frame pointers. */ fp = copy_to_reg (fp); emit_stack_restore (SAVE_NONLOCAL, stack); @@ -6920,7 +6917,7 @@ 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_move_insn (hard_frame_pointer_rtx, fp); emit_use (hard_frame_pointer_rtx); emit_use (stack_pointer_rtx); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 6d52f83..0227a53 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -679,7 +679,6 @@ static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; static void sparc_file_end (void); static bool sparc_frame_pointer_required (void); static bool sparc_can_eliminate (const int, const int); -static rtx sparc_builtin_setjmp_frame_value (void); static void sparc_conditional_register_usage (void); static bool sparc_use_pseudo_pic_reg (void); static void sparc_init_pic_reg (void); @@ -878,9 +877,6 @@ char sparc_hard_reg_printed[8]; #undef TARGET_FRAME_POINTER_REQUIRED #define TARGET_FRAME_POINTER_REQUIRED sparc_frame_pointer_required -#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE -#define TARGET_BUILTIN_SETJMP_FRAME_VALUE sparc_builtin_setjmp_frame_value - #undef TARGET_CAN_ELIMINATE #define TARGET_CAN_ELIMINATE sparc_can_eliminate @@ -13003,14 +12999,6 @@ sparc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) return to == HARD_FRAME_POINTER_REGNUM || !sparc_frame_pointer_required (); } -/* Return the hard frame pointer directly to bypass the stack bias. */ - -static rtx -sparc_builtin_setjmp_frame_value (void) -{ - return hard_frame_pointer_rtx; -} - /* If !TARGET_FPU, then make the fp registers and fp cc regs fixed so that they won't be allocated. */ diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c index 547a7e0..9559ffb 100644 --- a/gcc/config/vax/vax.c +++ b/gcc/config/vax/vax.c @@ -59,7 +59,6 @@ static rtx vax_function_arg (cumulative_args_t, machine_mode, static void vax_function_arg_advance (cumulative_args_t, machine_mode, const_tree, bool); static rtx vax_struct_value_rtx (tree, int); -static rtx vax_builtin_setjmp_frame_value (void); static void vax_asm_trampoline_template (FILE *); static void vax_trampoline_init (rtx, tree, rtx); static poly_int64 vax_return_pops_args (tree, tree, poly_int64); @@ -99,9 +98,6 @@ static HOST_WIDE_INT vax_starting_frame_offset (void); #undef TARGET_STRUCT_VALUE_RTX #define TARGET_STRUCT_VALUE_RTX vax_struct_value_rtx -#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE -#define TARGET_BUILTIN_SETJMP_FRAME_VALUE vax_builtin_setjmp_frame_value - #undef TARGET_LRA_P #define TARGET_LRA_P hook_bool_void_false @@ -1067,12 +1063,6 @@ vax_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, return gen_rtx_REG (Pmode, VAX_STRUCT_VALUE_REGNUM); } -static rtx -vax_builtin_setjmp_frame_value (void) -{ - return hard_frame_pointer_rtx; -} - /* Worker function for NOTICE_UPDATE_CC. */ void diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index ee56124..2b97fa2 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -2739,7 +2739,7 @@ xtensa_frame_pointer_required (void) This seems wrong but maybe it's necessary for other architectures. This function is derived from the i386 code. */ - if (cfun->machine->accesses_prev_frame) + if (cfun->machine->accesses_prev_frame || cfun->has_nonlocal_label) return true; return false; diff --git a/gcc/function.c b/gcc/function.c index 45b65dc..a957679 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -5135,7 +5135,7 @@ expand_function_start (tree subr) r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE); gcc_assert (GET_MODE (r_save) == Pmode); - emit_move_insn (r_save, targetm.builtin_setjmp_frame_value ()); + emit_move_insn (r_save, hard_frame_pointer_rtx); update_nonlocal_goto_save_area (); } diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c index ee9fd51..fa0ebcd 100644 --- a/gcc/lra-eliminations.c +++ b/gcc/lra-eliminations.c @@ -876,32 +876,6 @@ mark_not_eliminable (rtx x, machine_mode mem_mode) -#ifdef HARD_FRAME_POINTER_REGNUM - -/* Search INSN's reg notes to see whether the destination is equal to - WHAT + C for some constant C. Return true if so, storing C in - *OFFSET_OUT and removing the reg note. */ -static bool -remove_reg_equal_offset_note (rtx_insn *insn, rtx what, poly_int64 *offset_out) -{ - rtx link, *link_loc; - - for (link_loc = ®_NOTES (insn); - (link = *link_loc) != NULL_RTX; - link_loc = &XEXP (link, 1)) - if (REG_NOTE_KIND (link) == REG_EQUAL - && GET_CODE (XEXP (link, 0)) == PLUS - && XEXP (XEXP (link, 0), 0) == what - && poly_int_rtx_p (XEXP (XEXP (link, 0), 1), offset_out)) - { - *link_loc = XEXP (link, 1); - return true; - } - return false; -} - -#endif - /* Scan INSN and eliminate all eliminable hard registers in it. If REPLACE_P is true, do the replacement destructively. Also @@ -939,72 +913,6 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p, return; } - /* Check for setting an eliminable register. */ - if (old_set != 0 && REG_P (SET_DEST (old_set)) - && (ep = get_elimination (SET_DEST (old_set))) != NULL) - { - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate) - { - bool delete_p = replace_p; - -#ifdef HARD_FRAME_POINTER_REGNUM - if (ep->from == FRAME_POINTER_REGNUM - && ep->to == HARD_FRAME_POINTER_REGNUM) - /* If this is setting the frame pointer register to the - hardware frame pointer register and this is an - elimination that will be done (tested above), this - insn is really adjusting the frame pointer downward - to compensate for the adjustment done before a - nonlocal goto. */ - { - rtx src = SET_SRC (old_set); - poly_int64 offset = 0; - - /* We should never process such insn with non-zero - UPDATE_SP_OFFSET. */ - lra_assert (known_eq (update_sp_offset, 0)); - - if (remove_reg_equal_offset_note (insn, ep->to_rtx, &offset) - || strip_offset (src, &offset) == ep->to_rtx) - { - if (replace_p) - { - SET_DEST (old_set) = ep->to_rtx; - lra_update_insn_recog_data (insn); - return; - } - offset -= (ep->offset - ep->previous_offset); - src = plus_constant (Pmode, ep->to_rtx, offset); - - /* First see if this insn remains valid when we - make the change. If not, keep the INSN_CODE - the same and let the constraint pass fit it - up. */ - validate_change (insn, &SET_SRC (old_set), src, 1); - validate_change (insn, &SET_DEST (old_set), - ep->from_rtx, 1); - if (! apply_change_group ()) - { - SET_SRC (old_set) = src; - SET_DEST (old_set) = ep->from_rtx; - } - lra_update_insn_recog_data (insn); - /* Add offset note for future updates. */ - add_reg_note (insn, REG_EQUAL, copy_rtx (src)); - return; - } - } -#endif - - /* This insn isn't serving a useful purpose. We delete it - when REPLACE is set. */ - if (delete_p) - lra_delete_dead_insn (insn); - return; - } - } - /* We allow one special case which happens to work on all machines we currently support: a single set with the source or a REG_EQUAL note being a PLUS of an eliminable register and a constant. */ diff --git a/gcc/reload1.c b/gcc/reload1.c index 5039cee..3ad6f1d 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -3234,96 +3234,6 @@ eliminate_regs_in_insn (rtx_insn *insn, int replace) return 0; } - if (old_set != 0 && REG_P (SET_DEST (old_set)) - && REGNO (SET_DEST (old_set)) < FIRST_PSEUDO_REGISTER) - { - /* Check for setting an eliminable register. */ - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate) - { - /* If this is setting the frame pointer register to the - hardware frame pointer register and this is an elimination - that will be done (tested above), this insn is really - adjusting the frame pointer downward to compensate for - the adjustment done before a nonlocal goto. */ - if (!HARD_FRAME_POINTER_IS_FRAME_POINTER - && ep->from == FRAME_POINTER_REGNUM - && ep->to == HARD_FRAME_POINTER_REGNUM) - { - rtx base = SET_SRC (old_set); - rtx_insn *base_insn = insn; - HOST_WIDE_INT offset = 0; - - while (base != ep->to_rtx) - { - rtx_insn *prev_insn; - rtx prev_set; - - if (GET_CODE (base) == PLUS - && CONST_INT_P (XEXP (base, 1))) - { - offset += INTVAL (XEXP (base, 1)); - base = XEXP (base, 0); - } - else if ((prev_insn = prev_nonnote_insn (base_insn)) != 0 - && (prev_set = single_set (prev_insn)) != 0 - && rtx_equal_p (SET_DEST (prev_set), base)) - { - base = SET_SRC (prev_set); - base_insn = prev_insn; - } - else - break; - } - - if (base == ep->to_rtx) - { - rtx src = plus_constant (Pmode, ep->to_rtx, - offset - ep->offset); - - new_body = old_body; - if (! replace) - { - new_body = copy_insn (old_body); - if (REG_NOTES (insn)) - REG_NOTES (insn) = copy_insn_1 (REG_NOTES (insn)); - } - PATTERN (insn) = new_body; - old_set = single_set (insn); - - /* First see if this insn remains valid when we - make the change. If not, keep the INSN_CODE - the same and let reload fit it up. */ - validate_change (insn, &SET_SRC (old_set), src, 1); - validate_change (insn, &SET_DEST (old_set), - ep->to_rtx, 1); - if (! apply_change_group ()) - { - SET_SRC (old_set) = src; - SET_DEST (old_set) = ep->to_rtx; - } - - val = 1; - goto done; - } - } - - /* In this case this insn isn't serving a useful purpose. We - will delete it in reload_as_needed once we know that this - elimination is, in fact, being done. - - If REPLACE isn't set, we can't delete this insn, but needn't - process it since it won't be used unless something changes. */ - if (replace) - { - delete_dead_insn (insn); - return 1; - } - val = 1; - goto done; - } - } - /* We allow one special case which happens to work on all machines we currently support: a single set with the source or a REG_EQUAL note being a PLUS of an eliminable register and a constant. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 63711af..4247335 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-06-19 Wilco Dijkstra <wdijkstr@arm.com> + + PR middle-end/84521 + * gcc.c-torture/execute/pr84521.c: New test. + 2019-06-19 Jakub Jelinek <jakub@redhat.com> * gcc.dg/vect/vect-simd-8.c: If main is defined, don't include diff --git a/gcc/testsuite/gcc.c-torture/execute/pr84521.c b/gcc/testsuite/gcc.c-torture/execute/pr84521.c new file mode 100644 index 0000000..08d1a9e --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr84521.c @@ -0,0 +1,53 @@ +/* { dg-require-effective-target indirect_jumps } */ +/* { dg-additional-options "-fomit-frame-pointer -fno-inline" } */ + +extern void abort (void); + +void +broken_longjmp (void *p) +{ + __builtin_longjmp (p, 1); +} + +volatile int x = 256; +void *volatile p = (void*)&x; +void *volatile p1; + +void +test (void) +{ + void *buf[5]; + void *volatile q = p; + + if (!__builtin_setjmp (buf)) + broken_longjmp (buf); + + /* Fails if stack pointer corrupted. */ + if (p != q) + abort (); +} + +void +test2 (void) +{ + void *volatile q = p; + p1 = __builtin_alloca (x); + test (); + + /* Fails if frame pointer corrupted. */ + if (p != q) + abort (); +} + +int +main (void) +{ + void *volatile q = p; + test (); + test2 (); + /* Fails if stack pointer corrupted. */ + if (p != q) + abort (); + + return 0; +} |