/* Register renaming for the GNU compiler.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010 Free Software Foundation, Inc.
This file is part of GCC.
add_to_hard_reg_set (&chain->hard_conflicts, GET_MODE (x), REGNO (x));
}
+/* Create a new chain for THIS_NREGS registers starting at THIS_REGNO,
+ and record its occurrence in *LOC, which is being written to in INSN.
+ This access requires a register of class CL. */
+
+static void
+create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
+ rtx insn, enum reg_class cl)
+{
+ struct du_head *head = XOBNEW (&rename_obstack, struct du_head);
+ struct du_chain *this_du;
+ int nregs;
+
+ head->next_chain = open_chains;
+ open_chains = head;
+ head->regno = this_regno;
+ head->nregs = this_nregs;
+ head->need_caller_save_reg = 0;
+ head->cannot_rename = 0;
+ head->terminated = 0;
+
+ VEC_safe_push (du_head_p, heap, id_to_chain, head);
+ head->id = current_id++;
+
+ bitmap_initialize (&head->conflicts, &bitmap_default_obstack);
+ bitmap_copy (&head->conflicts, &open_chains_set);
+ 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 and track it in
+ live_in_chains instead. */
+ nregs = head->nregs;
+ while (nregs-- > 0)
+ {
+ 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);
+
+ open_chains = head;
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Creating chain %s (%d)",
+ reg_names[head->regno], head->id);
+ if (insn != NULL_RTX)
+ fprintf (dump_file, " at insn %d", INSN_UID (insn));
+ fprintf (dump_file, "\n");
+ }
+
+ if (insn == NULL_RTX)
+ {
+ head->first = head->last = NULL;
+ return;
+ }
+
+ this_du = XOBNEW (&rename_obstack, struct du_chain);
+ head->first = head->last = this_du;
+
+ this_du->next_use = 0;
+ this_du->loc = loc;
+ this_du->insn = insn;
+ this_du->cl = cl;
+}
+
static void
scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
enum op_type type)
if (action == mark_write)
{
if (type == OP_OUT)
- {
- struct du_head *head = XOBNEW (&rename_obstack, struct du_head);
- struct du_chain *this_du = XOBNEW (&rename_obstack, struct du_chain);
- int nregs;
-
- head->next_chain = open_chains;
- open_chains = head;
- head->first = head->last = this_du;
- head->regno = this_regno;
- head->nregs = this_nregs;
- head->need_caller_save_reg = 0;
- head->cannot_rename = 0;
- head->terminated = 0;
-
- VEC_safe_push (du_head_p, heap, id_to_chain, head);
- head->id = current_id++;
-
- bitmap_initialize (&head->conflicts, &bitmap_default_obstack);
- bitmap_copy (&head->conflicts, &open_chains_set);
- 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 and track it in
- live_in_chains instead. */
- nregs = head->nregs;
- while (nregs-- > 0)
- {
- 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);
-
- open_chains = head;
-
- this_du->next_use = 0;
- this_du->loc = loc;
- this_du->insn = insn;
- this_du->cl = cl;
-
- if (dump_file)
- fprintf (dump_file,
- "Creating chain %s (%d) at insn %d (%s)\n",
- reg_names[head->regno], head->id, INSN_UID (insn),
- scan_actions_name[(int) action]);
- }
+ create_new_chain (this_regno, this_nregs, loc, insn, cl);
return;
}
this_du->loc = loc;
this_du->insn = insn;
this_du->cl = cl;
- head->last->next_use = this_du;
+ if (head->first == NULL)
+ head->first = this_du;
+ else
+ head->last->next_use = this_du;
head->last = this_du;
}
return;
case STRICT_LOW_PART:
- scan_rtx (insn, &XEXP (x, 0), cl, action, OP_INOUT);
+ scan_rtx (insn, &XEXP (x, 0), cl, action,
+ verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT);
return;
case ZERO_EXTRACT:
case SIGN_EXTRACT:
scan_rtx (insn, &XEXP (x, 0), cl, action,
- type == OP_IN ? OP_IN : OP_INOUT);
+ (type == OP_IN ? OP_IN :
+ verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT));
scan_rtx (insn, &XEXP (x, 1), cl, action, OP_IN);
scan_rtx (insn, &XEXP (x, 2), cl, action, OP_IN);
return;
predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
for (i = 0; i < n_ops; ++i)
{
+ rtx op = recog_data.operand[i];
int matches = recog_op_alt[i][alt].matches;
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
- && verify_reg_tracked (recog_data.operand[i])))
+ || (predicated && recog_data.operand_type[i] == OP_OUT))
{
- rtx op = recog_data.operand[i];
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
untracked_operands |= 1 << matches;
}
}
+ /* If there's an in-out operand with a register that is not
+ being tracked at all yet, open a chain. */
+ if (recog_data.operand_type[i] == OP_INOUT
+ && !(untracked_operands & (1 << i))
+ && REG_P (op)
+ && !verify_reg_tracked (op))
+ {
+ enum machine_mode mode = GET_MODE (op);
+ unsigned this_regno = REGNO (op);
+ unsigned this_nregs = hard_regno_nregs[this_regno][mode];
+ create_new_chain (this_regno, this_nregs, NULL, NULL_RTX,
+ NO_REGS);
+ }
}
if (fail_current_block)