re PR rtl-optimization/66626 (gcc.dg/torture/stackalign/non-local-goto-5.c segfaults w/ -mregparm=3 or -miamcu)
2015-07-16 Vladimir Makarov <vmakarov@redhat.com> PR rtl-optimization/66626 * ira.h (emit-rtl.h): Include. (non_spilled_static_chain_regno_p): New. * ira-color.c (setup_profitable_hard_regs): Clear profitable regs unless it is non spilled static chain pseudo. (assign_hard_rego): Spill memory profitable allocno unless it is non spilled static chain pseudo. (allocno_spill_priority_compare): Put non spilled static chain pseudo at the end of sorted array. (improve_allocation): Do nothing if we have static chain and non-local goto. (allocno__priority_compare_func): Put non spilled static chain pseudo at the beginning of sorted array. (move_spill_restore): Ignore non spilled static chain pseudo. * ira-costs.c (find_costs_and_classes): Don't assign class NO_REGS to non spilled static chain pseudo. * lra-assigns.c (pseudo_compare_func): Put non spilled static chain pseudo at the beginning of sorted array. (spill_for): Spill non spilled static chain pseudo last. * lra-constraints.c (lra_constraints): Remove static chain pseudo check for equivalence. 2015-07-16 Vladimir Makarov <vmakarov@redhat.com> PR rtl-optimization/66626 * gcc.target/i386/pr66626-2.c: New. From-SVN: r225891
This commit is contained in:
parent
a7d1f3fedc
commit
b81a2f0dbc
8 changed files with 137 additions and 20 deletions
|
@ -1,3 +1,27 @@
|
|||
2015-07-16 Vladimir Makarov <vmakarov@redhat.com>
|
||||
|
||||
PR rtl-optimization/66626
|
||||
* ira.h (emit-rtl.h): Include.
|
||||
(non_spilled_static_chain_regno_p): New.
|
||||
* ira-color.c (setup_profitable_hard_regs): Clear profitable regs
|
||||
unless it is non spilled static chain pseudo.
|
||||
(assign_hard_rego): Spill memory profitable allocno unless it is
|
||||
non spilled static chain pseudo.
|
||||
(allocno_spill_priority_compare): Put non spilled static chain
|
||||
pseudo at the end of sorted array.
|
||||
(improve_allocation): Do nothing if we have static chain and
|
||||
non-local goto.
|
||||
(allocno__priority_compare_func): Put non spilled static chain
|
||||
pseudo at the beginning of sorted array.
|
||||
(move_spill_restore): Ignore non spilled static chain pseudo.
|
||||
* ira-costs.c (find_costs_and_classes): Don't assign class NO_REGS
|
||||
to non spilled static chain pseudo.
|
||||
* lra-assigns.c (pseudo_compare_func): Put non spilled static chain
|
||||
pseudo at the beginning of sorted array.
|
||||
(spill_for): Spill non spilled static chain pseudo last.
|
||||
* lra-constraints.c (lra_constraints): Remove static chain pseudo
|
||||
check for equivalence.
|
||||
|
||||
2015-07-16 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR ipa/66896.
|
||||
|
|
|
@ -1044,7 +1044,10 @@ setup_profitable_hard_regs (void)
|
|||
continue;
|
||||
data = ALLOCNO_COLOR_DATA (a);
|
||||
if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL
|
||||
&& ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a))
|
||||
&& ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a)
|
||||
/* Do not empty profitable regs for static chain pointer
|
||||
pseudo when non-local goto is used. */
|
||||
&& ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
|
||||
CLEAR_HARD_REG_SET (data->profitable_hard_regs);
|
||||
else
|
||||
{
|
||||
|
@ -1126,7 +1129,10 @@ setup_profitable_hard_regs (void)
|
|||
if (! TEST_HARD_REG_BIT (data->profitable_hard_regs,
|
||||
hard_regno))
|
||||
continue;
|
||||
if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j])
|
||||
if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j]
|
||||
/* Do not remove HARD_REGNO for static chain pointer
|
||||
pseudo when non-local goto is used. */
|
||||
&& ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
|
||||
CLEAR_HARD_REG_BIT (data->profitable_hard_regs,
|
||||
hard_regno);
|
||||
else if (min_cost > costs[j])
|
||||
|
@ -1134,7 +1140,10 @@ setup_profitable_hard_regs (void)
|
|||
}
|
||||
}
|
||||
else if (ALLOCNO_UPDATED_MEMORY_COST (a)
|
||||
< ALLOCNO_UPDATED_CLASS_COST (a))
|
||||
< ALLOCNO_UPDATED_CLASS_COST (a)
|
||||
/* Do not empty profitable regs for static chain
|
||||
pointer pseudo when non-local goto is used. */
|
||||
&& ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
|
||||
CLEAR_HARD_REG_SET (data->profitable_hard_regs);
|
||||
if (ALLOCNO_UPDATED_CLASS_COST (a) > min_cost)
|
||||
ALLOCNO_UPDATED_CLASS_COST (a) = min_cost;
|
||||
|
@ -1854,7 +1863,10 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
|
|||
ira_assert (hard_regno >= 0);
|
||||
}
|
||||
}
|
||||
if (min_full_cost > mem_cost)
|
||||
if (min_full_cost > mem_cost
|
||||
/* Do not spill static chain pointer pseudo when non-local goto
|
||||
is used. */
|
||||
&& ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
|
||||
{
|
||||
if (! retry_p && internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
|
||||
fprintf (ira_dump_file, "(memory is more profitable %d vs %d) ",
|
||||
|
@ -2480,6 +2492,12 @@ allocno_spill_priority_compare (ira_allocno_t a1, ira_allocno_t a2)
|
|||
{
|
||||
int pri1, pri2, diff;
|
||||
|
||||
/* Avoid spilling static chain pointer pseudo when non-local goto is
|
||||
used. */
|
||||
if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a1)))
|
||||
return 1;
|
||||
else if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a2)))
|
||||
return -1;
|
||||
if (ALLOCNO_BAD_SPILL_P (a1) && ! ALLOCNO_BAD_SPILL_P (a2))
|
||||
return 1;
|
||||
if (ALLOCNO_BAD_SPILL_P (a2) && ! ALLOCNO_BAD_SPILL_P (a1))
|
||||
|
@ -2732,6 +2750,11 @@ improve_allocation (void)
|
|||
ira_allocno_t a;
|
||||
bitmap_iterator bi;
|
||||
|
||||
/* Don't bother to optimize the code with static chain pointer and
|
||||
non-local goto in order not to spill the chain pointer
|
||||
pseudo. */
|
||||
if (cfun->static_chain_decl && crtl->has_nonlocal_goto)
|
||||
return;
|
||||
/* Clear counts used to process conflicting allocnos only once for
|
||||
each allocno. */
|
||||
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
|
||||
|
@ -2938,6 +2961,12 @@ allocno_priority_compare_func (const void *v1p, const void *v2p)
|
|||
ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
|
||||
int pri1, pri2;
|
||||
|
||||
/* Assign hard reg to static chain pointer pseudo first when
|
||||
non-local goto is used. */
|
||||
if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a1)))
|
||||
return 1;
|
||||
else if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a2)))
|
||||
return -1;
|
||||
pri1 = allocno_priorities[ALLOCNO_NUM (a1)];
|
||||
pri2 = allocno_priorities[ALLOCNO_NUM (a2)];
|
||||
if (pri2 != pri1)
|
||||
|
@ -3379,7 +3408,10 @@ move_spill_restore (void)
|
|||
by copy although the allocno will not get memory
|
||||
slot. */
|
||||
|| ira_equiv_no_lvalue_p (regno)
|
||||
|| !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a)))
|
||||
|| !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a))
|
||||
/* Do not spill static chain pointer pseudo when
|
||||
non-local goto is used. */
|
||||
|| non_spilled_static_chain_regno_p (regno))
|
||||
continue;
|
||||
mode = ALLOCNO_MODE (a);
|
||||
rclass = ALLOCNO_CLASS (a);
|
||||
|
|
|
@ -1836,7 +1836,8 @@ find_costs_and_classes (FILE *dump_file)
|
|||
alt_class = reg_class_subunion[alt_class][rclass];
|
||||
}
|
||||
alt_class = ira_allocno_class_translate[alt_class];
|
||||
if (best_cost > i_mem_cost)
|
||||
if (best_cost > i_mem_cost
|
||||
&& ! non_spilled_static_chain_regno_p (i))
|
||||
regno_aclass[i] = NO_REGS;
|
||||
else if (!optimize && !targetm.class_likely_spilled_p (best))
|
||||
/* Registers in the alternative class are likely to need
|
||||
|
@ -1875,7 +1876,10 @@ find_costs_and_classes (FILE *dump_file)
|
|||
}
|
||||
if (pass == flag_expensive_optimizations)
|
||||
{
|
||||
if (best_cost > i_mem_cost)
|
||||
if (best_cost > i_mem_cost
|
||||
/* Do not assign NO_REGS to static chain pointer
|
||||
pseudo when non-local goto is used. */
|
||||
&& ! non_spilled_static_chain_regno_p (i))
|
||||
best = alt_class = NO_REGS;
|
||||
else if (best == alt_class)
|
||||
alt_class = NO_REGS;
|
||||
|
@ -1890,7 +1894,9 @@ find_costs_and_classes (FILE *dump_file)
|
|||
regno_best_class[i] = best;
|
||||
if (! allocno_p)
|
||||
{
|
||||
pref[i] = best_cost > i_mem_cost ? NO_REGS : best;
|
||||
pref[i] = (best_cost > i_mem_cost
|
||||
&& ! non_spilled_static_chain_regno_p (i)
|
||||
? NO_REGS : best);
|
||||
continue;
|
||||
}
|
||||
for (a = ira_regno_allocno_map[i];
|
||||
|
|
13
gcc/ira.h
13
gcc/ira.h
|
@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see
|
|||
#ifndef GCC_IRA_H
|
||||
#define GCC_IRA_H
|
||||
|
||||
#include "emit-rtl.h"
|
||||
|
||||
/* True when we use LRA instead of reload pass for the current
|
||||
function. */
|
||||
extern bool ira_use_lra_p;
|
||||
|
@ -209,4 +211,15 @@ extern void ira_adjust_equiv_reg_cost (unsigned, int);
|
|||
/* ira-costs.c */
|
||||
extern void ira_costs_c_finalize (void);
|
||||
|
||||
/* Spilling static chain pseudo may result in generation of wrong
|
||||
non-local goto code using frame-pointer to address saved stack
|
||||
pointer value after restoring old frame pointer value. The
|
||||
function returns TRUE if REGNO is such a static chain pseudo. */
|
||||
static inline bool
|
||||
non_spilled_static_chain_regno_p (int regno)
|
||||
{
|
||||
return (cfun->static_chain_decl && crtl->has_nonlocal_goto
|
||||
&& REG_EXPR (regno_reg_rtx[regno]) == cfun->static_chain_decl);
|
||||
}
|
||||
|
||||
#endif /* GCC_IRA_H */
|
||||
|
|
|
@ -255,6 +255,13 @@ pseudo_compare_func (const void *v1p, const void *v2p)
|
|||
int r1 = *(const int *) v1p, r2 = *(const int *) v2p;
|
||||
int diff;
|
||||
|
||||
/* Assign hard reg to static chain pointer first pseudo when
|
||||
non-local goto is used. */
|
||||
if (non_spilled_static_chain_regno_p (r1))
|
||||
return -1;
|
||||
else if (non_spilled_static_chain_regno_p (r2))
|
||||
return 1;
|
||||
|
||||
/* Prefer to assign more frequently used registers first. */
|
||||
if ((diff = lra_reg_info[r2].freq - lra_reg_info[r1].freq) != 0)
|
||||
return diff;
|
||||
|
@ -892,6 +899,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
|
|||
{
|
||||
int i, j, n, p, hard_regno, best_hard_regno, cost, best_cost, rclass_size;
|
||||
int reload_hard_regno, reload_cost;
|
||||
bool static_p, best_static_p;
|
||||
machine_mode mode;
|
||||
enum reg_class rclass;
|
||||
unsigned int spill_regno, reload_regno, uid;
|
||||
|
@ -914,6 +922,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
|
|||
}
|
||||
best_hard_regno = -1;
|
||||
best_cost = INT_MAX;
|
||||
best_static_p = TRUE;
|
||||
best_insn_pseudos_num = INT_MAX;
|
||||
smallest_bad_spills_num = INT_MAX;
|
||||
rclass_size = ira_class_hard_regs_num[rclass];
|
||||
|
@ -936,6 +945,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
|
|||
&try_hard_reg_pseudos[hard_regno + j]);
|
||||
}
|
||||
/* Spill pseudos. */
|
||||
static_p = false;
|
||||
EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi)
|
||||
if ((pic_offset_table_rtx != NULL
|
||||
&& spill_regno == REGNO (pic_offset_table_rtx))
|
||||
|
@ -945,6 +955,8 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
|
|||
&& ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno)
|
||||
&& ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno)))
|
||||
goto fail;
|
||||
else if (non_spilled_static_chain_regno_p (spill_regno))
|
||||
static_p = true;
|
||||
insn_pseudos_num = 0;
|
||||
bad_spills_num = 0;
|
||||
if (lra_dump_file != NULL)
|
||||
|
@ -1024,14 +1036,19 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
|
|||
x = x->next ())
|
||||
cost -= REG_FREQ_FROM_BB (BLOCK_FOR_INSN (x->insn ()));
|
||||
}
|
||||
if (best_insn_pseudos_num > insn_pseudos_num
|
||||
|| (best_insn_pseudos_num == insn_pseudos_num
|
||||
&& (bad_spills_num < smallest_bad_spills_num
|
||||
|| (bad_spills_num == smallest_bad_spills_num
|
||||
&& best_cost > cost))))
|
||||
/* Avoid spilling static chain pointer pseudo when non-local
|
||||
goto is used. */
|
||||
if ((! static_p && best_static_p)
|
||||
|| (static_p == best_static_p
|
||||
&& (best_insn_pseudos_num > insn_pseudos_num
|
||||
|| (best_insn_pseudos_num == insn_pseudos_num
|
||||
&& (bad_spills_num < smallest_bad_spills_num
|
||||
|| (bad_spills_num == smallest_bad_spills_num
|
||||
&& best_cost > cost))))))
|
||||
{
|
||||
best_insn_pseudos_num = insn_pseudos_num;
|
||||
smallest_bad_spills_num = bad_spills_num;
|
||||
best_static_p = static_p;
|
||||
best_cost = cost;
|
||||
best_hard_regno = hard_regno;
|
||||
bitmap_copy (&best_spill_pseudos_bitmap, &spill_pseudos_bitmap);
|
||||
|
|
|
@ -4306,13 +4306,7 @@ lra_constraints (bool first_p)
|
|||
&& ((CONST_POOL_OK_P (PSEUDO_REGNO_MODE (i), x)
|
||||
&& (targetm.preferred_reload_class
|
||||
(x, lra_get_allocno_class (i)) == NO_REGS))
|
||||
|| contains_symbol_ref_p (x)))
|
||||
/* Static chain equivalence may contain eliminable
|
||||
regs and the result of elimination might be wrong
|
||||
after restoring frame pointer for a nonlocal
|
||||
goto. */
|
||||
|| (cfun->static_chain_decl && crtl->has_nonlocal_goto
|
||||
&& REG_EXPR (reg) == cfun->static_chain_decl))
|
||||
|| contains_symbol_ref_p (x))))
|
||||
ira_reg_equiv[i].defined_p = false;
|
||||
if (contains_reg_p (x, false, true))
|
||||
ira_reg_equiv[i].profitable_p = false;
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2015-07-16 Vladimir Makarov <vmakarov@redhat.com>
|
||||
|
||||
PR rtl-optimization/66626
|
||||
* gcc.target/i386/pr66626-2.c: New.
|
||||
|
||||
2015-07-16 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* g++.dg/ipa/pr66896.c: New test.
|
||||
|
|
26
gcc/testsuite/gcc.target/i386/pr66626-2.c
Normal file
26
gcc/testsuite/gcc.target/i386/pr66626-2.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -mregparm=3" } */
|
||||
/* { dg-require-effective-target ia32 } */
|
||||
extern void abort (void);
|
||||
|
||||
int s (int i)
|
||||
{
|
||||
__label__ l1;
|
||||
int f (int i)
|
||||
{
|
||||
if (i == 2)
|
||||
goto l1;
|
||||
return 0;
|
||||
}
|
||||
return f (i);
|
||||
l1:;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (s (2) != 1)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue