{
/* If I is 0, use the low-order word in both field and target;
if I is 1, use the next to lowest word; and so on. */
- unsigned int wordnum = (backwards ? nwords - i - 1 : i);
+ unsigned int wordnum = (backwards
+ ? GET_MODE_SIZE (fieldmode) / UNITS_PER_WORD
+ - i - 1
+ : i);
unsigned int bit_offset = (backwards
? MAX ((int) bitsize - ((int) i + 1)
* BITS_PER_WORD,
0)
: (int) i * BITS_PER_WORD);
rtx value_word = operand_subword_force (value, wordnum, fieldmode);
-
- if (!store_bit_field_1 (op0, MIN (BITS_PER_WORD,
- bitsize - i * BITS_PER_WORD),
+ unsigned HOST_WIDE_INT new_bitsize =
+ MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD);
+
+ /* If the remaining chunk doesn't have full wordsize we have
+ to make sure that for big endian machines the higher order
+ bits are used. */
+ if (new_bitsize < BITS_PER_WORD && BYTES_BIG_ENDIAN && !backwards)
+ value_word = simplify_expand_binop (word_mode, lshr_optab,
+ value_word,
+ GEN_INT (BITS_PER_WORD
+ - new_bitsize),
+ NULL_RTX, true,
+ OPTAB_LIB_WIDEN);
+
+ if (!store_bit_field_1 (op0, new_bitsize,
bitnum + bit_offset,
bitregion_start, bitregion_end,
word_mode,
&& GET_MODE (value) != BLKmode
&& bitsize > 0
&& GET_MODE_BITSIZE (op_mode) >= bitsize
+ /* Do not use insv for volatile bitfields when
+ -fstrict-volatile-bitfields is in effect. */
+ && !(MEM_P (op0) && MEM_VOLATILE_P (op0)
+ && flag_strict_volatile_bitfields > 0)
&& ! ((REG_P (op0) || GET_CODE (op0) == SUBREG)
- && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode))))
+ && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode)))
+ /* Do not use insv if the bit region is restricted and
+ op_mode integer at offset doesn't fit into the
+ restricted region. */
+ && !(MEM_P (op0) && bitregion_end
+ && bitnum - bitpos + GET_MODE_BITSIZE (op_mode)
+ > bitregion_end + 1))
{
struct expand_operand ops[4];
int xbitpos = bitpos;
copy_back = true;
}
- /* On big-endian machines, we count bits from the most significant.
- If the bit field insn does not, we must invert. */
-
- if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
- xbitpos = unit - bitsize - xbitpos;
-
/* We have been counting XBITPOS within UNIT.
Count instead within the size of the register. */
- if (BITS_BIG_ENDIAN && !MEM_P (xop0))
+ if (BYTES_BIG_ENDIAN && !MEM_P (xop0))
xbitpos += GET_MODE_BITSIZE (op_mode) - unit;
unit = GET_MODE_BITSIZE (op_mode);
+ /* If BITS_BIG_ENDIAN is zero on a BYTES_BIG_ENDIAN machine, we count
+ "backwards" from the size of the unit we are inserting into.
+ Otherwise, we count bits from the most significant on a
+ BYTES/BITS_BIG_ENDIAN machine. */
+
+ if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
+ xbitpos = unit - bitsize - xbitpos;
+
/* Convert VALUE to op_mode (which insv insn wants) in VALUE1. */
value1 = value;
if (GET_MODE (value) != op_mode)
|| GET_MODE_BITSIZE (GET_MODE (op0)) > maxbits
|| (op_mode != MAX_MACHINE_MODE
&& GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (op_mode)))
- bestmode = get_best_mode (bitsize, bitnum,
+ bestmode = get_best_mode (bitsize, bitnum,
bitregion_start, bitregion_end,
MEM_ALIGN (op0),
(op_mode == MAX_MACHINE_MODE
/* Under the C++0x memory model, we must not touch bits outside the
bit region. Adjust the address to start at the beginning of the
bit region. */
- if (MEM_P (str_rtx)
- && bitregion_start > 0)
+ if (MEM_P (str_rtx) && bitregion_start > 0)
{
enum machine_mode bestmode;
enum machine_mode op_mode;
if (op_mode == MAX_MACHINE_MODE)
op_mode = VOIDmode;
+ gcc_assert ((bitregion_start % BITS_PER_UNIT) == 0);
+
offset = bitregion_start / BITS_PER_UNIT;
bitnum -= bitregion_start;
bitregion_end -= bitregion_start;
offset = (bitpos + bitsdone) / unit;
thispos = (bitpos + bitsdone) % unit;
+ /* When region of bytes we can touch is restricted, decrease
+ UNIT close to the end of the region as needed. */
+ if (bitregion_end
+ && unit > BITS_PER_UNIT
+ && bitpos + bitsdone - thispos + unit > bitregion_end + 1)
+ {
+ unit = unit / 2;
+ continue;
+ }
+
/* THISSIZE must not overrun a word boundary. Otherwise,
store_fixed_bit_field will call us again, and we will mutually
recurse forever. */
if (ext_mode != MAX_MACHINE_MODE
&& bitsize > 0
&& GET_MODE_BITSIZE (ext_mode) >= bitsize
+ /* Do not use extv/extzv for volatile bitfields when
+ -fstrict-volatile-bitfields is in effect. */
+ && !(MEM_P (op0) && MEM_VOLATILE_P (op0)
+ && flag_strict_volatile_bitfields > 0)
/* If op0 is a register, we need it in EXT_MODE to make it
acceptable to the format of ext(z)v. */
&& !(GET_CODE (op0) == SUBREG && GET_MODE (op0) != ext_mode)
/* Get ref to first byte containing part of the field. */
xop0 = adjust_address (xop0, byte_mode, xoffset);
- /* On big-endian machines, we count bits from the most significant.
- If the bit field insn does not, we must invert. */
- if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
- xbitpos = unit - bitsize - xbitpos;
-
/* Now convert from counting within UNIT to counting in EXT_MODE. */
- if (BITS_BIG_ENDIAN && !MEM_P (xop0))
+ if (BYTES_BIG_ENDIAN && !MEM_P (xop0))
xbitpos += GET_MODE_BITSIZE (ext_mode) - unit;
unit = GET_MODE_BITSIZE (ext_mode);
+ /* If BITS_BIG_ENDIAN is zero on a BYTES_BIG_ENDIAN machine, we count
+ "backwards" from the size of the unit we are extracting from.
+ Otherwise, we count bits from the most significant on a
+ BYTES/BITS_BIG_ENDIAN machine. */
+
+ if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
+ xbitpos = unit - bitsize - xbitpos;
+
if (xtarget == 0)
xtarget = xspec_target = gen_reg_rtx (tmode);
% GET_MODE_BITSIZE (mode));
else if (GET_CODE (op1) == SUBREG
&& subreg_lowpart_p (op1)
- && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (op1))))
+ && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op1)))
+ && SCALAR_INT_MODE_P (GET_MODE (op1)))
op1 = SUBREG_REG (op1);
}
&& !optimize)
? target : 0;
rtx accum_target = optimize ? 0 : accum;
+ rtx accum_inner;
switch (alg->op[opno])
{
that. */
tem = op0, nmode = mode;
+ accum_inner = accum;
if (GET_CODE (accum) == SUBREG)
{
- nmode = GET_MODE (SUBREG_REG (accum));
+ accum_inner = SUBREG_REG (accum);
+ nmode = GET_MODE (accum_inner);
tem = gen_lowpart (nmode, op0);
}
insn = get_last_insn ();
- set_unique_reg_note (insn, REG_EQUAL,
- gen_rtx_MULT (nmode, tem,
- GEN_INT (val_so_far)));
+ set_dst_reg_note (insn, REG_EQUAL,
+ gen_rtx_MULT (nmode, tem, GEN_INT (val_so_far)),
+ accum_inner);
}
if (variant == negate_variant)
/* Try widening multiplication. */
moptab = unsignedp ? umul_widen_optab : smul_widen_optab;
- if (optab_handler (moptab, wider_mode) != CODE_FOR_nothing
+ if (widening_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing
&& mul_widen_cost[speed][wider_mode] < max_cost)
{
tem = expand_binop (wider_mode, moptab, op0, narrow_op1, 0,
/* Try widening multiplication of opposite signedness, and adjust. */
moptab = unsignedp ? smul_widen_optab : umul_widen_optab;
- if (optab_handler (moptab, wider_mode) != CODE_FOR_nothing
+ if (widening_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing
&& size - 1 < BITS_PER_WORD
&& (mul_widen_cost[speed][wider_mode] + 2 * shift_cost[speed][mode][size-1]
+ 4 * add_cost[speed][mode] < max_cost))
rtx quotient = 0, remainder = 0;
rtx last;
int size;
- rtx insn, set;
+ rtx insn;
optab optab1, optab2;
int op1_is_constant, op1_is_pow2 = 0;
int max_cost, extra_cost;
break;
insn = get_last_insn ();
- if (insn != last
- && (set = single_set (insn)) != 0
- && SET_DEST (set) == quotient)
- set_unique_reg_note (insn,
- REG_EQUAL,
- gen_rtx_UDIV (compute_mode, op0, op1));
+ if (insn != last)
+ set_dst_reg_note (insn, REG_EQUAL,
+ gen_rtx_UDIV (compute_mode, op0, op1),
+ quotient);
}
else /* TRUNC_DIV, signed */
{
{
insn = get_last_insn ();
if (insn != last
- && (set = single_set (insn)) != 0
- && SET_DEST (set) == quotient
&& abs_d < ((unsigned HOST_WIDE_INT) 1
<< (HOST_BITS_PER_WIDE_INT - 1)))
- set_unique_reg_note (insn,
- REG_EQUAL,
- gen_rtx_DIV (compute_mode,
- op0,
- GEN_INT
- (trunc_int_for_mode
- (abs_d,
- compute_mode))));
+ set_dst_reg_note (insn, REG_EQUAL,
+ gen_rtx_DIV (compute_mode, op0,
+ gen_int_mode
+ (abs_d,
+ compute_mode)),
+ quotient);
quotient = expand_unop (compute_mode, neg_optab,
quotient, quotient, 0);
break;
insn = get_last_insn ();
- if (insn != last
- && (set = single_set (insn)) != 0
- && SET_DEST (set) == quotient)
- set_unique_reg_note (insn,
- REG_EQUAL,
- gen_rtx_DIV (compute_mode, op0, op1));
+ if (insn != last)
+ set_dst_reg_note (insn, REG_EQUAL,
+ gen_rtx_DIV (compute_mode, op0, op1),
+ quotient);
}
break;
}
NULL_RTX, 1);
insn = get_last_insn ();
- set_unique_reg_note (insn,
- REG_EQUAL,
- gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
- compute_mode,
- op0, op1));
+ set_dst_reg_note (insn, REG_EQUAL,
+ gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
+ compute_mode, op0, op1),
+ quotient);
}
break;
/* For the reverse comparison, use either an addition or a XOR. */
if (want_add
- && rtx_cost (GEN_INT (normalizep), PLUS,
+ && rtx_cost (GEN_INT (normalizep), PLUS, 1,
optimize_insn_for_speed_p ()) == 0)
{
tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
target, 0, OPTAB_WIDEN);
}
else if (!want_add
- && rtx_cost (trueval, XOR,
+ && rtx_cost (trueval, XOR, 1,
optimize_insn_for_speed_p ()) == 0)
{
tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
/* Again, for the reverse comparison, use either an addition or a XOR. */
if (want_add
- && rtx_cost (GEN_INT (normalizep), PLUS,
+ && rtx_cost (GEN_INT (normalizep), PLUS, 1,
optimize_insn_for_speed_p ()) == 0)
{
tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
GEN_INT (normalizep), target, 0, OPTAB_WIDEN);
}
else if (!want_add
- && rtx_cost (trueval, XOR,
+ && rtx_cost (trueval, XOR, 1,
optimize_insn_for_speed_p ()) == 0)
{
tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,