+2011-06-01 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR target/45074
+ * optabs.h (valid_multiword_target_p): Declare.
+ * expmed.c (extract_bit_field_1): Check valid_multiword_target_p when
+ doing multi-word operations.
+ * optabs.c (expand_binop): Likewise.
+ (expand_doubleword_bswap): Likewise.
+ (expand_absneg_bit): Likewise.
+ (expand_unop): Likewise.
+ (expand_copysign_bit): Likewise.
+ (multiword_target_p): New function.
+
2011-06-01 Richard Sandiford <rdsandiford@googlemail.com>
PR rtl-optimization/48830
/* If TARGET is the same as one of the operands, the REG_EQUAL note
won't be accurate, so use a new target. */
- if (target == 0 || target == op0 || target == op1)
+ if (target == 0
+ || target == op0
+ || target == op1
+ || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode);
start_sequence ();
/* If TARGET is the same as one of the operands, the REG_EQUAL note
won't be accurate, so use a new target. */
- if (target == 0 || target == op0 || target == op1)
+ if (target == 0
+ || target == op0
+ || target == op1
+ || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode);
start_sequence ();
opportunities, and second because if target and op0 happen to be MEMs
designating the same location, we would risk clobbering it too early
in the code sequence we generate below. */
- if (target == 0 || target == op0 || target == op1 || ! REG_P (target))
+ if (target == 0
+ || target == op0
+ || target == op1
+ || !REG_P (target)
+ || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode);
start_sequence ();
xtarget = gen_reg_rtx (mode);
- if (target == 0 || !REG_P (target))
+ if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
target = xtarget;
/* Indicate for flow that the entire target reg is being set. */
t0 = expand_unop (word_mode, bswap_optab,
operand_subword_force (op, 1, mode), NULL_RTX, true);
- if (target == 0)
+ if (target == 0 || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode);
if (REG_P (target))
emit_clobber (target);
if (code == ABS)
mask = double_int_not (mask);
- if (target == 0 || target == op0)
+ if (target == 0
+ || target == op0
+ || (nwords > 1 && !valid_multiword_target_p (target)))
target = gen_reg_rtx (mode);
if (nwords > 1)
int i;
rtx insns;
- if (target == 0 || target == op0)
+ if (target == 0 || target == op0 || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode);
start_sequence ();
mask = double_int_setbit (double_int_zero, bitpos);
- if (target == 0 || target == op0 || target == op1)
+ if (target == 0
+ || target == op0
+ || target == op1
+ || (nwords > 1 && !valid_multiword_target_p (target)))
target = gen_reg_rtx (mode);
if (nwords > 1)
(operand, insn_data[(int) icode].operand[opno].mode)));
}
\f
+/* TARGET is a target of a multiword operation that we are going to
+ implement as a series of word-mode operations. Return true if
+ TARGET is suitable for this purpose. */
+
+bool
+valid_multiword_target_p (rtx target)
+{
+ enum machine_mode mode;
+ int i;
+
+ mode = GET_MODE (target);
+ for (i = 0; i < GET_MODE_SIZE (mode); i += UNITS_PER_WORD)
+ if (!validate_subreg (word_mode, mode, target, i))
+ return false;
+ return true;
+}
+
/* Like maybe_legitimize_operand, but do not change the code of the
current rtx value. */