#include "except.h"
#include "target.h"
#include "params.h"
+#include "rtlhooks-def.h"
/* The basic idea of common subexpression elimination is to go
through the code, keeping a record of expressions that would
/* Whether it should be taken or not. AROUND is the same as taken
except that it is used when the destination label is not preceded
by a BARRIER. */
- enum taken {TAKEN, NOT_TAKEN, AROUND} status;
+ enum taken {PATH_TAKEN, PATH_NOT_TAKEN, PATH_AROUND} status;
} *path;
};
static int notreg_cost (rtx, enum rtx_code);
static int approx_reg_cost_1 (rtx *, void *);
static int approx_reg_cost (rtx);
-static int preferrable (int, int, int, int);
+static int preferable (int, int, int, int);
static void new_basic_block (void);
static void make_new_qty (unsigned int, enum machine_mode);
static void make_regs_eqv (unsigned int, unsigned int);
static void record_jump_cond (enum rtx_code, enum machine_mode, rtx, rtx,
int);
static void cse_insn (rtx, rtx);
+static void cse_end_of_basic_block (rtx, struct cse_basic_block_data *,
+ int, int, int);
static int addr_affects_sp_p (rtx);
static void invalidate_from_clobbers (rtx);
static rtx cse_process_notes (rtx, rtx);
static void cse_change_cc_mode_insns (rtx, rtx, rtx);
static enum machine_mode cse_cc_succs (basic_block, rtx, rtx, bool);
\f
+
+#undef RTL_HOOKS_GEN_LOWPART
+#define RTL_HOOKS_GEN_LOWPART gen_lowpart_if_possible
+
+static const struct rtl_hooks cse_rtl_hooks = RTL_HOOKS_INITIALIZER;
+\f
/* Nonzero if X has the form (PLUS frame-pointer integer). We check for
virtual regs here because the simplify_*_operation routines are called
by integrate.c, which is called before virtual register instantiation. */
Return a positive value if A is less desirable, or 0 if the two are
equally good. */
static int
-preferrable (int cost_a, int regcost_a, int cost_b, int regcost_b)
+preferable (int cost_a, int regcost_a, int cost_b, int regcost_b)
{
/* First, get rid of cases involving expressions that are entirely
unwanted. */
: rtx_cost (x, outer) * 2);
}
-/* Return an estimate of the cost of computing rtx X.
- One use is in cse, to decide which expression to keep in the hash table.
- Another is in rtl generation, to pick the cheapest way to multiply.
- Other uses like the latter are expected in the future. */
-
-int
-rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED)
-{
- int i, j;
- enum rtx_code code;
- const char *fmt;
- int total;
-
- if (x == 0)
- return 0;
-
- /* Compute the default costs of certain things.
- Note that targetm.rtx_costs can override the defaults. */
-
- code = GET_CODE (x);
- switch (code)
- {
- case MULT:
- total = COSTS_N_INSNS (5);
- break;
- case DIV:
- case UDIV:
- case MOD:
- case UMOD:
- total = COSTS_N_INSNS (7);
- break;
- case USE:
- /* Used in loop.c and combine.c as a marker. */
- total = 0;
- break;
- default:
- total = COSTS_N_INSNS (1);
- }
-
- switch (code)
- {
- case REG:
- return 0;
-
- case SUBREG:
- /* If we can't tie these modes, make this expensive. The larger
- the mode, the more expensive it is. */
- if (! MODES_TIEABLE_P (GET_MODE (x), GET_MODE (SUBREG_REG (x))))
- return COSTS_N_INSNS (2
- + GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD);
- break;
-
- default:
- if ((*targetm.rtx_costs) (x, code, outer_code, &total))
- return total;
- break;
- }
-
- /* Sum the costs of the sub-rtx's, plus cost of this operation,
- which is already in total. */
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- total += rtx_cost (XEXP (x, i), code);
- else if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (x, i); j++)
- total += rtx_cost (XVECEXP (x, i, j), code);
-
- return total;
-}
-\f
-/* Return cost of address expression X.
- Expect that X is properly formed address reference. */
-
-int
-address_cost (rtx x, enum machine_mode mode)
-{
- /* The address_cost target hook does not deal with ADDRESSOF nodes. But,
- during CSE, such nodes are present. Using an ADDRESSOF node which
- refers to the address of a REG is a good thing because we can then
- turn (MEM (ADDRESSSOF (REG))) into just plain REG. */
-
- if (GET_CODE (x) == ADDRESSOF && REG_P (XEXP ((x), 0)))
- return -1;
-
- /* We may be asked for cost of various unusual addresses, such as operands
- of push instruction. It is not worthwhile to complicate writing
- of the target hook by such cases. */
-
- if (!memory_address_p (mode, x))
- return 1000;
-
- return (*targetm.address_cost) (x);
-}
-
-/* If the target doesn't override, compute the cost as with arithmetic. */
-
-int
-default_address_cost (rtx x)
-{
- return rtx_cost (x, MEM);
-}
\f
static struct cse_reg_info *
get_cse_reg_info (unsigned int regno)
unsigned int regno = REGNO (x);
unsigned int endregno
= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
- : HARD_REGNO_NREGS (regno, GET_MODE (x)));
+ : hard_regno_nregs[regno][GET_MODE (x)]);
unsigned int i;
for (i = regno; i < endregno; i++)
call that expensive function in the most common case where the only
use of the register is in the comparison. */
- if (code == COMPARE || GET_RTX_CLASS (code) == '<')
+ if (code == COMPARE || COMPARISON_P (x))
{
if (GET_CODE (XEXP (x, 0)) == REG
&& ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 0))))
If necessary, update table showing constant values of quantities. */
#define CHEAPER(X, Y) \
- (preferrable ((X)->cost, (X)->regcost, (Y)->cost, (Y)->regcost) < 0)
+ (preferable ((X)->cost, (X)->regcost, (Y)->cost, (Y)->regcost) < 0)
static struct table_elt *
insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mode)
if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
{
unsigned int regno = REGNO (x);
- unsigned int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+ unsigned int endregno = regno + hard_regno_nregs[regno][GET_MODE (x)];
unsigned int i;
for (i = regno; i < endregno; i++)
int exp_q = REG_QTY (REGNO (classp->exp));
struct qty_table_elem *exp_ent = &qty_table[exp_q];
- exp_ent->const_rtx = gen_lowpart_if_possible (exp_ent->mode, x);
+ exp_ent->const_rtx = gen_lowpart (exp_ent->mode, x);
exp_ent->const_insn = this_insn;
}
struct qty_table_elem *x_ent = &qty_table[x_q];
x_ent->const_rtx
- = gen_lowpart_if_possible (GET_MODE (x), p->exp);
+ = gen_lowpart (GET_MODE (x), p->exp);
x_ent->const_insn = this_insn;
break;
}
HOST_WIDE_INT in_table
= TEST_HARD_REG_BIT (hard_regs_in_table, regno);
unsigned int endregno
- = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+ = regno + hard_regno_nregs[regno][GET_MODE (x)];
unsigned int tregno, tendregno, rn;
struct table_elt *p, *next;
tregno = REGNO (p->exp);
tendregno
- = tregno + HARD_REGNO_NREGS (tregno, GET_MODE (p->exp));
+ = tregno + hard_regno_nregs[tregno][GET_MODE (p->exp)];
if (tendregno > regno && tregno < endregno)
remove_from_table (p, hash);
}
continue;
regno = REGNO (p->exp);
- endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (p->exp));
+ endregno = regno + hard_regno_nregs[regno][GET_MODE (p->exp)];
for (i = regno; i < endregno; i++)
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
unsigned int regno = REGNO (y);
unsigned int endregno
= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
- : HARD_REGNO_NREGS (regno, GET_MODE (y)));
+ : hard_regno_nregs[regno][GET_MODE (y)]);
unsigned int i;
/* If the quantities are not the same, the expressions are not
code on the Alpha for unaligned byte stores. */
if (flag_expensive_optimizations
- && (GET_RTX_CLASS (GET_CODE (*loc)) == '2'
- || GET_RTX_CLASS (GET_CODE (*loc)) == 'c')
+ && ARITHMETIC_P (*loc)
&& GET_CODE (XEXP (*loc, 0)) == REG)
{
rtx op1 = XEXP (*loc, 1);
/* If ARG1 is a comparison operator and CODE is testing for
STORE_FLAG_VALUE, get the inner arguments. */
- else if (GET_RTX_CLASS (GET_CODE (arg1)) == '<')
+ else if (COMPARISON_P (arg1))
{
#ifdef FLOAT_STORE_FLAG_VALUE
REAL_VALUE_TYPE fsfv;
REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
- && GET_RTX_CLASS (GET_CODE (p->exp)) == '<'))
+ && COMPARISON_P (p->exp)))
{
x = p->exp;
break;
REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
- && GET_RTX_CLASS (GET_CODE (p->exp)) == '<')
+ && COMPARISON_P (p->exp))
{
reverse_code = 1;
x = p->exp;
else
code = reversed;
}
- else if (GET_RTX_CLASS (GET_CODE (x)) == '<')
+ else if (COMPARISON_P (x))
code = GET_CODE (x);
arg1 = XEXP (x, 0), arg2 = XEXP (x, 1);
}
enum rtx_code eltcode = GET_CODE (elt->exp);
/* Just check for unary and binary operations. */
- if (GET_RTX_CLASS (GET_CODE (elt->exp)) == '1'
- && GET_CODE (elt->exp) != SIGN_EXTEND
- && GET_CODE (elt->exp) != ZERO_EXTEND
+ if (UNARY_P (elt->exp)
+ && eltcode != SIGN_EXTEND
+ && eltcode != ZERO_EXTEND
&& GET_CODE (XEXP (elt->exp, 0)) == SUBREG
&& GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) == mode
&& (GET_MODE_CLASS (mode)
new = simplify_unary_operation (GET_CODE (elt->exp), mode,
op0, mode);
}
- else if ((GET_RTX_CLASS (GET_CODE (elt->exp)) == '2'
- || GET_RTX_CLASS (GET_CODE (elt->exp)) == 'c')
+ else if (ARITHMETIC_P (elt->exp)
&& eltcode != DIV && eltcode != MOD
&& eltcode != UDIV && eltcode != UMOD
&& eltcode != ASHIFTRT && eltcode != LSHIFTRT
if (((BYTES_BIG_ENDIAN
&& offset == GET_MODE_SIZE (GET_MODE (constant)) - 1)
|| (! BYTES_BIG_ENDIAN && offset == 0))
- && (new = gen_lowpart_if_possible (mode, constant)) != 0)
+ && (new = gen_lowpart (mode, constant)) != 0)
return new;
}
&& GET_CODE (arg_ent->const_rtx) != REG
&& GET_CODE (arg_ent->const_rtx) != PLUS)
const_arg
- = gen_lowpart_if_possible (GET_MODE (arg),
+ = gen_lowpart (GET_MODE (arg),
arg_ent->const_rtx);
}
break;
|| (new_cost == old_cost && CONSTANT_P (XEXP (x, i))))
break;
+ /* It's not safe to substitute the operand of a conversion
+ operator with a constant, as the conversion's identity
+ depends upon the mode of it's operand. This optimization
+ is handled by the call to simplify_unary_operation. */
+ if (GET_RTX_CLASS (code) == RTX_UNARY
+ && GET_MODE (replacements[j]) != mode_arg0
+ && (code == ZERO_EXTEND
+ || code == SIGN_EXTEND
+ || code == TRUNCATE
+ || code == FLOAT_TRUNCATE
+ || code == FLOAT_EXTEND
+ || code == FLOAT
+ || code == FIX
+ || code == UNSIGNED_FLOAT
+ || code == UNSIGNED_FIX))
+ continue;
+
if (validate_change (insn, &XEXP (x, i), replacements[j], 0))
break;
- if (code == NE || code == EQ || GET_RTX_CLASS (code) == 'c'
- || code == LTGT || code == UNEQ || code == ORDERED
- || code == UNORDERED)
+ if (GET_RTX_CLASS (code) == RTX_COMM_COMPARE
+ || GET_RTX_CLASS (code) == RTX_COMM_ARITH)
{
validate_change (insn, &XEXP (x, i), XEXP (x, 1 - i), 1);
validate_change (insn, &XEXP (x, 1 - i), replacements[j], 1);
operand unless the first operand is also a constant integer. Otherwise,
place any constant second unless the first operand is also a constant. */
- if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c'
- || code == LTGT || code == UNEQ || code == ORDERED
- || code == UNORDERED)
+ if (COMMUTATIVE_P (x))
{
if (must_swap
|| swap_commutative_operands_p (const_arg0 ? const_arg0
switch (GET_RTX_CLASS (code))
{
- case '1':
+ case RTX_UNARY:
{
int is_const = 0;
}
break;
- case '<':
+ case RTX_COMPARE:
+ case RTX_COMM_COMPARE:
/* See what items are actually being compared and set FOLDED_ARG[01]
to those values and CODE to the actual comparison code. If any are
constant, set CONST_ARG0 and CONST_ARG1 appropriately. We needn't
}
}
- new = simplify_relational_operation (code,
- (mode_arg0 != VOIDmode
- ? mode_arg0
- : (GET_MODE (const_arg0
- ? const_arg0
- : folded_arg0)
- != VOIDmode)
- ? GET_MODE (const_arg0
- ? const_arg0
- : folded_arg0)
- : GET_MODE (const_arg1
- ? const_arg1
- : folded_arg1)),
- const_arg0 ? const_arg0 : folded_arg0,
- const_arg1 ? const_arg1 : folded_arg1);
-#ifdef FLOAT_STORE_FLAG_VALUE
- if (new != 0 && GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- if (new == const0_rtx)
- new = CONST0_RTX (mode);
- else
- new = (CONST_DOUBLE_FROM_REAL_VALUE
- (FLOAT_STORE_FLAG_VALUE (mode), mode));
- }
-#endif
+ {
+ rtx op0 = const_arg0 ? const_arg0 : folded_arg0;
+ rtx op1 = const_arg1 ? const_arg1 : folded_arg1;
+ new = simplify_relational_operation (code, mode, mode_arg0, op0, op1);
+ }
break;
- case '2':
- case 'c':
+ case RTX_BIN_ARITH:
+ case RTX_COMM_ARITH:
switch (code)
{
case PLUS:
const_arg1 ? const_arg1 : folded_arg1);
break;
- case 'o':
+ case RTX_OBJ:
/* (lo_sum (high X) X) is simply X. */
if (code == LO_SUM && const_arg0 != 0
&& GET_CODE (const_arg0) == HIGH
return const_arg1;
break;
- case '3':
- case 'b':
+ case RTX_TERNARY:
+ case RTX_BITFIELD_OPS:
new = simplify_ternary_operation (code, mode, mode_arg0,
const_arg0 ? const_arg0 : folded_arg0,
const_arg1 ? const_arg1 : folded_arg1,
const_arg2 ? const_arg2 : XEXP (x, 2));
break;
- case 'x':
- /* Eliminate CONSTANT_P_RTX if its constant. */
- if (code == CONSTANT_P_RTX)
- {
- if (const_arg0)
- return const1_rtx;
- if (optimize == 0 || !flag_gcse)
- return const0_rtx;
- }
+ default:
break;
}
struct qty_table_elem *x_ent = &qty_table[x_q];
if (x_ent->const_rtx)
- x = gen_lowpart_if_possible (GET_MODE (x), x_ent->const_rtx);
+ x = gen_lowpart (GET_MODE (x), x_ent->const_rtx);
}
if (x == 0 || CONSTANT_P (x))
If the requested operation cannot be done, 0 is returned.
- This is similar to gen_lowpart in emit-rtl.c. */
+ This is similar to gen_lowpart_general in emit-rtl.c. */
rtx
gen_lowpart_if_possible (enum machine_mode mode, rtx x)
return 0;
}
\f
-/* Given INSN, a jump insn, TAKEN indicates if we are following the "taken"
+/* Given INSN, a jump insn, PATH_TAKEN indicates if we are following the "taken"
branch. It will be zero if not.
In certain cases, this can cause us to add an equivalence. For example,
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
- rtx tem = gen_lowpart_if_possible (inner_mode, op1);
+ rtx tem = gen_lowpart (inner_mode, op1);
record_jump_cond (code, mode, SUBREG_REG (op0),
tem ? tem : gen_rtx_SUBREG (inner_mode, op1, 0),
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
- rtx tem = gen_lowpart_if_possible (inner_mode, op0);
+ rtx tem = gen_lowpart (inner_mode, op0);
record_jump_cond (code, mode, SUBREG_REG (op1),
tem ? tem : gen_rtx_SUBREG (inner_mode, op0, 0),
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
- rtx tem = gen_lowpart_if_possible (inner_mode, op1);
+ rtx tem = gen_lowpart (inner_mode, op1);
record_jump_cond (code, mode, SUBREG_REG (op0),
tem ? tem : gen_rtx_SUBREG (inner_mode, op1, 0),
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
- rtx tem = gen_lowpart_if_possible (inner_mode, op0);
+ rtx tem = gen_lowpart (inner_mode, op0);
record_jump_cond (code, mode, SUBREG_REG (op1),
tem ? tem : gen_rtx_SUBREG (inner_mode, op0, 0),
/* It is no longer clear why we used to do this, but it doesn't
appear to still be needed. So let's try without it since this
code hurts cse'ing widened ops. */
- /* If source is a perverse subreg (such as QI treated as an SI),
+ /* If source is a paradoxical subreg (such as QI treated as an SI),
treat it as volatile. It may do the work of an SI in one context
where the extra bits are not being used, but cannot replace an SI
in general. */
const_elt; const_elt = const_elt->next_same_value)
if (GET_CODE (const_elt->exp) == REG)
{
- src_related = gen_lowpart_if_possible (mode,
+ src_related = gen_lowpart (mode,
const_elt->exp);
break;
}
GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
tmode = GET_MODE_WIDER_MODE (tmode))
{
- rtx inner = gen_lowpart_if_possible (tmode, XEXP (src, 0));
+ rtx inner = gen_lowpart (tmode, XEXP (src, 0));
struct table_elt *larger_elt;
if (inner)
if (GET_CODE (larger_elt->exp) == REG)
{
src_related
- = gen_lowpart_if_possible (mode, larger_elt->exp);
+ = gen_lowpart (mode, larger_elt->exp);
break;
}
/* See if a MEM has already been loaded with a widening operation;
if it has, we can use a subreg of that. Many CISC machines
also have such operations, but this is only likely to be
- beneficial these machines. */
+ beneficial on these machines. */
if (flag_expensive_optimizations && src_related == 0
&& (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
larger_elt; larger_elt = larger_elt->next_same_value)
if (GET_CODE (larger_elt->exp) == REG)
{
- src_related = gen_lowpart_if_possible (mode,
+ src_related = gen_lowpart (mode,
larger_elt->exp);
break;
}
of equal cost, use this order:
src_folded, src, src_eqv, src_related and hash table entry. */
if (src_folded
- && preferrable (src_folded_cost, src_folded_regcost,
- src_cost, src_regcost) <= 0
- && preferrable (src_folded_cost, src_folded_regcost,
- src_eqv_cost, src_eqv_regcost) <= 0
- && preferrable (src_folded_cost, src_folded_regcost,
- src_related_cost, src_related_regcost) <= 0
- && preferrable (src_folded_cost, src_folded_regcost,
- src_elt_cost, src_elt_regcost) <= 0)
+ && preferable (src_folded_cost, src_folded_regcost,
+ src_cost, src_regcost) <= 0
+ && preferable (src_folded_cost, src_folded_regcost,
+ src_eqv_cost, src_eqv_regcost) <= 0
+ && preferable (src_folded_cost, src_folded_regcost,
+ src_related_cost, src_related_regcost) <= 0
+ && preferable (src_folded_cost, src_folded_regcost,
+ src_elt_cost, src_elt_regcost) <= 0)
{
trial = src_folded, src_folded_cost = MAX_COST;
if (src_folded_force_flag)
}
}
else if (src
- && preferrable (src_cost, src_regcost,
- src_eqv_cost, src_eqv_regcost) <= 0
- && preferrable (src_cost, src_regcost,
- src_related_cost, src_related_regcost) <= 0
- && preferrable (src_cost, src_regcost,
- src_elt_cost, src_elt_regcost) <= 0)
+ && preferable (src_cost, src_regcost,
+ src_eqv_cost, src_eqv_regcost) <= 0
+ && preferable (src_cost, src_regcost,
+ src_related_cost, src_related_regcost) <= 0
+ && preferable (src_cost, src_regcost,
+ src_elt_cost, src_elt_regcost) <= 0)
trial = src, src_cost = MAX_COST;
else if (src_eqv_here
- && preferrable (src_eqv_cost, src_eqv_regcost,
- src_related_cost, src_related_regcost) <= 0
- && preferrable (src_eqv_cost, src_eqv_regcost,
- src_elt_cost, src_elt_regcost) <= 0)
+ && preferable (src_eqv_cost, src_eqv_regcost,
+ src_related_cost, src_related_regcost) <= 0
+ && preferable (src_eqv_cost, src_eqv_regcost,
+ src_elt_cost, src_elt_regcost) <= 0)
trial = copy_rtx (src_eqv_here), src_eqv_cost = MAX_COST;
else if (src_related
- && preferrable (src_related_cost, src_related_regcost,
- src_elt_cost, src_elt_regcost) <= 0)
+ && preferable (src_related_cost, src_related_regcost,
+ src_elt_cost, src_elt_regcost) <= 0)
trial = copy_rtx (src_related), src_related_cost = MAX_COST;
else
{
&& (GET_CODE (sets[i].orig_src) == REG
|| GET_CODE (sets[i].orig_src) == SUBREG
|| GET_CODE (sets[i].orig_src) == MEM))
- simplify_replace_rtx (REG_NOTES (libcall_insn),
- sets[i].orig_src, copy_rtx (new));
+ {
+ rtx note = find_reg_equal_equiv_note (libcall_insn);
+ if (note != 0)
+ XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0),
+ sets[i].orig_src,
+ copy_rtx (new));
+ }
/* The result of apply_change_group can be ignored; see
canon_reg. */
#ifdef PUSH_ROUNDING
/* Stack pushes invalidate the stack pointer. */
rtx addr = XEXP (dest, 0);
- if (GET_RTX_CLASS (GET_CODE (addr)) == 'a'
+ if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC
&& XEXP (addr, 0) == stack_pointer_rtx)
invalidate (stack_pointer_rtx, Pmode);
#endif
and hope for the best. */
if (n_sets == 1)
{
- rtx new = emit_jump_insn_after (gen_jump (XEXP (src, 0)), insn);
+ rtx new, note;
+ new = emit_jump_insn_after (gen_jump (XEXP (src, 0)), insn);
JUMP_LABEL (new) = XEXP (src, 0);
LABEL_NUSES (XEXP (src, 0))++;
+
+ /* Make sure to copy over REG_NON_LOCAL_GOTO. */
+ note = find_reg_note (insn, REG_NON_LOCAL_GOTO, 0);
+ if (note)
+ {
+ XEXP (note, 1) = NULL_RTX;
+ REG_NOTES (new) = note;
+ }
+
delete_insn (insn);
insn = new;
else
INSN_CODE (insn) = -1;
- never_reached_warning (insn, NULL);
-
/* Do not bother deleting any unreachable code,
let jump/flow do that. */
unsigned int regno = REGNO (x);
unsigned int endregno
= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
- : HARD_REGNO_NREGS (regno, GET_MODE (x)));
+ : hard_regno_nregs[regno][GET_MODE (x)]);
unsigned int i;
for (i = regno; i < endregno; i++)
we are also doing (set (reg:m2 foo) (subreg:m2 (bar:m1) 0)) so
make that equivalence as well.
- However, BAR may have equivalences for which gen_lowpart_if_possible
- will produce a simpler value than gen_lowpart_if_possible applied to
+ However, BAR may have equivalences for which gen_lowpart
+ will produce a simpler value than gen_lowpart applied to
BAR (e.g., if BAR was ZERO_EXTENDed from M2), so we will scan all
BAR's equivalences. If we don't get a simplified form, make
the SUBREG. It will not be used in an equivalence, but will
static int
addr_affects_sp_p (rtx addr)
{
- if (GET_RTX_CLASS (GET_CODE (addr)) == 'a'
+ if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC
&& GET_CODE (XEXP (addr, 0)) == REG
&& REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
{
&& (CONSTANT_P (ent->const_rtx)
|| GET_CODE (ent->const_rtx) == REG))
{
- rtx new = gen_lowpart_if_possible (GET_MODE (x), ent->const_rtx);
+ rtx new = gen_lowpart (GET_MODE (x), ent->const_rtx);
if (new)
return new;
}
the current block. The incoming structure's branch path, if any, is used
to construct the output branch path. */
-void
+static void
cse_end_of_basic_block (rtx insn, struct cse_basic_block_data *data,
int follow_jumps, int after_loop, int skip_blocks)
{
int i;
/* Update the previous branch path, if any. If the last branch was
- previously TAKEN, mark it NOT_TAKEN. If it was previously NOT_TAKEN,
+ previously PATH_TAKEN, mark it PATH_NOT_TAKEN.
+ If it was previously PATH_NOT_TAKEN,
shorten the path by one and look at the previous branch. We know that
at least one branch must have been taken if PATH_SIZE is nonzero. */
while (path_size > 0)
{
- if (data->path[path_size - 1].status != NOT_TAKEN)
+ if (data->path[path_size - 1].status != PATH_NOT_TAKEN)
{
- data->path[path_size - 1].status = NOT_TAKEN;
+ data->path[path_size - 1].status = PATH_NOT_TAKEN;
break;
}
else
take it, do so. */
if (path_entry < path_size && data->path[path_entry].branch == p)
{
- if (data->path[path_entry].status != NOT_TAKEN)
+ if (data->path[path_entry].status != PATH_NOT_TAKEN)
p = JUMP_LABEL (p);
/* Point to next entry in path, if any. */
break;
data->path[path_entry].branch = p;
- data->path[path_entry++].status = TAKEN;
+ data->path[path_entry++].status = PATH_TAKEN;
/* This branch now ends our path. It was possible that we
didn't see this branch the last time around (when the
if (tmp == q)
{
data->path[path_entry].branch = p;
- data->path[path_entry++].status = AROUND;
+ data->path[path_entry++].status = PATH_AROUND;
path_size = path_entry;
/* If all jumps in the path are not taken, set our path length to zero
so a rescan won't be done. */
for (i = path_size - 1; i >= 0; i--)
- if (data->path[i].status != NOT_TAKEN)
+ if (data->path[i].status != PATH_NOT_TAKEN)
break;
if (i == -1)
constant_pool_entries_cost = 0;
constant_pool_entries_regcost = 0;
val.path_size = 0;
+ rtl_hooks = cse_rtl_hooks;
init_recog ();
init_alias_analysis ();
free (uid_cuid);
free (reg_eqv_table);
free (val.path);
+ rtl_hooks = general_rtl_hooks;
return cse_jumps_altered || recorded_label_ref;
}
if (next_branch->branch == insn)
{
enum taken status = next_branch++->status;
- if (status != NOT_TAKEN)
+ if (status != PATH_NOT_TAKEN)
{
- if (status == TAKEN)
+ if (status == PATH_TAKEN)
record_jump_equiv (insn, 1);
else
invalidate_skipped_block (NEXT_INSN (insn));
if (GET_MODE (insn) == QImode)
PUT_MODE (insn, VOIDmode);
- if (GET_RTX_CLASS (code) == 'i')
+ if (GET_RTX_CLASS (code) == RTX_INSN)
{
rtx p;
}
while (ndead != nlastdead);
- if (rtl_dump_file && ndead)
- fprintf (rtl_dump_file, "Deleted %i trivially dead insns; %i iterations\n",
+ if (dump_file && ndead)
+ fprintf (dump_file, "Deleted %i trivially dead insns; %i iterations\n",
ndead, niterations);
/* Clean up. */
free (counts);
/* Change the mode of any reference to the register REGNO (NEWREG) to
GET_MODE (NEWREG), starting at START. Stop before END. Stop at
- any instruction after START which modifies NEWREG. */
+ any instruction which modifies NEWREG. */
static void
cse_change_cc_mode_insns (rtx start, rtx end, rtx newreg)
if (! INSN_P (insn))
continue;
- if (insn != start && reg_set_p (newreg, insn))
+ if (reg_set_p (newreg, insn))
return;
for_each_rtx (&PATTERN (insn), cse_change_cc_mode, newreg);
XEXP (SET_SRC (set), 1)))
{
- comp_mode = (*targetm.cc_modes_compatible) (mode, set_mode);
+ comp_mode = targetm.cc_modes_compatible (mode, set_mode);
if (comp_mode != VOIDmode
&& (can_change_mode || comp_mode == mode))
found = true;
rtx cc_reg_2;
basic_block bb;
- if (! (*targetm.fixed_condition_code_regs) (&cc_regno_1, &cc_regno_2))
+ if (! targetm.fixed_condition_code_regs (&cc_regno_1, &cc_regno_2))
return;
cc_reg_1 = gen_rtx_REG (CCmode, cc_regno_1);
if (mode != GET_MODE (cc_src))
abort ();
if (mode != orig_mode)
- cse_change_cc_mode_insns (cc_src_insn, NEXT_INSN (last_insn),
- gen_rtx_REG (mode, REGNO (cc_reg)));
+ {
+ rtx newreg = gen_rtx_REG (mode, REGNO (cc_reg));
+
+ /* Change the mode of CC_REG in CC_SRC_INSN to
+ GET_MODE (NEWREG). */
+ for_each_rtx (&PATTERN (cc_src_insn), cse_change_cc_mode,
+ newreg);
+ for_each_rtx (®_NOTES (cc_src_insn), cse_change_cc_mode,
+ newreg);
+
+ /* Do the same in the following insns that use the
+ current value of CC_REG within BB. */
+ cse_change_cc_mode_insns (NEXT_INSN (cc_src_insn),
+ NEXT_INSN (last_insn),
+ newreg);
+ }
}
}
}