re PR rtl-optimization/42216 (changes in scheduling regress 464.h264ref 20%)
PR rtl-opt/42216 * regrename.c: Error out if MAX_RECOG_OPERANDS is larger than HOST_BITS_PER_WIDE_INT. (verify_reg_in_set): New function, broken out of verify_reg_tracked. (verify_reg_tracked): Use it. (scan_rtx_reg): When seeing a use involving a superset of the registers in an existing chain, enlarge that chain. Otherwise, allow subsets and set fail_current_block for all other kinds of overlap. (hide_operands): New argument UNTRACKED_OPERANDS; callers changed. Do not modify operands when the bit with the corresponding number is set in that bitmap. (build_def_use): When we see matching operands with different modes, don't set fail_current_block, but keep track of such operands in a bitmap if their registers aren't already tracked in an open chain. Pass this bitmap to all hide_operands calls. From-SVN: r155134
This commit is contained in:
parent
574f366488
commit
d435810e76
@ -1,3 +1,22 @@
|
|||||||
|
2009-12-10 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||||
|
|
||||||
|
PR rtl-opt/42216
|
||||||
|
* regrename.c: Error out if MAX_RECOG_OPERANDS is larger than
|
||||||
|
HOST_BITS_PER_WIDE_INT.
|
||||||
|
(verify_reg_in_set): New function, broken out of verify_reg_tracked.
|
||||||
|
(verify_reg_tracked): Use it.
|
||||||
|
(scan_rtx_reg): When seeing a use involving a superset of the
|
||||||
|
registers in an existing chain, enlarge that chain. Otherwise,
|
||||||
|
allow subsets and set fail_current_block for all other kinds of
|
||||||
|
overlap.
|
||||||
|
(hide_operands): New argument UNTRACKED_OPERANDS; callers changed.
|
||||||
|
Do not modify operands when the bit with the corresponding number
|
||||||
|
is set in that bitmap.
|
||||||
|
(build_def_use): When we see matching operands with different
|
||||||
|
modes, don't set fail_current_block, but keep track of such
|
||||||
|
operands in a bitmap if their registers aren't already tracked
|
||||||
|
in an open chain. Pass this bitmap to all hide_operands calls.
|
||||||
|
|
||||||
2009-12-10 Richard Guenther <rguenther@suse.de>
|
2009-12-10 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
PR tree-optimization/42337
|
PR tree-optimization/42337
|
||||||
|
110
gcc/regrename.c
110
gcc/regrename.c
@ -40,6 +40,10 @@
|
|||||||
#include "tree-pass.h"
|
#include "tree-pass.h"
|
||||||
#include "df.h"
|
#include "df.h"
|
||||||
|
|
||||||
|
#if HOST_BITS_PER_WIDE_INT <= MAX_RECOG_OPERANDS
|
||||||
|
#error "Use a different bitmap implementation for untracked_operands."
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We keep linked lists of DU_HEAD structures, each of which describes
|
/* We keep linked lists of DU_HEAD structures, each of which describes
|
||||||
a chain of occurrences of a reg. */
|
a chain of occurrences of a reg. */
|
||||||
struct du_head
|
struct du_head
|
||||||
@ -434,21 +438,23 @@ static unsigned current_id;
|
|||||||
static struct du_head *open_chains;
|
static struct du_head *open_chains;
|
||||||
static struct du_head *closed_chains;
|
static struct du_head *closed_chains;
|
||||||
|
|
||||||
/* Conflict bitmaps, tracking the live chains and the live hard registers.
|
/* Bitmap of open chains. The bits set always match the list found in
|
||||||
The bits set in open_chains_set always match the list found in
|
|
||||||
open_chains. */
|
open_chains. */
|
||||||
static bitmap_head open_chains_set;
|
static bitmap_head open_chains_set;
|
||||||
static HARD_REG_SET live_hard_regs;
|
|
||||||
|
|
||||||
/* Record the registers being tracked in open_chains. The intersection
|
/* Record the registers being tracked in open_chains. */
|
||||||
between this and live_hard_regs is empty. */
|
|
||||||
static HARD_REG_SET live_in_chains;
|
static HARD_REG_SET live_in_chains;
|
||||||
|
|
||||||
/* Return true if OP is a reg that is being tracked already in some form.
|
/* Record the registers that are live but not tracked. The intersection
|
||||||
May set fail_current_block if it sees an unhandled case of overlap. */
|
between this and live_in_chains is empty. */
|
||||||
|
static HARD_REG_SET live_hard_regs;
|
||||||
|
|
||||||
|
/* Return true if OP is a reg for which all bits are set in PSET, false
|
||||||
|
if all bits are clear.
|
||||||
|
In other cases, set fail_current_block and return false. */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
verify_reg_tracked (rtx op)
|
verify_reg_in_set (rtx op, HARD_REG_SET *pset)
|
||||||
{
|
{
|
||||||
unsigned regno, nregs;
|
unsigned regno, nregs;
|
||||||
bool all_live, all_dead;
|
bool all_live, all_dead;
|
||||||
@ -459,7 +465,7 @@ verify_reg_tracked (rtx op)
|
|||||||
nregs = hard_regno_nregs[regno][GET_MODE (op)];
|
nregs = hard_regno_nregs[regno][GET_MODE (op)];
|
||||||
all_live = all_dead = true;
|
all_live = all_dead = true;
|
||||||
while (nregs-- > 0)
|
while (nregs-- > 0)
|
||||||
if (TEST_HARD_REG_BIT (live_hard_regs, regno + nregs))
|
if (TEST_HARD_REG_BIT (*pset, regno + nregs))
|
||||||
all_dead = false;
|
all_dead = false;
|
||||||
else
|
else
|
||||||
all_live = false;
|
all_live = false;
|
||||||
@ -468,26 +474,19 @@ verify_reg_tracked (rtx op)
|
|||||||
fail_current_block = true;
|
fail_current_block = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all_live)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
nregs = hard_regno_nregs[regno][GET_MODE (op)];
|
|
||||||
all_live = all_dead = true;
|
|
||||||
while (nregs-- > 0)
|
|
||||||
if (TEST_HARD_REG_BIT (live_in_chains, regno + nregs))
|
|
||||||
all_dead = false;
|
|
||||||
else
|
|
||||||
all_live = false;
|
|
||||||
if (!all_dead && !all_live)
|
|
||||||
{
|
|
||||||
fail_current_block = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return all_live;
|
return all_live;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if OP is a reg that is being tracked already in some form.
|
||||||
|
May set fail_current_block if it sees an unhandled case of overlap. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
verify_reg_tracked (rtx op)
|
||||||
|
{
|
||||||
|
return (verify_reg_in_set (op, &live_hard_regs)
|
||||||
|
|| verify_reg_in_set (op, &live_in_chains));
|
||||||
|
}
|
||||||
|
|
||||||
/* Called through note_stores. DATA points to a rtx_code, either SET or
|
/* Called through note_stores. DATA points to a rtx_code, either SET or
|
||||||
CLOBBER, which tells us which kind of rtx to look at. If we have a
|
CLOBBER, which tells us which kind of rtx to look at. If we have a
|
||||||
match, record the set register in live_hard_regs and in the hard_conflicts
|
match, record the set register in live_hard_regs and in the hard_conflicts
|
||||||
@ -584,6 +583,8 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
|
|||||||
&& head->nregs == this_nregs);
|
&& head->nregs == this_nregs);
|
||||||
int superset = (this_regno <= head->regno
|
int superset = (this_regno <= head->regno
|
||||||
&& this_regno + this_nregs >= head->regno + head->nregs);
|
&& this_regno + this_nregs >= head->regno + head->nregs);
|
||||||
|
int subset = (this_regno >= head->regno
|
||||||
|
&& this_regno + this_nregs <= head->regno + head->nregs);
|
||||||
|
|
||||||
if (head->terminated
|
if (head->terminated
|
||||||
|| head->regno + head->nregs <= this_regno
|
|| head->regno + head->nregs <= this_regno
|
||||||
@ -607,6 +608,25 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
|
|||||||
reg_names[head->regno], head->id, INSN_UID (insn),
|
reg_names[head->regno], head->id, INSN_UID (insn),
|
||||||
scan_actions_name[(int) action]);
|
scan_actions_name[(int) action]);
|
||||||
head->cannot_rename = 1;
|
head->cannot_rename = 1;
|
||||||
|
if (superset)
|
||||||
|
{
|
||||||
|
unsigned nregs = this_nregs;
|
||||||
|
head->regno = this_regno;
|
||||||
|
head->nregs = this_nregs;
|
||||||
|
while (nregs-- > 0)
|
||||||
|
SET_HARD_REG_BIT (live_in_chains, head->regno + nregs);
|
||||||
|
if (dump_file)
|
||||||
|
fprintf (dump_file,
|
||||||
|
"Widening register in chain %s (%d) at insn %d\n",
|
||||||
|
reg_names[head->regno], head->id, INSN_UID (insn));
|
||||||
|
}
|
||||||
|
else if (!subset)
|
||||||
|
{
|
||||||
|
fail_current_block = true;
|
||||||
|
if (dump_file)
|
||||||
|
fprintf (dump_file,
|
||||||
|
"Failing basic block due to unhandled overlap\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -919,12 +939,13 @@ scan_rtx (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
|
|||||||
/* Hide operands of the current insn (of which there are N_OPS) by
|
/* Hide operands of the current insn (of which there are N_OPS) by
|
||||||
substituting cc0 for them.
|
substituting cc0 for them.
|
||||||
Previous values are stored in the OLD_OPERANDS and OLD_DUPS.
|
Previous values are stored in the OLD_OPERANDS and OLD_DUPS.
|
||||||
|
For every bit set in DO_NOT_HIDE, we leave the operand alone.
|
||||||
If INOUT_AND_EC_ONLY is set, we only do this for OP_INOUT type operands
|
If INOUT_AND_EC_ONLY is set, we only do this for OP_INOUT type operands
|
||||||
and earlyclobbers. */
|
and earlyclobbers. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
|
hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
|
||||||
bool inout_and_ec_only)
|
unsigned HOST_WIDE_INT do_not_hide, bool inout_and_ec_only)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int alt = which_alternative;
|
int alt = which_alternative;
|
||||||
@ -936,6 +957,8 @@ hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
|
|||||||
reachable by proper operands. */
|
reachable by proper operands. */
|
||||||
if (recog_data.constraints[i][0] == '\0')
|
if (recog_data.constraints[i][0] == '\0')
|
||||||
continue;
|
continue;
|
||||||
|
if (do_not_hide & (1 << i))
|
||||||
|
continue;
|
||||||
if (!inout_and_ec_only || recog_data.operand_type[i] == OP_INOUT
|
if (!inout_and_ec_only || recog_data.operand_type[i] == OP_INOUT
|
||||||
|| recog_op_alt[i][alt].earlyclobber)
|
|| recog_op_alt[i][alt].earlyclobber)
|
||||||
*recog_data.operand_loc[i] = cc0_rtx;
|
*recog_data.operand_loc[i] = cc0_rtx;
|
||||||
@ -944,6 +967,8 @@ hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
|
|||||||
{
|
{
|
||||||
int opn = recog_data.dup_num[i];
|
int opn = recog_data.dup_num[i];
|
||||||
old_dups[i] = *recog_data.dup_loc[i];
|
old_dups[i] = *recog_data.dup_loc[i];
|
||||||
|
if (do_not_hide & (1 << opn))
|
||||||
|
continue;
|
||||||
if (!inout_and_ec_only || recog_data.operand_type[opn] == OP_INOUT
|
if (!inout_and_ec_only || recog_data.operand_type[opn] == OP_INOUT
|
||||||
|| recog_op_alt[opn][alt].earlyclobber)
|
|| recog_op_alt[opn][alt].earlyclobber)
|
||||||
*recog_data.dup_loc[i] = cc0_rtx;
|
*recog_data.dup_loc[i] = cc0_rtx;
|
||||||
@ -1018,6 +1043,7 @@ build_def_use (basic_block bb)
|
|||||||
{
|
{
|
||||||
rtx insn;
|
rtx insn;
|
||||||
df_ref *def_rec;
|
df_ref *def_rec;
|
||||||
|
unsigned HOST_WIDE_INT untracked_operands;
|
||||||
|
|
||||||
open_chains = closed_chains = NULL;
|
open_chains = closed_chains = NULL;
|
||||||
|
|
||||||
@ -1077,6 +1103,7 @@ build_def_use (basic_block bb)
|
|||||||
preprocess_constraints ();
|
preprocess_constraints ();
|
||||||
alt = which_alternative;
|
alt = which_alternative;
|
||||||
n_ops = recog_data.n_operands;
|
n_ops = recog_data.n_operands;
|
||||||
|
untracked_operands = 0;
|
||||||
|
|
||||||
/* Simplify the code below by rewriting things to reflect
|
/* Simplify the code below by rewriting things to reflect
|
||||||
matching constraints. Also promote OP_OUT to OP_INOUT in
|
matching constraints. Also promote OP_OUT to OP_INOUT in
|
||||||
@ -1094,11 +1121,21 @@ build_def_use (basic_block bb)
|
|||||||
|| (predicated && recog_data.operand_type[i] == OP_OUT
|
|| (predicated && recog_data.operand_type[i] == OP_OUT
|
||||||
&& verify_reg_tracked (recog_data.operand[i])))
|
&& verify_reg_tracked (recog_data.operand[i])))
|
||||||
{
|
{
|
||||||
|
rtx op = recog_data.operand[i];
|
||||||
recog_data.operand_type[i] = OP_INOUT;
|
recog_data.operand_type[i] = OP_INOUT;
|
||||||
|
/* A special case to deal with instruction patterns that
|
||||||
|
have matching operands with different modes. If we're
|
||||||
|
not already tracking such a reg, we won't start here,
|
||||||
|
and we must instead make sure to make the operand visible
|
||||||
|
to the machinery that tracks hard registers. */
|
||||||
if (matches >= 0
|
if (matches >= 0
|
||||||
&& (GET_MODE_SIZE (recog_data.operand_mode[i])
|
&& (GET_MODE_SIZE (recog_data.operand_mode[i])
|
||||||
!= GET_MODE_SIZE (recog_data.operand_mode[matches])))
|
!= GET_MODE_SIZE (recog_data.operand_mode[matches]))
|
||||||
fail_current_block = true;
|
&& !verify_reg_in_set (op, &live_in_chains))
|
||||||
|
{
|
||||||
|
untracked_operands |= 1 << i;
|
||||||
|
untracked_operands |= 1 << matches;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1107,7 +1144,8 @@ build_def_use (basic_block bb)
|
|||||||
|
|
||||||
/* Step 1a: Mark hard registers that are clobbered in this insn,
|
/* Step 1a: Mark hard registers that are clobbered in this insn,
|
||||||
outside an operand, as live. */
|
outside an operand, as live. */
|
||||||
hide_operands (n_ops, old_operands, old_dups, false);
|
hide_operands (n_ops, old_operands, old_dups, untracked_operands,
|
||||||
|
false);
|
||||||
note_stores (PATTERN (insn), note_sets_clobbers, &clobber_code);
|
note_stores (PATTERN (insn), note_sets_clobbers, &clobber_code);
|
||||||
restore_operands (insn, n_ops, old_operands, old_dups);
|
restore_operands (insn, n_ops, old_operands, old_dups);
|
||||||
|
|
||||||
@ -1120,7 +1158,8 @@ build_def_use (basic_block bb)
|
|||||||
We do this by munging all operands into CC0, and closing
|
We do this by munging all operands into CC0, and closing
|
||||||
everything remaining. */
|
everything remaining. */
|
||||||
|
|
||||||
hide_operands (n_ops, old_operands, old_dups, false);
|
hide_operands (n_ops, old_operands, old_dups, untracked_operands,
|
||||||
|
false);
|
||||||
scan_rtx (insn, &PATTERN (insn), NO_REGS, mark_all_read, OP_IN);
|
scan_rtx (insn, &PATTERN (insn), NO_REGS, mark_all_read, OP_IN);
|
||||||
restore_operands (insn, n_ops, old_operands, old_dups);
|
restore_operands (insn, n_ops, old_operands, old_dups);
|
||||||
|
|
||||||
@ -1157,7 +1196,8 @@ build_def_use (basic_block bb)
|
|||||||
/* Don't scan match_operand here, since we've no reg class
|
/* Don't scan match_operand here, since we've no reg class
|
||||||
information to pass down. Any operands that we could
|
information to pass down. Any operands that we could
|
||||||
substitute in will be represented elsewhere. */
|
substitute in will be represented elsewhere. */
|
||||||
if (recog_data.constraints[opn][0] == '\0')
|
if (recog_data.constraints[opn][0] == '\0'
|
||||||
|
|| untracked_operands & (1 << opn))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (recog_op_alt[opn][alt].is_address)
|
if (recog_op_alt[opn][alt].is_address)
|
||||||
@ -1202,13 +1242,15 @@ build_def_use (basic_block bb)
|
|||||||
the previous insn at the latest, as such operands cannot
|
the previous insn at the latest, as such operands cannot
|
||||||
possibly overlap with any input operands. */
|
possibly overlap with any input operands. */
|
||||||
|
|
||||||
hide_operands (n_ops, old_operands, old_dups, true);
|
hide_operands (n_ops, old_operands, old_dups, untracked_operands,
|
||||||
|
true);
|
||||||
scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN);
|
scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN);
|
||||||
restore_operands (insn, n_ops, old_operands, old_dups);
|
restore_operands (insn, n_ops, old_operands, old_dups);
|
||||||
|
|
||||||
/* Step 6a: Mark hard registers that are set in this insn,
|
/* Step 6a: Mark hard registers that are set in this insn,
|
||||||
outside an operand, as live. */
|
outside an operand, as live. */
|
||||||
hide_operands (n_ops, old_operands, old_dups, false);
|
hide_operands (n_ops, old_operands, old_dups, untracked_operands,
|
||||||
|
false);
|
||||||
note_stores (PATTERN (insn), note_sets_clobbers, &set_code);
|
note_stores (PATTERN (insn), note_sets_clobbers, &set_code);
|
||||||
restore_operands (insn, n_ops, old_operands, old_dups);
|
restore_operands (insn, n_ops, old_operands, old_dups);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user