aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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" } } */