/* IRA processing allocno lives to build allocno live ranges.
- Copyright (C) 2006, 2007, 2008, 2009
+ Copyright (C) 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Vladimir Makarov <vmakarov@redhat.com>.
if (high_pressure_start_point[cl] >= 0
&& curr_reg_pressure[cl] <= ira_available_class_regs[cl])
high_pressure_start_point[cl] = -1;
-
+
}
}
sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a));
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
-
+
if (! REG_P (reg) || REGNO (reg) < FIRST_PSEUDO_REGISTER)
return advance_p;
-
+
a = ira_curr_regno_allocno_map[REGNO (reg)];
if (! reg_classes_intersect_p (cl, ALLOCNO_COVER_CLASS (a)))
return advance_p;
{
if (! reg_classes_intersect_p (def_cl, use_cl))
return advance_p;
-
+
advance_p = make_pseudo_conflict (recog_data.operand[use],
use_cl, dreg, advance_p);
/* Reload may end up swapping commutative operands, so you
different. (Indeed, if the constraints for the two
operands are the same for all alternatives, there's no
point marking them as commutative.) */
- if (use < recog_data.n_operands + 1
+ if (use < recog_data.n_operands - 1
&& recog_data.constraints[use][0] == '%')
advance_p
= make_pseudo_conflict (recog_data.operand[use + 1],
enum reg_class use_cl, acl;
bool advance_p;
rtx dreg = recog_data.operand[def];
-
+
if (def_cl == NO_REGS)
return;
-
+
if (GET_CODE (dreg) == SUBREG)
dreg = SUBREG_REG (dreg);
-
+
if (! REG_P (dreg) || REGNO (dreg) < FIRST_PSEUDO_REGISTER)
return;
-
+
a = ira_curr_regno_allocno_map[REGNO (dreg)];
acl = ALLOCNO_COVER_CLASS (a);
if (! reg_classes_intersect_p (acl, def_cl))
return;
-
+
advance_p = true;
-
+
for (use = 0; use < recog_data.n_operands; use++)
{
+ int alt1;
+
if (use == def || recog_data.operand_type[use] == OP_OUT)
continue;
-
+
if (recog_op_alt[use][alt].anything_ok)
use_cl = ALL_REGS;
else
use_cl = recog_op_alt[use][alt].cl;
-
+
+ /* If there's any alternative that allows USE to match DEF, do not
+ record a conflict. If that causes us to create an invalid
+ instruction due to the earlyclobber, reload must fix it up. */
+ for (alt1 = 0; alt1 < recog_data.n_alternatives; alt1++)
+ if (recog_op_alt[use][alt1].matches == def
+ || (use < recog_data.n_operands - 1
+ && recog_data.constraints[use][0] == '%'
+ && recog_op_alt[use + 1][alt1].matches == def)
+ || (use >= 1
+ && recog_data.constraints[use - 1][0] == '%'
+ && recog_op_alt[use - 1][alt1].matches == def))
+ break;
+
+ if (alt1 < recog_data.n_alternatives)
+ continue;
+
advance_p = check_and_make_def_use_conflict (dreg, def_cl, use,
use_cl, advance_p);
-
+
if ((use_match = recog_op_alt[use][alt].matches) >= 0)
{
if (use_match == def)
continue;
-
+
if (recog_op_alt[use_match][alt].anything_ok)
use_cl = ALL_REGS;
else
if (DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MUST_CLOBBER))
{
rtx dreg = DF_REF_REG (*def_rec);
-
+
if (GET_CODE (dreg) == SUBREG)
dreg = SUBREG_REG (dreg);
if (! REG_P (dreg) || REGNO (dreg) >= FIRST_PSEUDO_REGISTER)
/* Hard register clobbers are believed to be early clobber
because there is no way to say that non-operand hard
- register clobbers are not early ones. */
+ register clobbers are not early ones. */
if (live_p)
mark_ref_live (*def_rec);
else
&& GET_MODE (equiv_const) == VOIDmode))))
return NO_REGS;
break;
-
+
case 's':
if ((CONSTANT_P (op) && !CONST_INT_P (op)
&& (GET_CODE (op) != CONST_DOUBLE || GET_MODE (op) != VOIDmode))
|| GET_MODE (equiv_const) != VOIDmode)))
return NO_REGS;
break;
-
+
case 'I':
case 'J':
case 'K':
c, constraints)))
return NO_REGS;
break;
-
+
case 'E':
case 'F':
if (GET_CODE (op) == CONST_DOUBLE
== MODE_VECTOR_FLOAT)))))
return NO_REGS;
break;
-
+
case 'G':
case 'H':
if ((GET_CODE (op) == CONST_DOUBLE
return NO_REGS;
cl = next_cl;
break;
-
+
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
next_cl
return NO_REGS;
cl = next_cl;
break;
-
+
default:
return NO_REGS;
}
void
ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set)
{
- int i, c, regno;
+ int i, c, regno = 0;
bool ignore_p;
enum reg_class cl;
rtx op;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
-
+
if (GET_CODE (op) == SCRATCH
|| (REG_P (op) && (regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER))
{
? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT (c, p));
if (cl != NO_REGS
+ /* There is no register pressure problem if all of the
+ regs in this class are fixed. */
+ && ira_available_class_regs[cl] != 0
&& (ira_available_class_regs[cl]
<= ira_reg_class_nregs[cl][mode]))
IOR_HARD_REG_SET (*set, reg_class_contents[cl]);
{
int i, regno, cost;
unsigned int px;
- enum reg_class cl, cover_class;
+ enum reg_class cl;
rtx operand;
ira_allocno_t operand_a, a;
if (GET_CODE (operand) == SUBREG)
operand = SUBREG_REG (operand);
-
+
if (REG_P (operand)
&& (regno = REGNO (operand)) >= FIRST_PSEUDO_REGISTER)
{
[ira_class_hard_regs[cl][0]]) >= 0
&& reg_class_size[cl] <= (unsigned) CLASS_MAX_NREGS (cl, mode))
{
+ int i, size;
cost
= (freq
* (in_p
: ira_get_register_move_cost (mode, cl, cover_class)));
ira_allocate_and_set_costs
(&ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a), cover_class, 0);
- ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a)
- [ira_class_hard_reg_index
- [cover_class][ira_class_hard_regs[cl][0]]]
- -= cost;
+ size = ira_reg_class_nregs[cover_class][mode];
+ for (i = 0; i < size; i++)
+ ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a)
+ [ira_class_hard_reg_index
+ [cover_class][ira_class_hard_regs[cl][i]]]
+ -= cost;
}
}
EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, px)
{
a = ira_allocnos[px];
- cover_class = ALLOCNO_COVER_CLASS (a);
if (a != operand_a)
{
/* We could increase costs of A instead of making it
{
edge e;
edge_iterator ei;
-
+
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
if (TEST_HARD_REG_BIT (hard_regs_live, i))
{
enum reg_class cover_class, cl;
-
+
cover_class = ira_class_translate[REGNO_REG_CLASS (i)];
for (j = 0;
(cl = ira_reg_class_super_classes[cover_class][j])
EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
{
ira_allocno_t a = ira_curr_regno_allocno_map[j];
-
+
if (a == NULL)
continue;
ira_assert (! sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)));
set_allocno_live (a);
make_regno_born (j);
}
-
+
freq = REG_FREQ_FROM_BB (bb);
if (freq == 0)
freq = 1;
{
df_ref *def_rec, *use_rec;
bool call_p;
-
+
if (!NONDEBUG_INSN_P (insn))
continue;
-
+
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Insn %u(l%d): point = %d\n",
INSN_UID (insn), loop_tree_node->parent->loop->num,
}
}
}
-
+
extract_insn (insn);
preprocess_constraints ();
process_single_reg_class_operands (false, freq);
-
+
/* See which defined values die here. */
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
if (!call_p || !DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MAY_CLOBBER))
EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
{
ira_allocno_t a = ira_allocnos[i];
-
+
if (allocno_saved_at_call[i] != last_call_num)
/* Here we are mimicking caller-save.c behaviour
which does not save hard register at a call if
}
}
}
-
+
make_early_clobber_and_input_conflicts ();
curr_point++;
mark_ref_live (*use_rec);
process_single_reg_class_operands (true, freq);
-
+
set_p = mark_hard_reg_early_clobbers (insn, true);
if (set_p)
for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
{
rtx ureg = DF_REF_REG (*use_rec);
-
+
if (GET_CODE (ureg) == SUBREG)
ureg = SUBREG_REG (ureg);
if (! REG_P (ureg) || REGNO (ureg) >= FIRST_PSEUDO_REGISTER)
continue;
-
+
mark_ref_live (*use_rec);
}
}
allocno_live_range_t r;
bitmap born_or_died;
bitmap_iterator bi;
-
+
born_or_died = ira_allocate_bitmap ();
FOR_EACH_ALLOCNO (a, ai)
{