diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 143 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr59501-4a.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81769-1a.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81769-1b.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81769-2.c | 21 |
7 files changed, 157 insertions, 56 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2f6983f..fa34e13 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-09-05 H.J. Lu <hongjiu.lu@intel.com> + + PR target/59501 + PR target/81624 + PR target/81769 + * config/i386/i386.c (ix86_finalize_stack_frame_flags): Don't + realign stack if stack alignment needed is less than incoming + stack boundary. + 2017-09-05 Marek Polacek <polacek@redhat.com> PR sanitizer/82072 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 6fdc9fd..7406451 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -14303,6 +14303,11 @@ ix86_finalize_stack_frame_flags (void) add_to_hard_reg_set (&set_up_by_prologue, Pmode, ARG_POINTER_REGNUM); add_to_hard_reg_set (&set_up_by_prologue, Pmode, HARD_FRAME_POINTER_REGNUM); + + /* The preferred stack alignment is the minimum stack alignment. */ + unsigned int stack_alignment = crtl->preferred_stack_boundary; + bool require_stack_frame = false; + FOR_EACH_BB_FN (bb, cfun) { rtx_insn *insn; @@ -14311,79 +14316,107 @@ ix86_finalize_stack_frame_flags (void) && requires_stack_frame_p (insn, prologue_used, set_up_by_prologue)) { - if (crtl->stack_realign_needed != stack_realign) - recompute_frame_layout_p = true; - crtl->stack_realign_needed = stack_realign; - crtl->stack_realign_finalized = true; - if (recompute_frame_layout_p) - ix86_compute_frame_layout (); - return; + require_stack_frame = true; + + if (stack_realign) + { + /* Find the maximum stack alignment. */ + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL) + if (MEM_P (*iter) + && (reg_mentioned_p (stack_pointer_rtx, + *iter) + || reg_mentioned_p (frame_pointer_rtx, + *iter))) + { + unsigned int alignment = MEM_ALIGN (*iter); + if (alignment > stack_alignment) + stack_alignment = alignment; + } + } } } - /* If drap has been set, but it actually isn't live at the start - of the function, there is no reason to set it up. */ - if (crtl->drap_reg) + if (require_stack_frame) { - basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; - if (! REGNO_REG_SET_P (DF_LR_IN (bb), REGNO (crtl->drap_reg))) + /* Stack frame is required. If stack alignment needed is less + than incoming stack boundary, don't realign stack. */ + stack_realign = incoming_stack_boundary < stack_alignment; + if (!stack_realign) { - crtl->drap_reg = NULL_RTX; - crtl->need_drap = false; + crtl->max_used_stack_slot_alignment + = incoming_stack_boundary; + crtl->stack_alignment_needed + = incoming_stack_boundary; } } else - cfun->machine->no_drap_save_restore = true; - - frame_pointer_needed = false; - stack_realign = false; - crtl->max_used_stack_slot_alignment = incoming_stack_boundary; - crtl->stack_alignment_needed = incoming_stack_boundary; - crtl->stack_alignment_estimated = incoming_stack_boundary; - if (crtl->preferred_stack_boundary > incoming_stack_boundary) - crtl->preferred_stack_boundary = incoming_stack_boundary; - df_finish_pass (true); - df_scan_alloc (NULL); - df_scan_blocks (); - df_compute_regs_ever_live (true); - df_analyze (); - - if (flag_var_tracking) { - /* Since frame pointer is no longer available, replace it with - stack pointer - UNITS_PER_WORD in debug insns. */ - df_ref ref, next; - for (ref = DF_REG_USE_CHAIN (HARD_FRAME_POINTER_REGNUM); - ref; ref = next) + /* If drap has been set, but it actually isn't live at the + start of the function, there is no reason to set it up. */ + if (crtl->drap_reg) { - rtx_insn *insn = DF_REF_INSN (ref); - /* Make sure the next ref is for a different instruction, - so that we're not affected by the rescan. */ - next = DF_REF_NEXT_REG (ref); - while (next && DF_REF_INSN (next) == insn) - next = DF_REF_NEXT_REG (next); - - if (DEBUG_INSN_P (insn)) + basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; + if (! REGNO_REG_SET_P (DF_LR_IN (bb), + REGNO (crtl->drap_reg))) + { + crtl->drap_reg = NULL_RTX; + crtl->need_drap = false; + } + } + else + cfun->machine->no_drap_save_restore = true; + + frame_pointer_needed = false; + stack_realign = false; + crtl->max_used_stack_slot_alignment = incoming_stack_boundary; + crtl->stack_alignment_needed = incoming_stack_boundary; + crtl->stack_alignment_estimated = incoming_stack_boundary; + if (crtl->preferred_stack_boundary > incoming_stack_boundary) + crtl->preferred_stack_boundary = incoming_stack_boundary; + df_finish_pass (true); + df_scan_alloc (NULL); + df_scan_blocks (); + df_compute_regs_ever_live (true); + df_analyze (); + + if (flag_var_tracking) + { + /* Since frame pointer is no longer available, replace it with + stack pointer - UNITS_PER_WORD in debug insns. */ + df_ref ref, next; + for (ref = DF_REG_USE_CHAIN (HARD_FRAME_POINTER_REGNUM); + ref; ref = next) { - bool changed = false; - for (; ref != next; ref = DF_REF_NEXT_REG (ref)) + rtx_insn *insn = DF_REF_INSN (ref); + /* Make sure the next ref is for a different instruction, + so that we're not affected by the rescan. */ + next = DF_REF_NEXT_REG (ref); + while (next && DF_REF_INSN (next) == insn) + next = DF_REF_NEXT_REG (next); + + if (DEBUG_INSN_P (insn)) { - rtx *loc = DF_REF_LOC (ref); - if (*loc == hard_frame_pointer_rtx) + bool changed = false; + for (; ref != next; ref = DF_REF_NEXT_REG (ref)) { - *loc = plus_constant (Pmode, - stack_pointer_rtx, - -UNITS_PER_WORD); - changed = true; + rtx *loc = DF_REF_LOC (ref); + if (*loc == hard_frame_pointer_rtx) + { + *loc = plus_constant (Pmode, + stack_pointer_rtx, + -UNITS_PER_WORD); + changed = true; + } } + if (changed) + df_insn_rescan (insn); } - if (changed) - df_insn_rescan (insn); } } - } - recompute_frame_layout_p = true; + recompute_frame_layout_p = true; + } } if (crtl->stack_realign_needed != stack_realign) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 623e414..a34c692 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2017-09-05 H.J. Lu <hongjiu.lu@intel.com> + + PR target/59501 + PR target/81624 + PR target/81769 + * gcc.target/i386/pr59501-4a.c: Remove xfail. + * gcc.target/i386/pr81769-1a.c: New test. + * gcc.target/i386/pr81769-1b.c: Likewise. + * gcc.target/i386/pr81769-2.c: Likewise. + 2017-09-05 Marek Polacek <polacek@redhat.com> PR sanitizer/82072 diff --git a/gcc/testsuite/gcc.target/i386/pr59501-4a.c b/gcc/testsuite/gcc.target/i386/pr59501-4a.c index 5c3cb68..908c7f4 100644 --- a/gcc/testsuite/gcc.target/i386/pr59501-4a.c +++ b/gcc/testsuite/gcc.target/i386/pr59501-4a.c @@ -5,4 +5,4 @@ #include "pr59501-3a.c" /* Verify no dynamic realignment is performed. */ -/* { dg-final { scan-assembler-not "and\[^\n\r]*sp" { xfail *-*-* } } } */ +/* { dg-final { scan-assembler-not "and\[^\n\r]*sp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81769-1a.c b/gcc/testsuite/gcc.target/i386/pr81769-1a.c new file mode 100644 index 0000000..8ebe729 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81769-1a.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mavx" } */ + +typedef int v8si __attribute__ ((vector_size (32))); +typedef unsigned long long int u64 __attribute__ ((aligned(64))); + + +void +#ifndef __x86_64__ +__attribute__((regparm(3))) +#endif +foo (u64 *idx, v8si *out_start, v8si *regions) +{ + if (*idx < 20 ) { + v8si base = regions[*idx]; + *out_start = base; + } +} + +/* Verify no dynamic realignment is performed. */ +/* { dg-final { scan-assembler-not "and\[^\n\r]*sp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81769-1b.c b/gcc/testsuite/gcc.target/i386/pr81769-1b.c new file mode 100644 index 0000000..6505a5f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81769-1b.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mavx -fno-omit-frame-pointer" } */ + +#include "pr81769-1a.c" + +/* Verify no dynamic realignment is performed. */ +/* { dg-final { scan-assembler-not "and\[^\n\r]*sp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81769-2.c b/gcc/testsuite/gcc.target/i386/pr81769-2.c new file mode 100644 index 0000000..e020db2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81769-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mavx -fno-omit-frame-pointer" } */ + +typedef unsigned long long int u64 __attribute__ ((aligned(64))); + +void +#ifndef __x86_64__ +__attribute__((regparm(3))) +#endif +foo (u64 *idx, unsigned int *out_start, unsigned int *out_end, + unsigned int *regions) +{ + if (*idx < 20 ) { + unsigned int base = regions[*idx]; + *out_start = base; + *out_end = base; + } +} + +/* Verify no dynamic realignment is performed. */ +/* { dg-final { scan-assembler-not "and\[^\n\r]*sp" } } */ |