The following patch implements most proposals of Richard's review of
lra.c and lra-int.h.
The patch was successfully bootstrapped and tested on x86/x86-64.
Committed as rev. 192544.
2012-10-17 Vladimir Makarov <vmaka...@redhat.com>
* Makefile.in (LRA_INT_H): Add $(BITMAP_H) $(RECOG_H)
$(INSN_ATTR_H) insn-codes.h.
* lra-int.h: Include recog.h and insn-codes.h.
(struct lra_insn_reg, struct lra_static_insn_data): Improve
comments.
(lra_expand_reg_info, lra_secondary_memory): Remove.
(lra_save_restore, lra_hard_reg_set_intersection_p): Ditto.
(lra_add_hard_reg_set): Ditto.
(lra_get_hard_regno_and_offset): Set up offset to zero.
(struct target_lra_int): New.
(default_target_lra_int, this_target_lra_int, op_alt_data): Ditto.
* target-globals.h (this_target_lra_int): New external.
(target_globals): New member lra_int.
(restore_target_globals): Restore this_target_lra_int.
* target-globals.c: Include lra-int.h.
(default_target_globals): Add &default_target_lra_int.
* doc/md.texi: Add new interpretation of hint * for LRA.
* lra-assigns.c (find_hard_regno_for, spill_for): Use
add_to_hard_reg_set instead of lra_add_hard_reg_set. Use
overlaps_hard_reg_set_p instead of
lra_hard_reg_set_intersection_p.
(setup_live_pseudos_and_spill_after_risky): Ditto.
(setup_try_hard_regno_pseudos): Use overlaps_hard_reg_set_p
instead of lra_hard_reg_set_intersection_p.
* lra-constraints.c (uses_hard_regs_p, contains_reg_p): Ditto.
(need_for_call_save_p): Ditto.
(process_alt_operands, inherit_in_ebb): Use add_to_hard_reg_set
instead of lra_add_hard_reg_set.
* lra-eliminations.c (spill_pseudos): Use overlaps_hard_reg_set_p
instead of lra_hard_reg_set_intersection_p.
* lra-spills.c (assign_spill_hard_regs): Use add_to_hard_reg_set
instead of lra_add_hard_reg_set. Use overlaps_hard_reg_set_p
instead of lra_hard_reg_set_intersection_p.
* lra.c (lra_create_new_reg_with_unique_value): Improve comments.
(lra_emit_add): Ditto.
(this_target_lra_int, default_target_lra_int): New.
(op_alt_data): Move to struct target_lra_int.
(collect_non_operand_hard_regs): Simplify code.
(lra_set_insn_recog_data): Use recog_memoized.
(lra_update_insn_recog_data): Fix typo in a comment.
(initialize_lra_reg_info_element): New.
(init_reg_info, expand_reg_info): Use
initialize_lra_reg_info_element.
(add_regs_to_insn_regno_info): Simplify the code.
(check_rtl): Use AUTOINC.
(has_nonexceptional_receiver): Simplify code.
(update_reg_notes): Rename to update_inc_notes. Ignore REG_DEAD
and REG_UNUSED.
(lra_init): Improve comment.
Index: Makefile.in
===================================================================
--- Makefile.in (revision 192534)
+++ Makefile.in (working copy)
@@ -939,7 +939,7 @@ TREE_DATA_REF_H = tree-data-ref.h $(OMEG
TREE_INLINE_H = tree-inline.h vecir.h
REAL_H = real.h $(MACHMODE_H)
IRA_INT_H = ira.h ira-int.h $(CFGLOOP_H) alloc-pool.h
-LRA_INT_H = lra.h lra-int.h
+LRA_INT_H = lra.h $(BITMAP_H) $(RECOG_H) $(INSN_ATTR_H) insn-codes.h lra-int.h
DBGCNT_H = dbgcnt.h dbgcnt.def
EBITMAP_H = ebitmap.h sbitmap.h
LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \
Index: doc/md.texi
===================================================================
--- doc/md.texi (revision 192534)
+++ doc/md.texi (working copy)
@@ -1,5 +1,5 @@
@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001,
-@c 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+@c 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
@c Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -1606,7 +1606,9 @@ register preferences.
@item *
Says that the following character should be ignored when choosing
register preferences. @samp{*} has no effect on the meaning of the
-constraint as a constraint, and no effect on reloading.
+constraint as a constraint, and no effect on reloading. For LRA
+@samp{*} additionally disparages slightly the alternative if the
+following character matches the operand.
@ifset INTERNALS
Here is an example: the 68000 has an instruction to sign-extend a
Index: lra-assigns.c
===================================================================
--- lra-assigns.c (revision 192534)
+++ lra-assigns.c (working copy)
@@ -523,9 +523,9 @@ find_hard_regno_for (int regno, int *cos
}
else
{
- lra_add_hard_reg_set (live_pseudos_reg_renumber[conflict_regno],
- lra_reg_info[conflict_regno].biggest_mode,
- &conflict_set);
+ add_to_hard_reg_set (&conflict_set,
+ lra_reg_info[conflict_regno].biggest_mode,
+ live_pseudos_reg_renumber[conflict_regno]);
if (hard_reg_set_subset_p (reg_class_contents[rclass],
conflict_set))
return -1;
@@ -564,9 +564,8 @@ find_hard_regno_for (int regno, int *cos
hard_regno = try_only_hard_regno;
else
hard_regno = ira_class_hard_regs[rclass][i];
- if (! lra_hard_reg_set_intersection_p (hard_regno,
- PSEUDO_REGNO_MODE (regno),
- conflict_set)
+ if (! overlaps_hard_reg_set_p (conflict_set,
+ PSEUDO_REGNO_MODE (regno), hard_regno)
/* We can not use prohibited_class_mode_regs because it is
not defined for all classes. */
&& HARD_REGNO_MODE_OK (hard_regno, PSEUDO_REGNO_MODE (regno))
@@ -741,8 +740,8 @@ setup_try_hard_regno_pseudos (int p, enu
{
mode = PSEUDO_REGNO_MODE (spill_regno);
hard_regno = live_pseudos_reg_renumber[spill_regno];
- if (lra_hard_reg_set_intersection_p (hard_regno, mode,
- reg_class_contents[rclass]))
+ if (overlaps_hard_reg_set_p (reg_class_contents[rclass],
+ mode, hard_regno))
{
for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--)
{
@@ -862,8 +861,8 @@ spill_for (int regno, bitmap spilled_pse
if (lra_dump_file != NULL)
fprintf (lra_dump_file, " spill %d(freq=%d)",
spill_regno, lra_reg_info[spill_regno].freq);
- lra_add_hard_reg_set (reg_renumber[spill_regno], mode2,
- &spilled_hard_regs);
+ add_to_hard_reg_set (&spilled_hard_regs,
+ mode2, reg_renumber[spill_regno]);
for (r = lra_reg_info[spill_regno].live_ranges;
r != NULL;
r = r->next)
@@ -903,9 +902,9 @@ spill_for (int regno, bitmap spilled_pse
if ((reload_hard_regno
= find_hard_regno_for (reload_regno,
&reload_cost, -1)) >= 0
- && (lra_hard_reg_set_intersection_p
- (reload_hard_regno, PSEUDO_REGNO_MODE (reload_regno),
- spilled_hard_regs)))
+ && (overlaps_hard_reg_set_p
+ (spilled_hard_regs,
+ PSEUDO_REGNO_MODE (reload_regno), reload_hard_regno)))
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file, " assign %d(cost=%d)",
@@ -1058,10 +1057,10 @@ setup_live_pseudos_and_spill_after_risky
/* If it is multi-register pseudos they should start on
the same hard register. */
|| hard_regno != reg_renumber[conflict_regno])
- lra_add_hard_reg_set (reg_renumber[conflict_regno],
- lra_reg_info[conflict_regno].biggest_mode,
- &conflict_set);
- if (! lra_hard_reg_set_intersection_p (hard_regno, mode, conflict_set))
+ add_to_hard_reg_set (&conflict_set,
+ lra_reg_info[conflict_regno].biggest_mode,
+ reg_renumber[conflict_regno]);
+ if (! overlaps_hard_reg_set_p (conflict_set, mode, hard_regno))
{
update_lives (regno, false);
continue;
@@ -1357,9 +1356,8 @@ lra_assign (void)
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
&& lra_reg_info[i].call_p
- && lra_hard_reg_set_intersection_p (reg_renumber[i],
- PSEUDO_REGNO_MODE (i),
- call_used_reg_set))
+ && overlaps_hard_reg_set_p (call_used_reg_set,
+ PSEUDO_REGNO_MODE (i), reg_renumber[i]))
gcc_unreachable ();
#endif
/* Setup insns to process on the next constraint pass. */
Index: lra-constraints.c
===================================================================
--- lra-constraints.c (revision 192534)
+++ lra-constraints.c (working copy)
@@ -1465,7 +1465,7 @@ uses_hard_regs_p (rtx x, HARD_REG_SET se
/* The real hard regno of the operand after the allocation. */
x_hard_regno = get_final_hard_regno (x_hard_regno, offset);
return (x_hard_regno >= 0
- && lra_hard_reg_set_intersection_p (x_hard_regno, mode, set));
+ && overlaps_hard_reg_set_p (set, mode, x_hard_regno));
}
if (MEM_P (x))
{
@@ -2223,7 +2223,7 @@ process_alt_operands (int only_alternati
continue;
clobbered_hard_regno = hard_regno[i];
CLEAR_HARD_REG_SET (temp_set);
- lra_add_hard_reg_set (clobbered_hard_regno, biggest_mode[i],
&temp_set);
+ add_to_hard_reg_set (&temp_set, biggest_mode[i],
clobbered_hard_regno);
for (j = 0; j < n_operands; j++)
if (j == i
/* We don't want process insides of match_operator and
@@ -3330,8 +3330,7 @@ contains_reg_p (rtx x, bool hard_reg_p,
if (regno < 0)
return false;
COMPL_HARD_REG_SET (alloc_regs, lra_no_alloc_regs);
- return lra_hard_reg_set_intersection_p (regno, GET_MODE (x),
- alloc_regs);
+ return overlaps_hard_reg_set_p (alloc_regs, GET_MODE (x), regno);
}
else
{
@@ -3972,9 +3971,9 @@ need_for_call_save_p (int regno)
{
lra_assert (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0);
return (usage_insns[regno].calls_num < calls_num
- && (lra_hard_reg_set_intersection_p
- (reg_renumber[regno], PSEUDO_REGNO_MODE (regno),
- call_used_reg_set)));
+ && (overlaps_hard_reg_set_p
+ (call_used_reg_set,
+ PSEUDO_REGNO_MODE (regno), reg_renumber[regno])));
}
/* Global registers occuring in the current EBB. */
@@ -4504,9 +4503,9 @@ inherit_in_ebb (rtx head, rtx tail)
if (j < FIRST_PSEUDO_REGISTER)
SET_HARD_REG_BIT (live_hard_regs, j);
else
- lra_add_hard_reg_set (reg_renumber[j],
- PSEUDO_REGNO_MODE (j),
- &live_hard_regs);
+ add_to_hard_reg_set (&live_hard_regs,
+ PSEUDO_REGNO_MODE (j),
+ reg_renumber[j]);
setup_next_usage_insn (j, last_insn, reloads_num, after_p);
}
}
@@ -4605,10 +4604,10 @@ inherit_in_ebb (rtx head, rtx tail)
change_p = true;
CLEAR_HARD_REG_SET (s);
if (dst_regno < FIRST_PSEUDO_REGISTER)
- lra_add_hard_reg_set (dst_regno, reg->biggest_mode, &s);
+ add_to_hard_reg_set (&s, reg->biggest_mode, dst_regno);
else
- lra_add_hard_reg_set (reg_renumber[dst_regno],
- PSEUDO_REGNO_MODE (dst_regno), &s);
+ add_to_hard_reg_set (&s, PSEUDO_REGNO_MODE (dst_regno),
+ reg_renumber[dst_regno]);
AND_COMPL_HARD_REG_SET (live_hard_regs, s);
}
/* We should invalidate potential inheritance for the
@@ -4704,12 +4703,12 @@ inherit_in_ebb (rtx head, rtx tail)
if (NONDEBUG_INSN_P (curr_insn))
{
if (src_regno < FIRST_PSEUDO_REGISTER)
- lra_add_hard_reg_set (src_regno, reg->biggest_mode,
- &live_hard_regs);
+ add_to_hard_reg_set (&live_hard_regs,
+ reg->biggest_mode, src_regno);
else
- lra_add_hard_reg_set (reg_renumber[src_regno],
- PSEUDO_REGNO_MODE (src_regno),
- &live_hard_regs);
+ add_to_hard_reg_set (&live_hard_regs,
+ PSEUDO_REGNO_MODE (src_regno),
+ reg_renumber[src_regno]);
}
add_next_usage_insn (src_regno, use_insn, reloads_num);
}
Index: lra-eliminations.c
===================================================================
--- lra-eliminations.c (revision 192534)
+++ lra-eliminations.c (working copy)
@@ -1016,8 +1016,8 @@ spill_pseudos (HARD_REG_SET set)
bitmap_initialize (&to_process, ®_obstack);
for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
- && lra_hard_reg_set_intersection_p (reg_renumber[i],
- PSEUDO_REGNO_MODE (i), set))
+ && overlaps_hard_reg_set_p (set,
+ PSEUDO_REGNO_MODE (i), reg_renumber[i]))
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file, " Spilling r%d(%d)\n",
Index: lra-int.h
===================================================================
--- lra-int.h (revision 192534)
+++ lra-int.h (working copy)
@@ -21,7 +21,9 @@ along with GCC; see the file COPYING3. I
#include "lra.h"
#include "bitmap.h"
+#include "recog.h"
#include "insn-attr.h"
+#include "insn-codes.h"
#ifdef ENABLE_CHECKING
#define lra_assert(c) gcc_assert (c)
@@ -161,12 +163,12 @@ struct lra_operand_data
unsigned int is_address : 1;
};
-/* Info about register in an insn. */
+/* Info about register occurrence in an insn. */
struct lra_insn_reg
{
/* The biggest mode through which the insn refers to the register
- (remember the register can be accessed through a subreg in the
- insn). */
+ occurrence (remember the register can be accessed through a
+ subreg in the insn). */
ENUM_BITFIELD(machine_mode) biggest_mode : 16;
/* The type of the corresponding operand which is the register. */
ENUM_BITFIELD (op_type) type : 8;
@@ -183,10 +185,11 @@ struct lra_insn_reg
};
/* Static part (common info for insns with the same ICODE) of LRA
- internal insn info. It exists in at most one exemplar for each
- non-negative ICODE. Warning: if the structure definition is
- changed, the initializer for debug_insn_static_data in lra.c should
- be changed too. */
+ internal insn info. It exists in at most one exemplar for each
+ non-negative ICODE. There is only one exception. Each asm insn has
+ own structure. Warning: if the structure definition is changed,
+ the initializer for debug_insn_static_data in lra.c should be
+ changed too. */
struct lra_static_insn_data
{
/* Static info about each insn operand. */
@@ -215,9 +218,12 @@ struct lra_static_insn_data
representation). */
struct lra_insn_recog_data
{
- int icode; /* The insn code. */
- rtx insn; /* The insn itself. */
- /* Common data for insns with the same ICODE. */
+ /* The insn code. */
+ int icode;
+ /* The insn itself. */
+ rtx insn;
+ /* Common data for insns with the same ICODE. Asm insns (their
+ ICODE is negative) do not share such structures. */
struct lra_static_insn_data *insn_static_data;
/* Two arrays of size correspondingly equal to the operand and the
duplication numbers: */
@@ -235,7 +241,8 @@ struct lra_insn_recog_data
should try to use any alternative, or the insn is a debug
insn. */
int used_insn_alternative;
- struct lra_insn_reg *regs; /* Always NULL for a debug insn. */
+ /* The following member value is always NULL for a debug insn. */
+ struct lra_insn_reg *regs;
};
typedef struct lra_insn_recog_data *lra_insn_recog_data_t;
@@ -280,7 +287,6 @@ extern void lra_invalidate_insn_regno_in
extern void lra_update_insn_regno_info (rtx);
extern struct lra_insn_reg *lra_get_insn_regs (int);
-extern void lra_expand_reg_info (void);
extern void lra_free_copies (void);
extern void lra_create_copy (int, int, int);
extern lra_copy_t lra_get_copy (int);
@@ -297,8 +303,6 @@ extern int lra_constraint_new_insn_uid_s
extern bitmap_head lra_special_reload_pseudos;
-extern rtx lra_secondary_memory[NUM_MACHINE_MODES];
-
extern int lra_constraint_offset (int, enum machine_mode);
extern int lra_constraint_iter;
@@ -346,10 +350,6 @@ extern bool lra_assign (void);
extern int lra_coalesce_iter;
extern bool lra_coalesce (void);
-/* lra-saves.c: */
-
-extern bool lra_save_restore (void);
-
/* lra-spills.c: */
extern bool lra_need_for_spills_p (void);
@@ -368,22 +368,6 @@ extern void lra_eliminate_reg_if_possibl
-/* The function returns TRUE if at least one hard register from ones
- starting with HARD_REGNO and containing value of MODE are in set
- HARD_REGSET. */
-static inline bool
-lra_hard_reg_set_intersection_p (int hard_regno, enum machine_mode mode,
- HARD_REG_SET hard_regset)
-{
- int i;
-
- lra_assert (hard_regno >= 0);
- for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--)
- if (TEST_HARD_REG_BIT (hard_regset, hard_regno + i))
- return true;
- return false;
-}
-
/* Return hard regno and offset of (sub-)register X through arguments
HARD_REGNO and OFFSET. If it is not (sub-)register or the hard
register is unknown, then return -1 and 0 correspondingly. */
@@ -392,7 +376,8 @@ lra_get_hard_regno_and_offset (rtx x, in
{
rtx reg;
- *hard_regno = *offset = -1;
+ *hard_regno = -1;
+ *offset = 0;
reg = x;
if (GET_CODE (x) == SUBREG)
reg = SUBREG_REG (x);
@@ -402,23 +387,11 @@ lra_get_hard_regno_and_offset (rtx x, in
*hard_regno = lra_get_regno_hard_regno (*hard_regno);
if (*hard_regno < 0)
return;
- *offset = 0;
if (GET_CODE (x) == SUBREG)
*offset += subreg_regno_offset (*hard_regno, GET_MODE (reg),
SUBREG_BYTE (x), GET_MODE (x));
}
-/* Add hard registers starting with HARD_REGNO and holding value of
- MODE to the set S. */
-static inline void
-lra_add_hard_reg_set (int hard_regno, enum machine_mode mode, HARD_REG_SET *s)
-{
- int i;
-
- for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--)
- SET_HARD_REG_BIT (*s, hard_regno + i);
-}
-
/* Update insn operands which are duplication of NOP operand. The
insn is represented by its LRA internal representation ID. */
static inline void
@@ -470,3 +443,22 @@ lra_get_insn_recog_data (rtx insn)
}
return lra_set_insn_recog_data (insn);
}
+
+
+
+struct target_lra_int
+{
+ /* Map INSN_UID -> the operand alternative data (NULL if unknown).
+ We assume that this data is valid until register info is changed
+ because classes in the data can be changed. */
+ struct operand_alternative *x_op_alt_data[LAST_INSN_CODE];
+};
+
+extern struct target_lra_int default_target_lra_int;
+#if SWITCHABLE_TARGET
+extern struct target_lra_int *this_target_lra_int;
+#else
+#define this_target_lra_int (&default_target_lra_int)
+#endif
+
+#define op_alt_data (this_target_lra_int->x_op_alt_data)
Index: lra-spills.c
===================================================================
--- lra-spills.c (revision 192534)
+++ lra-spills.c (working copy)
@@ -279,8 +279,8 @@ assign_spill_hard_regs (int *pseudo_regn
&& (hard_regno = lra_get_regno_hard_regno (i)) >= 0)
for (r = lra_reg_info[i].live_ranges; r != NULL; r = r->next)
for (p = r->start; p <= r->finish; p++)
- lra_add_hard_reg_set (hard_regno, lra_reg_info[i].biggest_mode,
- &reserved_hard_regs[p]);
+ add_to_hard_reg_set (&reserved_hard_regs[p],
+ lra_reg_info[i].biggest_mode, hard_regno);
bitmap_initialize (&ok_insn_bitmap, ®_obstack);
FOR_EACH_BB (bb)
FOR_BB_INSNS (bb, insn)
@@ -314,8 +314,7 @@ assign_spill_hard_regs (int *pseudo_regn
for (k = 0; k < spill_class_size; k++)
{
hard_regno = ira_class_hard_regs[spill_class][k];
- if (! lra_hard_reg_set_intersection_p (hard_regno, mode,
- conflict_hard_regs))
+ if (! overlaps_hard_reg_set_p (conflict_hard_regs, mode, hard_regno))
break;
}
if (k >= spill_class_size)
@@ -329,8 +328,8 @@ assign_spill_hard_regs (int *pseudo_regn
/* Update reserved_hard_regs. */
for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
for (p = r->start; p <= r->finish; p++)
- lra_add_hard_reg_set (hard_regno, lra_reg_info[regno].biggest_mode,
- &reserved_hard_regs[p]);
+ add_to_hard_reg_set (&reserved_hard_regs[p],
+ lra_reg_info[regno].biggest_mode, hard_regno);
spill_hard_reg[regno]
= gen_raw_REG (PSEUDO_REGNO_MODE (regno), hard_regno);
for (nr = 0;
Index: lra.c
===================================================================
--- lra.c (revision 192534)
+++ lra.c (working copy)
@@ -138,11 +138,12 @@ expand_reg_data (void)
ira_expand_reg_equiv ();
}
-/* Create and return a new reg from register FROM corresponding to
- machine description operand of mode MD_MODE. Initialize its
+/* Create and return a new reg of ORIGINAL mode. If ORIGINAL is NULL
+ or of VOIDmode, use MD_MODE for the new reg. Initialize its
register class to RCLASS. Print message about assigning class
- RCLASS containing new register name TITLE unless it is NULL. The
- created register will have unique held value. */
+ RCLASS containing new register name TITLE unless it is NULL. Use
+ attributes of ORIGINAL if it is a register. The created register
+ will have unique held value. */
rtx
lra_create_new_reg_with_unique_value (enum machine_mode md_mode, rtx original,
enum reg_class rclass, const char *title)
@@ -247,8 +248,11 @@ lra_delete_dead_insn (rtx insn)
which are frequent results of elimination.
Emit insns for x = y + z. X can be used to store intermediate
- values and should be not in Y and Z when we use x to store an
- intermediate value. */
+ values and should be not in Y and Z when we use X to store an
+ intermediate value. Y + Z should form [base] [+ index[ * scale]] [
+ + disp] where base and index are registers, disp and scale are
+ constants. Y should contain base if it is present, Z should
+ contain disp if any. index[*scale] can be part of Y or Z. */
void
lra_emit_add (rtx x, rtx y, rtx z)
{
@@ -496,16 +500,15 @@ finish_insn_regs (void)
/* This page contains code dealing LRA insn info (or in other words
LRA internal insn representation). */
+struct target_lra_int default_target_lra_int;
+#if SWITCHABLE_TARGET
+struct target_lra_int *this_target_lra_int = &default_target_lra_int;
+#endif
/* Map INSN_CODE -> the static insn data. This info is valid during
all translation unit. */
struct lra_static_insn_data *insn_code_data[LAST_INSN_CODE];
-/* Map INSN_UID -> the operand alternative data (NULL if unknown). We
- assume that this data is valid until register info is changed
- because classes in the data can be changed. */
-struct operand_alternative *op_alt_data[LAST_INSN_CODE];
-
/* Debug insns are represented as a special insn with one input
operand which is RTL expression in var_location. */
@@ -918,10 +921,16 @@ collect_non_operand_hard_regs (rtx *x, l
if (! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno))
{
for (curr = list; curr != NULL; curr = curr->next)
- if (curr->regno == regno)
- break;
- if (curr == NULL || curr->subreg_p != subreg_p
- || curr->biggest_mode != mode)
+ if (curr->regno == regno && curr->subreg_p == subreg_p
+ && curr->biggest_mode == mode)
+ {
+ if (curr->type != type)
+ curr->type = OP_INOUT;
+ if (curr->early_clobber != early_clobber)
+ curr->early_clobber = true;
+ break;
+ }
+ if (curr == NULL)
{
/* This is a new hard regno or the info can not be
integrated into the found structure. */
@@ -936,13 +945,6 @@ collect_non_operand_hard_regs (rtx *x, l
list = new_insn_reg (regno, type, mode, subreg_p,
early_clobber, list);
}
- else
- {
- if (curr->type != type)
- curr->type = OP_INOUT;
- if (curr->early_clobber != early_clobber)
- curr->early_clobber = true;
- }
}
return list;
}
@@ -1005,7 +1007,7 @@ lra_set_insn_recog_data (rtx insn)
icode = INSN_CODE (insn);
if (icode < 0)
/* It might be a new simple insn which is not recognized yet. */
- INSN_CODE (insn) = icode = recog (PATTERN (insn), insn, 0);
+ INSN_CODE (insn) = icode = recog_memoized (insn);
}
data = XNEW (struct lra_insn_recog_data);
lra_insn_recog_data[uid] = data;
@@ -1231,7 +1233,7 @@ invalidate_insn_recog_data (int uid)
}
/* Update all the insn info about INSN. It is usually called when
- something in the insn was changed. Return the udpated info. */
+ something in the insn was changed. Return the updated info. */
lra_insn_recog_data_t
lra_update_insn_recog_data (rtx insn)
{
@@ -1379,6 +1381,27 @@ DEF_VEC_ALLOC_P(lra_copy_t, heap);
/* Vec referring to pseudo copies. */
static VEC(lra_copy_t,heap) *copy_vec;
+/* Initialize I-th element of lra_reg_info. */
+static inline void
+initialize_lra_reg_info_element (int i)
+{
+ bitmap_initialize (&lra_reg_info[i].insn_bitmap, ®_obstack);
+#ifdef STACK_REGS
+ lra_reg_info[i].no_stack_p = false;
+#endif
+ CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
+ lra_reg_info[i].preferred_hard_regno1 = -1;
+ lra_reg_info[i].preferred_hard_regno2 = -1;
+ lra_reg_info[i].preferred_hard_regno_profit1 = 0;
+ lra_reg_info[i].preferred_hard_regno_profit2 = 0;
+ lra_reg_info[i].live_ranges = NULL;
+ lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0;
+ lra_reg_info[i].last_reload = 0;
+ lra_reg_info[i].restore_regno = -1;
+ lra_reg_info[i].val = get_new_reg_value ();
+ lra_reg_info[i].copies = NULL;
+}
+
/* Initialize common reg info and copies. */
static void
init_reg_info (void)
@@ -1389,23 +1412,7 @@ init_reg_info (void)
reg_info_size = max_reg_num () * 3 / 2 + 1;
lra_reg_info = XNEWVEC (struct lra_reg, reg_info_size);
for (i = 0; i < reg_info_size; i++)
- {
- bitmap_initialize (&lra_reg_info[i].insn_bitmap, ®_obstack);
-#ifdef STACK_REGS
- lra_reg_info[i].no_stack_p = false;
-#endif
- CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
- lra_reg_info[i].preferred_hard_regno1 = -1;
- lra_reg_info[i].preferred_hard_regno2 = -1;
- lra_reg_info[i].preferred_hard_regno_profit1 = 0;
- lra_reg_info[i].preferred_hard_regno_profit2 = 0;
- lra_reg_info[i].live_ranges = NULL;
- lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0;
- lra_reg_info[i].last_reload = 0;
- lra_reg_info[i].restore_regno = -1;
- lra_reg_info[i].val = get_new_reg_value ();
- lra_reg_info[i].copies = NULL;
- }
+ initialize_lra_reg_info_element (i);
copy_pool
= create_alloc_pool ("lra copies", sizeof (struct lra_copy), 100);
copy_vec = VEC_alloc (lra_copy_t, heap, 100);
@@ -1437,23 +1444,7 @@ expand_reg_info (void)
reg_info_size = max_reg_num () * 3 / 2 + 1;
lra_reg_info = XRESIZEVEC (struct lra_reg, lra_reg_info, reg_info_size);
for (i = old; i < reg_info_size; i++)
- {
- bitmap_initialize (&lra_reg_info[i].insn_bitmap, ®_obstack);
-#ifdef STACK_REGS
- lra_reg_info[i].no_stack_p = false;
-#endif
- CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
- lra_reg_info[i].preferred_hard_regno1 = -1;
- lra_reg_info[i].preferred_hard_regno2 = -1;
- lra_reg_info[i].preferred_hard_regno_profit1 = 0;
- lra_reg_info[i].preferred_hard_regno_profit2 = 0;
- lra_reg_info[i].live_ranges = NULL;
- lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0;
- lra_reg_info[i].last_reload = 0;
- lra_reg_info[i].restore_regno = -1;
- lra_reg_info[i].val = get_new_reg_value ();
- lra_reg_info[i].copies = NULL;
- }
+ initialize_lra_reg_info_element (i);
}
/* Free all copies. */
@@ -1551,28 +1542,32 @@ add_regs_to_insn_regno_info (lra_insn_re
regno = REGNO (x);
expand_reg_info ();
if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, uid))
- data->regs = new_insn_reg (regno, type, mode, subreg_p, early_clobber,
- data->regs);
+ {
+ data->regs = new_insn_reg (regno, type, mode, subreg_p,
+ early_clobber, data->regs);
+ return;
+ }
else
{
for (curr = data->regs; curr != NULL; curr = curr->next)
if (curr->regno == regno)
- break;
- if (curr->subreg_p != subreg_p || curr->biggest_mode != mode)
- /* The info can not be integrated into the found
- structure. */
- data->regs = new_insn_reg (regno, type, mode, subreg_p,
- early_clobber, data->regs);
- else
- {
- if (curr->type != type)
- curr->type = OP_INOUT;
- if (curr->early_clobber != early_clobber)
- curr->early_clobber = true;
- }
- lra_assert (curr != NULL);
+ {
+ if (curr->subreg_p != subreg_p || curr->biggest_mode != mode)
+ /* The info can not be integrated into the found
+ structure. */
+ data->regs = new_insn_reg (regno, type, mode, subreg_p,
+ early_clobber, data->regs);
+ else
+ {
+ if (curr->type != type)
+ curr->type = OP_INOUT;
+ if (curr->early_clobber != early_clobber)
+ curr->early_clobber = true;
+ }
+ return;
+ }
+ gcc_unreachable ();
}
- return;
}
switch (code)
@@ -2039,13 +2034,7 @@ check_rtl (bool final_p)
as legitimate. Although they are legitimate if
they satisfies the constraints and will be checked
by insn constraints which we ignore here. */
- && GET_CODE (XEXP (op, 0)) != UNSPEC
- && GET_CODE (XEXP (op, 0)) != PRE_DEC
- && GET_CODE (XEXP (op, 0)) != PRE_INC
- && GET_CODE (XEXP (op, 0)) != POST_DEC
- && GET_CODE (XEXP (op, 0)) != POST_INC
- && GET_CODE (XEXP (op, 0)) != PRE_MODIFY
- && GET_CODE (XEXP (op, 0)) != POST_MODIFY)
+ && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) == RTX_AUTOINC)
fatal_insn_not_found (insn);
}
}
@@ -2081,7 +2070,12 @@ has_nonexceptional_receiver (void)
bb = *--tos;
FOR_EACH_EDGE (e, ei, bb->preds)
- if (!(e->flags & EDGE_ABNORMAL))
+ if (e->flags & EDGE_ABNORMAL)
+ {
+ free (worklist);
+ return true;
+ }
+ else
{
basic_block src = e->src;
@@ -2093,15 +2087,6 @@ has_nonexceptional_receiver (void)
}
}
free (worklist);
-
- /* Now see if there's a reachable block with an exceptional incoming
- edge. */
- FOR_EACH_BB (bb)
- if (bb->flags & BB_REACHABLE)
- FOR_EACH_EDGE (e, ei, bb->preds)
- if (e->flags & EDGE_ABNORMAL)
- return true;
-
/* No exceptional block reached exit unexceptionally. */
return false;
}
@@ -2141,7 +2126,7 @@ add_auto_inc_notes (rtx insn, rtx x)
that can make the notes obsolete. DF-infrastructure does not deal
with REG_INC notes -- so we should regenerate them here. */
static void
-update_reg_notes (void)
+update_inc_notes (void)
{
rtx *pnote;
basic_block bb;
@@ -2154,9 +2139,7 @@ update_reg_notes (void)
pnote = ®_NOTES (insn);
while (*pnote != 0)
{
- if (REG_NOTE_KIND (*pnote) == REG_DEAD
- || REG_NOTE_KIND (*pnote) == REG_UNUSED
- || REG_NOTE_KIND (*pnote) == REG_INC)
+ if (REG_NOTE_KIND (*pnote) == REG_INC)
*pnote = XEXP (*pnote, 1);
else
pnote = &XEXP (*pnote, 1);
@@ -2361,7 +2344,7 @@ lra (FILE *f)
regstat_free_n_sets_and_refs ();
regstat_free_ri ();
reload_completed = 1;
- update_reg_notes ();
+ update_inc_notes ();
inserted_p = fixup_abnormal_edges ();
@@ -2397,7 +2380,7 @@ lra_init_once (void)
init_insn_code_data_once ();
}
-/* Initialize LRA data once per function. */
+/* Initialize LRA whenever register-related information is changed. */
void
lra_init (void)
{
Index: target-globals.c
===================================================================
--- target-globals.c (revision 192534)
+++ target-globals.c (working copy)
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.
#include "libfuncs.h"
#include "cfgloop.h"
#include "ira-int.h"
+#include "lra-int.h"
#include "builtins.h"
#include "gcse.h"
#include "bb-reorder.h"
@@ -55,6 +56,7 @@ struct target_globals default_target_glo
&default_target_cfgloop,
&default_target_ira,
&default_target_ira_int,
+ &default_target_lra_int,
&default_target_builtins,
&default_target_gcse,
&default_target_bb_reorder,
Index: target-globals.h
===================================================================
--- target-globals.h (revision 192534)
+++ target-globals.h (working copy)
@@ -32,6 +32,7 @@ extern struct target_libfuncs *this_targ
extern struct target_cfgloop *this_target_cfgloop;
extern struct target_ira *this_target_ira;
extern struct target_ira_int *this_target_ira_int;
+extern struct target_lra_int *this_target_lra_int;
extern struct target_builtins *this_target_builtins;
extern struct target_gcse *this_target_gcse;
extern struct target_bb_reorder *this_target_bb_reorder;
@@ -49,6 +50,7 @@ struct GTY(()) target_globals {
struct target_cfgloop *GTY((skip)) cfgloop;
struct target_ira *GTY((skip)) ira;
struct target_ira_int *GTY((skip)) ira_int;
+ struct target_lra_int *GTY((skip)) lra_int;
struct target_builtins *GTY((skip)) builtins;
struct target_gcse *GTY((skip)) gcse;
struct target_bb_reorder *GTY((skip)) bb_reorder;
@@ -73,6 +75,7 @@ restore_target_globals (struct target_gl
this_target_cfgloop = g->cfgloop;
this_target_ira = g->ira;
this_target_ira_int = g->ira_int;
+ this_target_lra_int = g->lra_int;
this_target_builtins = g->builtins;
this_target_gcse = g->gcse;
this_target_bb_reorder = g->bb_reorder;