Commit d435810e by Bernd Schmidt Committed by Bernd Schmidt

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
parent 574f3664
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
...@@ -40,6 +40,10 @@ ...@@ -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; ...@@ -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) ...@@ -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,24 +474,17 @@ verify_reg_tracked (rtx op) ...@@ -468,24 +474,17 @@ verify_reg_tracked (rtx op)
fail_current_block = true; fail_current_block = true;
return false; return false;
} }
return all_live;
}
if (all_live) /* Return true if OP is a reg that is being tracked already in some form.
return true; May set fail_current_block if it sees an unhandled case of overlap. */
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; 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
...@@ -584,6 +583,8 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment