/* Common subexpression elimination for GNU compiler.
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
This file is part of GCC.
static int
notreg_cost (rtx x, machine_mode mode, enum rtx_code outer, int opno)
{
+ scalar_int_mode int_mode, inner_mode;
return ((GET_CODE (x) == SUBREG
&& REG_P (SUBREG_REG (x))
- && GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_INT
- && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
+ && is_int_mode (mode, &int_mode)
+ && is_int_mode (GET_MODE (SUBREG_REG (x)), &inner_mode)
+ && GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (inner_mode)
&& subreg_lowpart_p (x)
- && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (SUBREG_REG (x))))
+ && TRULY_NOOP_TRUNCATION_MODES_P (int_mode, inner_mode))
? 0
: rtx_cost (x, mode, outer, opno, optimize_this_for_speed_p) * 2);
}
{
if (SHIFT_COUNT_TRUNCATED)
canon_const_arg1 = GEN_INT (INTVAL (const_arg1)
- & (GET_MODE_BITSIZE (mode)
+ & (GET_MODE_UNIT_BITSIZE (mode)
- 1));
else
break;
{
if (SHIFT_COUNT_TRUNCATED)
inner_const = GEN_INT (INTVAL (inner_const)
- & (GET_MODE_BITSIZE (mode) - 1));
+ & (GET_MODE_UNIT_BITSIZE (mode)
+ - 1));
else
break;
}
/* As an exception, we can turn an ASHIFTRT of this
form into a shift of the number of bits - 1. */
if (code == ASHIFTRT)
- new_const = GEN_INT (GET_MODE_BITSIZE (mode) - 1);
+ new_const = GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1);
else if (!side_effects_p (XEXP (y, 0)))
return CONST0_RTX (mode);
else
the subreg. Note that the upper bits of paradoxical subregs
are undefined, so they cannot be said to equal anything. */
if (REG_P (SUBREG_REG (x))
- && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (imode)
+ && !paradoxical_subreg_p (x)
&& (new_rtx = equiv_constant (SUBREG_REG (x))) != 0)
return simplify_subreg (mode, new_rtx, imode, SUBREG_BYTE (x));
if we test MODE instead, we can get an infinite recursion
alternating between two modes each wider than MODE. */
- if (code == NE && GET_CODE (op0) == SUBREG
- && subreg_lowpart_p (op0)
- && (GET_MODE_SIZE (GET_MODE (op0))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
+ if (code == NE
+ && partial_subreg_p (op0)
+ && subreg_lowpart_p (op0))
{
machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
rtx tem = record_jump_cond_subreg (inner_mode, op1);
reversed_nonequality);
}
- if (code == NE && GET_CODE (op1) == SUBREG
- && subreg_lowpart_p (op1)
- && (GET_MODE_SIZE (GET_MODE (op1))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
+ if (code == NE
+ && partial_subreg_p (op1)
+ && subreg_lowpart_p (op1))
{
machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
rtx tem = record_jump_cond_subreg (inner_mode, op0);
The size of this field should match the size of the mode
field of struct rtx_def (see rtl.h). */
ENUM_BITFIELD(machine_mode) mode : 8;
- /* A constant equivalent for SET_SRC, if any. */
- rtx src_const;
/* Hash value of constant equivalent for SET_SRC. */
unsigned src_const_hash;
+ /* A constant equivalent for SET_SRC, if any. */
+ rtx src_const;
/* Table entry for constant equivalent for SET_SRC, if any. */
struct table_elt *src_const_elt;
/* Table entry for the destination address. */
&& CONST_INT_P (XEXP (SET_DEST (sets[0].rtl), 2)))
{
rtx dest_reg = XEXP (SET_DEST (sets[0].rtl), 0);
+ /* This is the mode of XEXP (tem, 0) as well. */
+ scalar_int_mode dest_mode
+ = as_a <scalar_int_mode> (GET_MODE (dest_reg));
rtx width = XEXP (SET_DEST (sets[0].rtl), 1);
rtx pos = XEXP (SET_DEST (sets[0].rtl), 2);
HOST_WIDE_INT val = INTVAL (XEXP (tem, 0));
HOST_WIDE_INT mask;
unsigned int shift;
if (BITS_BIG_ENDIAN)
- shift = GET_MODE_PRECISION (GET_MODE (dest_reg))
- - INTVAL (pos) - INTVAL (width);
+ shift = (GET_MODE_PRECISION (dest_mode)
+ - INTVAL (pos) - INTVAL (width));
else
shift = INTVAL (pos);
if (INTVAL (width) == HOST_BITS_PER_WIDE_INT)
/* Set nonzero if we need to call force_const_mem on with the
contents of src_folded before using it. */
int src_folded_force_flag = 0;
+ scalar_int_mode int_mode;
dest = SET_DEST (sets[i].rtl);
src = SET_SRC (sets[i].rtl);
wider mode. */
if (src_const && src_related == 0 && CONST_INT_P (src_const)
- && GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_PRECISION (mode) < BITS_PER_WORD)
+ && is_int_mode (mode, &int_mode)
+ && GET_MODE_PRECISION (int_mode) < BITS_PER_WORD)
{
- machine_mode wider_mode;
-
- for (wider_mode = GET_MODE_WIDER_MODE (mode);
- wider_mode != VOIDmode
- && GET_MODE_PRECISION (wider_mode) <= BITS_PER_WORD
- && src_related == 0;
- wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+ opt_scalar_int_mode wider_mode_iter;
+ FOR_EACH_WIDER_MODE (wider_mode_iter, int_mode)
{
+ scalar_int_mode wider_mode = wider_mode_iter.require ();
+ if (GET_MODE_PRECISION (wider_mode) > BITS_PER_WORD)
+ break;
+
struct table_elt *const_elt
= lookup (src_const, HASH (src_const, wider_mode), wider_mode);
const_elt; const_elt = const_elt->next_same_value)
if (REG_P (const_elt->exp))
{
- src_related = gen_lowpart (mode, const_elt->exp);
+ src_related = gen_lowpart (int_mode, const_elt->exp);
break;
}
+
+ if (src_related != 0)
+ break;
}
}
value. */
if (flag_expensive_optimizations && ! src_related
+ && is_a <scalar_int_mode> (mode, &int_mode)
&& GET_CODE (src) == AND && CONST_INT_P (XEXP (src, 1))
- && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+ && GET_MODE_SIZE (int_mode) < UNITS_PER_WORD)
{
- machine_mode tmode;
+ opt_scalar_int_mode tmode_iter;
rtx new_and = gen_rtx_AND (VOIDmode, NULL_RTX, XEXP (src, 1));
- for (tmode = GET_MODE_WIDER_MODE (mode);
- GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
- tmode = GET_MODE_WIDER_MODE (tmode))
+ FOR_EACH_WIDER_MODE (tmode_iter, int_mode)
{
+ scalar_int_mode tmode = tmode_iter.require ();
+ if (GET_MODE_SIZE (tmode) > UNITS_PER_WORD)
+ break;
+
rtx inner = gen_lowpart (tmode, XEXP (src, 0));
struct table_elt *larger_elt;
if (REG_P (larger_elt->exp))
{
src_related
- = gen_lowpart (mode, larger_elt->exp);
+ = gen_lowpart (int_mode, larger_elt->exp);
break;
}
also have such operations, but this is only likely to be
beneficial on these machines. */
+ rtx_code extend_op;
if (flag_expensive_optimizations && src_related == 0
- && (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
- && GET_MODE_CLASS (mode) == MODE_INT
&& MEM_P (src) && ! do_not_record
- && LOAD_EXTEND_OP (mode) != UNKNOWN)
+ && is_a <scalar_int_mode> (mode, &int_mode)
+ && (extend_op = load_extend_op (int_mode)) != UNKNOWN)
{
struct rtx_def memory_extend_buf;
rtx memory_extend_rtx = &memory_extend_buf;
- machine_mode tmode;
/* Set what we are trying to extend and the operation it might
have been extended with. */
memset (memory_extend_rtx, 0, sizeof (*memory_extend_rtx));
- PUT_CODE (memory_extend_rtx, LOAD_EXTEND_OP (mode));
+ PUT_CODE (memory_extend_rtx, extend_op);
XEXP (memory_extend_rtx, 0) = src;
- for (tmode = GET_MODE_WIDER_MODE (mode);
- GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
- tmode = GET_MODE_WIDER_MODE (tmode))
+ opt_scalar_int_mode tmode_iter;
+ FOR_EACH_WIDER_MODE (tmode_iter, int_mode)
{
struct table_elt *larger_elt;
+ scalar_int_mode tmode = tmode_iter.require ();
+ if (GET_MODE_SIZE (tmode) > UNITS_PER_WORD)
+ break;
+
PUT_MODE (memory_extend_rtx, tmode);
larger_elt = lookup (memory_extend_rtx,
HASH (memory_extend_rtx, tmode), tmode);
larger_elt; larger_elt = larger_elt->next_same_value)
if (REG_P (larger_elt->exp))
{
- src_related = gen_lowpart (mode, larger_elt->exp);
+ src_related = gen_lowpart (int_mode, larger_elt->exp);
break;
}
&& ! (src != 0
&& GET_CODE (src) == SUBREG
&& GET_MODE (src) == GET_MODE (p->exp)
- && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (p->exp))))))
+ && partial_subreg_p (GET_MODE (SUBREG_REG (src)),
+ GET_MODE (SUBREG_REG (p->exp)))))
continue;
if (src && GET_CODE (src) == code && rtx_equal_p (src, p->exp))
&& ! (src != 0
&& GET_CODE (src) == SUBREG
&& GET_MODE (src) == GET_MODE (elt->exp)
- && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (elt->exp))))))
+ && partial_subreg_p (GET_MODE (SUBREG_REG (src)),
+ GET_MODE (SUBREG_REG (elt->exp)))))
{
elt = elt->next_same_value;
continue;
HOST_WIDE_INT val = INTVAL (dest_cst);
HOST_WIDE_INT mask;
unsigned int shift;
+ /* This is the mode of DEST_CST as well. */
+ scalar_int_mode dest_mode
+ = as_a <scalar_int_mode> (GET_MODE (dest_reg));
if (BITS_BIG_ENDIAN)
- shift = GET_MODE_PRECISION (GET_MODE (dest_reg))
+ shift = GET_MODE_PRECISION (dest_mode)
- INTVAL (pos) - INTVAL (width);
else
shift = INTVAL (pos);
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));
+ val = trunc_int_for_mode (val, dest_mode);
validate_unshare_change (insn, &SET_DEST (sets[i].rtl),
dest_reg, 1);
validate_unshare_change (insn, &SET_SRC (sets[i].rtl),
&& (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) - 1)
/ UNITS_PER_WORD)
== (GET_MODE_SIZE (GET_MODE (dest)) - 1) / UNITS_PER_WORD)
- && (GET_MODE_SIZE (GET_MODE (dest))
- >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))
+ && !partial_subreg_p (dest)
&& sets[i].src_elt != 0)
{
machine_mode new_mode = GET_MODE (SUBREG_REG (dest));
rtx new_src = 0;
unsigned src_hash;
struct table_elt *src_elt;
- int byte = 0;
/* Ignore invalid entries. */
if (!REG_P (elt->exp)
new_src = elt->exp;
else
{
- /* Calculate big endian correction for the SUBREG_BYTE.
- We have already checked that M1 (GET_MODE (dest))
- is not narrower than M2 (new_mode). */
- if (BYTES_BIG_ENDIAN)
- byte = (GET_MODE_SIZE (GET_MODE (dest))
- - GET_MODE_SIZE (new_mode));
-
+ unsigned int byte
+ = subreg_lowpart_offset (new_mode, GET_MODE (dest));
new_src = simplify_gen_subreg (new_mode, elt->exp,
GET_MODE (dest), byte);
}
equivalences due to the condition being tested. */
insn = BB_END (bb);
if (path_entry < path_size - 1
+ && EDGE_COUNT (bb->succs) == 2
&& JUMP_P (insn)
&& single_set (insn)
&& any_condjump_p (insn))