+2017-05-12 Jim Wilson <jim.wilson@linaro.org>
+
+ PR middle-end/79794
+ * expmed.c (extract_bit_field_1): Add alt_rtl argument. Before
+ maybe_expand_insn call, set ops[0].target. If still set after call,
+ set alt_rtl. Add extra arg to recursive calls.
+ (extract_bit_field): Add alt_rtl argument. Pass to
+ extract_bit_field.
+ * expmed.h (extract_bit_field): Fix prototype.
+ * expr.c (emit_group_load_1, copy_blkmode_from_reg)
+ (copy_blkmode_to_reg, read_complex_part, store_field): Pass extra NULL
+ to extract_bit_field_calls.
+ (expand_expr_real_1): Pass alt_rtl to expand_expr_real instead of 0.
+ Pass alt_rtl to extract_bit_field calls.
+ * calls.c (store_unaligned_arguments_into_psuedos)
+ load_register_parameters): Pass extra NULL to extract_bit_field calls.
+ * optabs.c (maybe_legitimize_operand): Clear op->target when call
+ gen_reg_rtx.
+ * optabs.h (struct expand_operand): Add target bitfield.
+
2017-05-12 Uros Bizjak <ubizjak@gmail.com>
* compare-elim.c (try_eliminate_compare): Canonicalize
args[i].aligned_regs[j] = reg;
word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX,
- word_mode, word_mode, false);
+ word_mode, word_mode, false, NULL);
/* There is no need to restrict this code to loading items
in TYPE_ALIGN sized hunks. The bitfield instructions can
unsigned int bitoff = (nregs - 1) * BITS_PER_WORD;
unsigned int bitsize = size * BITS_PER_UNIT - bitoff;
rtx x = extract_bit_field (mem, bitsize, bitoff, 1, dest,
- word_mode, word_mode, false);
+ word_mode, word_mode, false,
+ NULL);
if (BYTES_BIG_ENDIAN)
x = expand_shift (LSHIFT_EXPR, word_mode, x,
BITS_PER_WORD - bitsize, dest, 1);
extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
machine_mode mode, machine_mode tmode,
- bool reverse, bool fallback_p)
+ bool reverse, bool fallback_p, rtx *alt_rtl)
{
rtx op0 = str_rtx;
machine_mode int_mode;
unsigned HOST_WIDE_INT pos = bitnum / GET_MODE_BITSIZE (innermode);
create_output_operand (&ops[0], target, innermode);
+ ops[0].target = 1;
create_input_operand (&ops[1], op0, outermode);
create_integer_operand (&ops[2], pos);
if (maybe_expand_insn (icode, 3, ops))
{
+ if (alt_rtl && ops[0].target)
+ *alt_rtl = target;
target = ops[0].value;
if (GET_MODE (target) != mode)
return gen_lowpart (tmode, target);
= extract_bit_field_1 (op0, MIN (BITS_PER_WORD,
bitsize - i * BITS_PER_WORD),
bitnum + bit_offset, 1, target_part,
- mode, word_mode, reverse, fallback_p);
+ mode, word_mode, reverse, fallback_p, NULL);
gcc_assert (target_part);
if (!result_part)
xop0 = copy_to_reg (xop0);
rtx result = extract_bit_field_1 (xop0, bitsize, bitpos,
unsignedp, target,
- mode, tmode, reverse, false);
+ mode, tmode, reverse, false, NULL);
if (result)
return result;
delete_insns_since (last);
rtx
extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
- machine_mode mode, machine_mode tmode, bool reverse)
+ machine_mode mode, machine_mode tmode, bool reverse,
+ rtx *alt_rtl)
{
machine_mode mode1;
}
return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp,
- target, mode, tmode, reverse, true);
+ target, mode, tmode, reverse, true, alt_rtl);
}
\f
/* Use shifts and boolean operations to extract a field of BITSIZE bits
machine_mode, rtx, bool);
extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, int, rtx,
- machine_mode, machine_mode, bool);
+ machine_mode, machine_mode, bool, rtx *);
extern rtx extract_low_bits (machine_mode, machine_mode, rtx);
extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int);
extern rtx expand_mult_highpart_adjust (machine_mode, rtx, rtx, rtx, rtx, int);
&& (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode)))
tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
subpos * BITS_PER_UNIT,
- 1, NULL_RTX, mode, mode, false);
+ 1, NULL_RTX, mode, mode, false,
+ NULL);
}
else
{
mem = assign_stack_temp (GET_MODE (src), slen);
emit_move_insn (mem, src);
tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT,
- 0, 1, NULL_RTX, mode, mode, false);
+ 0, 1, NULL_RTX, mode, mode, false,
+ NULL);
}
}
/* FIXME: A SIMD parallel will eventually lead to a subreg of a
else
tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
bytepos * BITS_PER_UNIT, 1, NULL_RTX,
- mode, mode, false);
+ mode, mode, false, NULL);
if (shift)
tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i],
extract_bit_field (src, bitsize,
xbitpos % BITS_PER_WORD, 1,
NULL_RTX, copy_mode, copy_mode,
- false),
+ false, NULL),
false);
}
}
extract_bit_field (src_word, bitsize,
bitpos % BITS_PER_WORD, 1,
NULL_RTX, word_mode, word_mode,
- false),
+ false, NULL),
false);
}
}
return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0,
- true, NULL_RTX, imode, imode, false);
+ true, NULL_RTX, imode, imode, false, NULL);
}
\f
/* A subroutine of emit_move_insn_1. Yet another lowpart generator.
{
machine_mode temp_mode = smallest_mode_for_size (bitsize, MODE_INT);
temp = extract_bit_field (temp, bitsize, 0, 1, NULL_RTX, temp_mode,
- temp_mode, false);
+ temp_mode, false, NULL);
}
/* Store the value in the bitfield. */
case GIMPLE_SINGLE_RHS:
{
r = expand_expr_real (gimple_assign_rhs1 (g), target,
- tmode, modifier, NULL, inner_reference_p);
+ tmode, modifier, alt_rtl,
+ inner_reference_p);
break;
}
default:
0, TYPE_UNSIGNED (TREE_TYPE (exp)),
(modifier == EXPAND_STACK_PARM
? NULL_RTX : target),
- mode, mode, false);
+ mode, mode, false, alt_rtl);
}
if (reverse
&& modifier != EXPAND_MEMORY
op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
(modifier == EXPAND_STACK_PARM
? NULL_RTX : target),
- ext_mode, ext_mode, reversep);
+ ext_mode, ext_mode, reversep, alt_rtl);
/* If the result has a record type and the mode of OP0 is an
integral mode then, if BITSIZE is narrower than this mode
else if (reduce_bit_field)
return extract_bit_field (op0, TYPE_PRECISION (type), 0,
TYPE_UNSIGNED (type), NULL_RTX,
- mode, mode, false);
+ mode, mode, false, NULL);
/* As a last resort, spill op0 to memory, and reload it in a
different mode. */
else if (!MEM_P (op0))
return true;
op->value = gen_reg_rtx (mode);
+ op->target = 0;
break;
case EXPAND_INPUT:
rather than signed. Only meaningful for certain types. */
unsigned int unsigned_p : 1;
+ /* Is the target operand. */
+ unsigned int target : 1;
+
/* Unused; available for future use. */
- unsigned int unused : 7;
+ unsigned int unused : 6;
/* The mode passed to the convert_*_operand function. It has a
type-dependent meaning. */