summaryrefslogtreecommitdiff
path: root/gcc/regrename.c
diff options
context:
space:
mode:
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2009-12-03 12:58:30 +0000
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2009-12-03 12:58:30 +0000
commit83361a4c45d3a992a71446b9b40316f3ae371268 (patch)
treed1e4eef4dd149c60c96d350a0634ee170fc294ff /gcc/regrename.c
parentb3878a6c2ac223ec76282d0309750c7a68b69681 (diff)
downloadgcc-83361a4c45d3a992a71446b9b40316f3ae371268.tar.gz
PR middle-end/42202
* regrename.c (live_in_chains): New variable. (verify_reg_tracked): New static function. (scan_rtx_reg): Update live_in_chains. (scan_rtx): Only promote sets in COND_EXEC to OP_INOUT if we're already tracking the reg. (build_def_use): Likewise. Initialize live_in_chains. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154944 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/regrename.c')
-rw-r--r--gcc/regrename.c79
1 files changed, 72 insertions, 7 deletions
diff --git a/gcc/regrename.c b/gcc/regrename.c
index e0e89709513..0026324d1ed 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -440,6 +440,54 @@ static struct du_head *closed_chains;
static bitmap_head open_chains_set;
static HARD_REG_SET live_hard_regs;
+/* Record the registers being tracked in open_chains. The intersection
+ between this and live_hard_regs is empty. */
+static HARD_REG_SET live_in_chains;
+
+/* 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)
+{
+ unsigned regno, nregs;
+ bool all_live, all_dead;
+ if (!REG_P (op))
+ return false;
+
+ regno = REGNO (op);
+ nregs = hard_regno_nregs[regno][GET_MODE (op)];
+ all_live = all_dead = true;
+ while (nregs-- > 0)
+ if (TEST_HARD_REG_BIT (live_hard_regs, regno + nregs))
+ all_dead = false;
+ else
+ all_live = false;
+ if (!all_dead && !all_live)
+ {
+ fail_current_block = true;
+ 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;
+}
+
/* 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
match, record the set register in live_hard_regs and in the hard_conflicts
@@ -497,10 +545,14 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
mark_conflict (open_chains, head->id);
/* Since we're tracking this as a chain now, remove it from the
- list of conflicting live hard registers. */
+ list of conflicting live hard registers and track it in
+ live_in_chains instead. */
nregs = head->nregs;
while (nregs-- > 0)
- CLEAR_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
+ {
+ SET_HARD_REG_BIT (live_in_chains, head->regno + nregs);
+ CLEAR_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
+ }
COPY_HARD_REG_SET (head->hard_conflicts, live_hard_regs);
bitmap_set_bit (&open_chains_set, head->id);
@@ -585,10 +637,17 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
if ((action == terminate_dead || action == terminate_write)
&& superset)
{
+ unsigned nregs;
+
head->terminated = 1;
head->next_chain = closed_chains;
closed_chains = head;
bitmap_clear_bit (&open_chains_set, head->id);
+
+ nregs = head->nregs;
+ while (nregs-- > 0)
+ CLEAR_HARD_REG_BIT (live_in_chains, head->regno + nregs);
+
*p = next;
if (dump_file)
fprintf (dump_file,
@@ -805,7 +864,8 @@ scan_rtx (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
case SET:
scan_rtx (insn, &SET_SRC (x), cl, action, OP_IN);
scan_rtx (insn, &SET_DEST (x), cl, action,
- GET_CODE (PATTERN (insn)) == COND_EXEC ? OP_INOUT : OP_OUT);
+ (GET_CODE (PATTERN (insn)) == COND_EXEC
+ && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT);
return;
case STRICT_LOW_PART:
@@ -831,7 +891,8 @@ scan_rtx (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
case CLOBBER:
scan_rtx (insn, &SET_DEST (x), cl, action,
- GET_CODE (PATTERN (insn)) == COND_EXEC ? OP_INOUT : OP_OUT);
+ (GET_CODE (PATTERN (insn)) == COND_EXEC
+ && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT);
return;
case EXPR_LIST:
@@ -964,6 +1025,7 @@ build_def_use (basic_block bb)
current_id = 0;
bitmap_initialize (&open_chains_set, &bitmap_default_obstack);
+ CLEAR_HARD_REG_SET (live_in_chains);
REG_SET_TO_HARD_REG_SET (live_hard_regs, df_get_live_in (bb));
for (def_rec = df_get_artificial_defs (bb->index); *def_rec; def_rec++)
{
@@ -1017,8 +1079,10 @@ build_def_use (basic_block bb)
n_ops = recog_data.n_operands;
/* Simplify the code below by rewriting things to reflect
- matching constraints. Also promote OP_OUT to OP_INOUT
- in predicated instructions. */
+ matching constraints. Also promote OP_OUT to OP_INOUT in
+ predicated instructions, but only for register operands
+ that are already tracked, so that we can create a chain
+ when the first SET makes a register live. */
predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
for (i = 0; i < n_ops; ++i)
@@ -1027,7 +1091,8 @@ build_def_use (basic_block bb)
if (matches >= 0)
recog_op_alt[i][alt].cl = recog_op_alt[matches][alt].cl;
if (matches >= 0 || recog_op_alt[i][alt].matched >= 0
- || (predicated && recog_data.operand_type[i] == OP_OUT))
+ || (predicated && recog_data.operand_type[i] == OP_OUT
+ && verify_reg_tracked (recog_data.operand[i])))
{
recog_data.operand_type[i] = OP_INOUT;
if (matches >= 0