{
if (regno < FIRST_PSEUDO_REGISTER)
{
- if (SMALL_REGISTER_CLASSES)
+ if (targetm.small_register_classes_for_mode_p (GET_MODE (x)))
return 1;
*cost_p += 2;
}
return hash;
}
-/* Same as hash_rtx, but call CB on each rtx if it is not NULL.
+/* Same as hash_rtx, but call CB on each rtx if it is not NULL.
When the callback returns true, we continue with the new rtx. */
unsigned
return hash;
/* Invoke the callback first. */
- if (cb != NULL
+ if (cb != NULL
&& ((*cb) (x, mode, &newx, &newmode)))
{
hash += hash_rtx_cb (newx, newmode, do_not_record_p,
record = true;
else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
record = true;
- else if (SMALL_REGISTER_CLASSES)
+ else if (targetm.small_register_classes_for_mode_p (GET_MODE (x)))
record = false;
else if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (regno)))
record = false;
{
elt = CONST_VECTOR_ELT (x, i);
hash += hash_rtx_cb (elt, GET_MODE (elt),
- do_not_record_p, hash_arg_in_memory_p,
+ do_not_record_p, hash_arg_in_memory_p,
have_reg_qty, cb);
}
x = XEXP (x, i);
goto repeat;
}
-
+
hash += hash_rtx_cb (XEXP (x, i), VOIDmode, do_not_record_p,
hash_arg_in_memory_p,
have_reg_qty, cb);
They could e.g. be two different entities allocated into the
same space on the stack (see e.g. PR25130). In that case, the
MEM addresses can be the same, even though the two MEMs are
- absolutely not equivalent.
-
+ absolutely not equivalent.
+
But because really all MEM attributes should be the same for
equivalent MEMs, we just use the invariant that MEMs that have
the same attributes share the same mem_attrs data structure. */
constant through simplifications. */
p = lookup (folded_arg0, SAFE_HASH (folded_arg0, mode_arg0),
mode_arg0);
-
+
if (p != NULL)
{
cheapest_simplification = x;
for (i = 0; i < n_sets; i++)
{
+ bool repeat = false;
rtx src, dest;
rtx src_folded;
struct table_elt *elt = 0, *p;
break;
}
+ /* Try to optimize
+ (set (reg:M N) (const_int A))
+ (set (reg:M2 O) (const_int B))
+ (set (zero_extract:M2 (reg:M N) (const_int C) (const_int D))
+ (reg:M2 O)). */
+ if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT
+ && CONST_INT_P (trial)
+ && CONST_INT_P (XEXP (SET_DEST (sets[i].rtl), 1))
+ && CONST_INT_P (XEXP (SET_DEST (sets[i].rtl), 2))
+ && REG_P (XEXP (SET_DEST (sets[i].rtl), 0))
+ && (GET_MODE_BITSIZE (GET_MODE (SET_DEST (sets[i].rtl)))
+ >= INTVAL (XEXP (SET_DEST (sets[i].rtl), 1)))
+ && ((unsigned) INTVAL (XEXP (SET_DEST (sets[i].rtl), 1))
+ + (unsigned) INTVAL (XEXP (SET_DEST (sets[i].rtl), 2))
+ <= HOST_BITS_PER_WIDE_INT))
+ {
+ rtx dest_reg = XEXP (SET_DEST (sets[i].rtl), 0);
+ rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
+ rtx pos = XEXP (SET_DEST (sets[i].rtl), 2);
+ unsigned int dest_hash = HASH (dest_reg, GET_MODE (dest_reg));
+ struct table_elt *dest_elt
+ = lookup (dest_reg, dest_hash, GET_MODE (dest_reg));
+ rtx dest_cst = NULL;
+
+ if (dest_elt)
+ for (p = dest_elt->first_same_value; p; p = p->next_same_value)
+ if (p->is_const && CONST_INT_P (p->exp))
+ {
+ dest_cst = p->exp;
+ break;
+ }
+ if (dest_cst)
+ {
+ HOST_WIDE_INT val = INTVAL (dest_cst);
+ HOST_WIDE_INT mask;
+ unsigned int shift;
+ if (BITS_BIG_ENDIAN)
+ shift = GET_MODE_BITSIZE (GET_MODE (dest_reg))
+ - INTVAL (pos) - INTVAL (width);
+ else
+ shift = INTVAL (pos);
+ if (INTVAL (width) == HOST_BITS_PER_WIDE_INT)
+ mask = ~(HOST_WIDE_INT) 0;
+ else
+ mask = ((HOST_WIDE_INT) 1 << INTVAL (width)) - 1;
+ val &= ~(mask << shift);
+ val |= (INTVAL (trial) & mask) << shift;
+ val = trunc_int_for_mode (val, GET_MODE (dest_reg));
+ validate_unshare_change (insn, &SET_DEST (sets[i].rtl),
+ dest_reg, 1);
+ validate_unshare_change (insn, &SET_SRC (sets[i].rtl),
+ GEN_INT (val), 1);
+ if (apply_change_group ())
+ {
+ rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+ if (note)
+ {
+ remove_note (insn, note);
+ df_notes_rescan (insn);
+ }
+ src_eqv = NULL_RTX;
+ src_eqv_elt = NULL;
+ src_eqv_volatile = 0;
+ src_eqv_in_memory = 0;
+ src_eqv_hash = 0;
+ repeat = true;
+ break;
+ }
+ }
+ }
+
/* We don't normally have an insn matching (set (pc) (pc)), so
check for this separately here. We will delete such an
insn below.
}
}
+ /* If we changed the insn too much, handle this set from scratch. */
+ if (repeat)
+ {
+ i--;
+ continue;
+ }
+
src = SET_SRC (sets[i].rtl);
/* In general, it is good to have a SET with SET_SRC == SET_DEST.
describe the path.
It is filled with a queue of basic blocks, starting with FIRST_BB
and following a trace through the CFG.
-
+
If all paths starting at FIRST_BB have been followed, or no new path
starting at FIRST_BB can be constructed, this function returns FALSE.
Otherwise, DATA->path is filled and the function returns TRUE indicating
basic_block bb;
edge e;
int path_size;
-
+
SET_BIT (cse_visited_basic_blocks, first_bb->index);
/* See if there is a previous path. */
int path_entry;
/* Scan to end of each basic block in the path. */
- for (path_entry = 0; path_entry < path_size; path_entry++)
+ for (path_entry = 0; path_entry < path_size; path_entry++)
{
basic_block bb;
rtx insn;
&& GET_MODE (*loc) != GET_MODE (args->newreg))
{
validate_change (args->insn, loc, args->newreg, 1);
-
+
return -1;
}
return 0;
args.insn = insn;
args.newreg = newreg;
-
+
for_each_rtx (&PATTERN (insn), cse_change_cc_mode, &args);
for_each_rtx (®_NOTES (insn), cse_change_cc_mode, &args);
-
+
/* If the following assertion was triggered, there is most probably
something wrong with the cc_modes_compatible back end function.
CC modes only can be considered compatible if the insn - with the mode
XEXP (SET_SRC (set), 0))
&& rtx_equal_p (XEXP (cc_src, 1),
XEXP (SET_SRC (set), 1)))
-
+
{
comp_mode = targetm.cc_modes_compatible (mode, set_mode);
if (comp_mode != VOIDmode
{
RTL_PASS,
"cse1", /* name */
- gate_handle_cse, /* gate */
- rest_of_handle_cse, /* execute */
+ gate_handle_cse, /* gate */
+ rest_of_handle_cse, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
{
RTL_PASS,
"cse2", /* name */
- gate_handle_cse2, /* gate */
- rest_of_handle_cse2, /* execute */
+ gate_handle_cse2, /* gate */
+ rest_of_handle_cse2, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
{
RTL_PASS,
"cse_local", /* name */
- gate_handle_cse_after_global_opts, /* gate */
- rest_of_handle_cse_after_global_opts, /* execute */
+ gate_handle_cse_after_global_opts, /* gate */
+ rest_of_handle_cse_after_global_opts, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */