* emit-rtl.c (paradoxical_subreg_p): New function.
* rtl.h (paradoxical_subreg_p): Declare.
* combine.c (set_nonzero_bits_and_sign_copies, get_last_value,
apply_distributive_law, simplify_comparison, simplify_set): Use it.
* cse.c (record_jump_cond, cse_insn): Likewise.
* expr.c (force_operand): Likewise.
* rtlanal.c (num_sign_bit_copies1): Likewise.
* reload1.c (eliminate_regs_1, strip_paradoxical_subreg): Likewise.
* reload.c (push_secondary_reload, find_reloads_toplev): Likewise.
(push_reload): Use precision to check for paradoxical subregs.
* expmed.c (extract_bit_field_1): Likewise.
From-SVN: r175944
+2011-07-07 Bernd Schmidt <bernds@codesourcery.com>
+
+ * emit-rtl.c (paradoxical_subreg_p): New function.
+ * rtl.h (paradoxical_subreg_p): Declare.
+ * combine.c (set_nonzero_bits_and_sign_copies, get_last_value,
+ apply_distributive_law, simplify_comparison, simplify_set): Use it.
+ * cse.c (record_jump_cond, cse_insn): Likewise.
+ * expr.c (force_operand): Likewise.
+ * rtlanal.c (num_sign_bit_copies1): Likewise.
+ * reload1.c (eliminate_regs_1, strip_paradoxical_subreg): Likewise.
+ * reload.c (push_secondary_reload, find_reloads_toplev): Likewise.
+ (push_reload): Use precision to check for paradoxical subregs.
+ * expmed.c (extract_bit_field_1): Likewise.
+
2011-07-06 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000-protos.h (rs6000_call_indirect_aix): New
set what we know about X. */
if (SET_DEST (set) == x
- || (GET_CODE (SET_DEST (set)) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (set)))))
+ || (paradoxical_subreg_p (SET_DEST (set))
&& SUBREG_REG (SET_DEST (set)) == x))
{
rtx src = SET_SRC (set);
&& INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (src)))
&& LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))) != UNKNOWN
&& SUBREG_BYTE (src) == 0
- && (GET_MODE_SIZE (GET_MODE (src))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
+ && paradoxical_subreg_p (src)
&& MEM_P (SUBREG_REG (src)))
{
SUBST (SET_SRC (x),
|| ! subreg_lowpart_p (lhs)
|| (GET_MODE_CLASS (GET_MODE (lhs))
!= GET_MODE_CLASS (GET_MODE (SUBREG_REG (lhs))))
- || (GET_MODE_SIZE (GET_MODE (lhs))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (lhs))))
+ || paradoxical_subreg_p (lhs)
|| VECTOR_MODE_P (GET_MODE (lhs))
|| GET_MODE_SIZE (GET_MODE (SUBREG_REG (lhs))) > UNITS_PER_WORD
/* Result might need to be truncated. Don't change mode if
HOST_WIDE_INT c1 = INTVAL (XEXP (op1, 1));
int changed = 0;
- if (GET_CODE (inner_op0) == SUBREG && GET_CODE (inner_op1) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (inner_op0))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner_op0))))
+ if (paradoxical_subreg_p (inner_op0)
+ && GET_CODE (inner_op1) == SUBREG
&& (GET_MODE (SUBREG_REG (inner_op0))
== GET_MODE (SUBREG_REG (inner_op1)))
&& (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (inner_op0)))
&& GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
&& (code == NE || code == EQ))
{
- if (GET_MODE_SIZE (GET_MODE (op0))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))
+ if (paradoxical_subreg_p (op0))
{
/* For paradoxical subregs, allow case 1 as above. Case 3 isn't
implemented. */
we cannot predict what values the "extra" bits might have. */
if (GET_CODE (x) == SUBREG
&& subreg_lowpart_p (x)
- && (GET_MODE_SIZE (GET_MODE (x))
- <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ && !paradoxical_subreg_p (x)
&& (value = get_last_value (SUBREG_REG (x))) != 0)
return gen_lowpart (GET_MODE (x), value);
is not worth testing for with no SUBREG). */
/* Note that GET_MODE (op0) may not equal MODE. */
- if (code == EQ && GET_CODE (op0) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (op0))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
+ if (code == EQ && paradoxical_subreg_p (op0))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
rtx tem = record_jump_cond_subreg (inner_mode, op1);
reversed_nonequality);
}
- if (code == EQ && GET_CODE (op1) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (op1))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
+ if (code == EQ && paradoxical_subreg_p (op1))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
rtx tem = record_jump_cond_subreg (inner_mode, op0);
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. */
- if (GET_CODE (src) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (src))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))
+ if (paradoxical_subreg_p (src))
sets[i].src_volatile = 1;
#endif
/* Also skip paradoxical subregs, unless that's what we're
looking for. */
- if (code == SUBREG
- && (GET_MODE_SIZE (GET_MODE (p->exp))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (p->exp))))
+ if (paradoxical_subreg_p (p->exp)
&& ! (src != 0
&& GET_CODE (src) == SUBREG
&& GET_MODE (src) == GET_MODE (p->exp)
size, but later may be adjusted so that the upper bits aren't
what we want. So reject it. */
if (elt != 0
- && GET_CODE (elt->exp) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (elt->exp))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (elt->exp))))
+ && paradoxical_subreg_p (elt->exp)
/* It is okay, though, if the rtx we're trying to match
will ignore any of the bits we can't predict. */
&& ! (src != 0
some tracking to be wrong.
??? Think about this more later. */
- || (GET_CODE (dest) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (dest))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))
+ || (paradoxical_subreg_p (dest)
&& (GET_CODE (sets[i].src) == SIGN_EXTEND
|| GET_CODE (sets[i].src) == ZERO_EXTEND)))
continue;
return (subreg_lowpart_offset (GET_MODE (x), GET_MODE (SUBREG_REG (x)))
== SUBREG_BYTE (x));
}
+
+/* Return true if X is a paradoxical subreg, false otherwise. */
+bool
+paradoxical_subreg_p (const_rtx x)
+{
+ if (GET_CODE (x) != SUBREG)
+ return false;
+ return (GET_MODE_PRECISION (GET_MODE (x))
+ > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (x))));
+}
\f
/* Return subword OFFSET of operand OP.
The word number, OFFSET, is interpreted as the word number starting
&& TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (xtarget), ext_mode))
{
xtarget = gen_lowpart (ext_mode, xtarget);
- if (GET_MODE_SIZE (ext_mode)
- > GET_MODE_SIZE (GET_MODE (xspec_target)))
+ if (GET_MODE_PRECISION (ext_mode)
+ > GET_MODE_PRECISION (GET_MODE (xspec_target)))
xspec_target_subreg = xtarget;
}
else
#ifdef INSN_SCHEDULING
/* On machines that have insn scheduling, we want all memory reference to be
explicit, so we need to deal with such paradoxical SUBREGs. */
- if (GET_CODE (value) == SUBREG && MEM_P (SUBREG_REG (value))
- && (GET_MODE_SIZE (GET_MODE (value))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (value)))))
+ if (paradoxical_subreg_p (value) && MEM_P (SUBREG_REG (value)))
value
= simplify_gen_subreg (GET_MODE (value),
force_reg (GET_MODE (SUBREG_REG (value)),
/* If X is a paradoxical SUBREG, use the inner value to determine both the
mode and object being reloaded. */
- if (GET_CODE (x) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (x))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
+ if (paradoxical_subreg_p (x))
{
x = SUBREG_REG (x);
reload_mode = GET_MODE (x);
|| (((REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)
|| MEM_P (SUBREG_REG (in)))
- && ((GET_MODE_SIZE (inmode)
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+ && ((GET_MODE_PRECISION (inmode)
+ > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
#ifdef LOAD_EXTEND_OP
|| (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
<= UNITS_PER_WORD)
- && (GET_MODE_SIZE (inmode)
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+ && (GET_MODE_PRECISION (inmode)
+ > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
&& INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
&& LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN)
#endif
#ifdef WORD_REGISTER_OPERATIONS
- || ((GET_MODE_SIZE (inmode)
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+ || ((GET_MODE_PRECISION (inmode)
+ < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
&& ((GET_MODE_SIZE (inmode) - 1) / UNITS_PER_WORD ==
((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1)
/ UNITS_PER_WORD)))
|| (((REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
|| MEM_P (SUBREG_REG (out)))
- && ((GET_MODE_SIZE (outmode)
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
+ && ((GET_MODE_PRECISION (outmode)
+ > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
#ifdef WORD_REGISTER_OPERATIONS
- || ((GET_MODE_SIZE (outmode)
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
+ || ((GET_MODE_PRECISION (outmode)
+ < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
&& ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD ==
((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1)
/ UNITS_PER_WORD)))
if (regno >= FIRST_PSEUDO_REGISTER
#ifdef LOAD_EXTEND_OP
- && (GET_MODE_SIZE (GET_MODE (x))
- <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ && !paradoxical_subreg_p (x)
#endif
- && (reg_equiv_address (regno) != 0
- || (reg_equiv_mem (regno) != 0
- && (! strict_memory_address_addr_space_p
- (GET_MODE (x), XEXP (reg_equiv_mem (regno), 0),
- MEM_ADDR_SPACE (reg_equiv_mem (regno)))
- || ! offsettable_memref_p (reg_equiv_mem (regno))
- || num_not_at_initial_offset))))
+ && (reg_equiv_address (regno) != 0
+ || (reg_equiv_mem (regno) != 0
+ && (! strict_memory_address_addr_space_p
+ (GET_MODE (x), XEXP (reg_equiv_mem (regno), 0),
+ MEM_ADDR_SPACE (reg_equiv_mem (regno)))
+ || ! offsettable_memref_p (reg_equiv_mem (regno))
+ || num_not_at_initial_offset))))
x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
insn, address_reloaded);
}
eliminated version of the memory location because push_reload
may do the replacement in certain circumstances. */
if (REG_P (SUBREG_REG (x))
- && (GET_MODE_SIZE (GET_MODE (x))
- <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ && !paradoxical_subreg_p (x)
&& reg_equivs
&& reg_equiv_memory_loc (REGNO (SUBREG_REG (x))) != 0)
{
rtx op, inner, other, tem;
op = *op_ptr;
- if (GET_CODE (op) != SUBREG)
+ if (!paradoxical_subreg_p (op))
return false;
-
inner = SUBREG_REG (op);
- if (GET_MODE_SIZE (GET_MODE (op)) <= GET_MODE_SIZE (GET_MODE (inner)))
- return false;
other = *other_ptr;
tem = gen_lowpart_common (GET_MODE (inner), other);
/* In emit-rtl.c */
extern rtx operand_subword_force (rtx, unsigned int, enum machine_mode);
+extern bool paradoxical_subreg_p (const_rtx);
extern int subreg_lowpart_p (const_rtx);
extern unsigned int subreg_lowpart_offset (enum machine_mode,
enum machine_mode);
then we lose all sign bit copies that existed before the store
to the stack. */
- if ((GET_MODE_SIZE (GET_MODE (x))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ if (paradoxical_subreg_p (x)
&& LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
&& MEM_P (SUBREG_REG (x)))
return cached_num_sign_bit_copies (SUBREG_REG (x), mode,