aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2017-09-05 16:39:24 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2017-09-05 09:39:24 -0700
commitf174328efedff73f53cad8848fe69f92e940309a (patch)
tree706d0c95cf17f85e96d477d27f667d470ee40466
parentc253525edd51a027b7db30e077a6643a78544b0c (diff)
downloadgcc-f174328efedff73f53cad8848fe69f92e940309a.zip
gcc-f174328efedff73f53cad8848fe69f92e940309a.tar.gz
gcc-f174328efedff73f53cad8848fe69f92e940309a.tar.bz2
i386: Avoid stack realignment if possible
ix86_finalize_stack_frame_flags has been extended to eliminate frame pointer when the new stack frame isn't needed with and without -maccumulate-outgoing-args as well as -fomit-frame-pointer. Since stack access with larger alignment may be optimized out, to decide if stack realignment is needed, we need to not only check for stack frame access, but also verify the alignment of stack frame access. Since alignment of memory access via arg_pointer is set up by caller, not by callee, we should find the maximum stack alignment from the stack frame access instructions via stack pointer and frame pointrer to avoid stack realignment when stack alignment needed is less than incoming stack boundary. gcc/ 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. gcc/testsuite/ 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. From-SVN: r251718
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/i386/i386.c143
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59501-4a.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81769-1a.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81769-1b.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81769-2.c21
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" } } */