+2005-01-05 Steven Bosscher <stevenb@suse.de>
+
+ * combine.c (expand_compound_operation) <ZERO_EXTRACT>: Add
+ comment that we fall through after case.
+ (mark_used_regs_combine): Don't expect a SIGN_EXTRACT in a SET_DEST.
+ (distribute_links): Likewise.
+ * cse.c (cse_insn): Likewise.
+ * cselib.c (cselib_invalidate_mem): Likewise.
+ * df.c: Update comments at the top of the file.
+ (read_modify_subreg_p): Update comments here too.
+ (df_def_record_1): Don't expect a SIGN_EXTRACT in a SET_DEST.
+ * flow.c (mark_set_1): Likewise.
+ (mark_used_regs): Likewise.
+ * gcse.c (mems_conflict_for_gcse_p): Likewise.
+ (canon_list_insert): Likewise.
+ (mark_set): Likewise.
+ (try_replace_reg): Likewise.
+ (store_killed_in_insn): Likewise.
+ * loop.c (count_one_set): Likewise.
+ (basic_induction_var): Likewise.
+ * postreload-gcse.c (find_mem_conflicts): Likewise.
+ * postreload.c (reload_combine_note_store): Likewise.
+ (move2add_note_store): Likewise.
+ * reload.c (find_equiv_reg): Likewise.
+ (mark_referenced_resources): Likewise.
+ * rtlanal.c (set_noop_p): Likewise.
+ (note_stores): Likewise.
+ (note_uses): Likewise.
+ * sched-deps.c (sched_analyze_1): Likewise.
+ * sched-rgn.c (check_live_1): Likewise.
+ (update_live_1): Likewise.
+ * config/i860/i860.c: Likewise.
+
+ * rtl.dec (SIGN_EXTRACT): Document that this cannot appear as
+ an lvalue.
+ (ZERO_EXTRACT): Mention that this one can be an lvalue.
+
+ * doc/rtl.texi: Update documentation for bit-fields and SET.
+
2005-01-05 Roger Sayle <roger@eyesopen.com>
* ifcvt.c (find_if_case_1): Revert 2005-01-04 change.
case ZERO_EXTRACT:
unsignedp = 1;
+
+ /* ... fall through ... */
+
case SIGN_EXTRACT:
/* If the operand is a CLOBBER, just return it. */
if (GET_CODE (XEXP (x, 0)) == CLOBBER)
while (GET_CODE (testreg) == SUBREG
|| GET_CODE (testreg) == ZERO_EXTRACT
- || GET_CODE (testreg) == SIGN_EXTRACT
|| GET_CODE (testreg) == STRICT_LOW_PART)
testreg = XEXP (testreg, 0);
reg = SET_DEST (set);
while (GET_CODE (reg) == SUBREG || GET_CODE (reg) == ZERO_EXTRACT
- || GET_CODE (reg) == SIGN_EXTRACT
|| GET_CODE (reg) == STRICT_LOW_PART)
reg = XEXP (reg, 0);
while (GET_CODE (dest) == STRICT_LOW_PART
|| GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == ZERO_EXTRACT)
dest = XEXP (dest, 0);
else
SET_SRC (sets[i].rtl) = new;
- if (GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SIGN_EXTRACT)
+ if (GET_CODE (dest) == ZERO_EXTRACT)
{
validate_change (insn, &XEXP (dest, 1),
canon_reg (XEXP (dest, 1), insn), 1);
canon_reg (XEXP (dest, 2), insn), 1);
}
- while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART
+ while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT)
+ || GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
if (MEM_P (dest))
causes later instructions to be mis-optimized. */
/* If storing a constant in a bitfield, pre-truncate the constant
so we will be able to record it later. */
- if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT
- || GET_CODE (SET_DEST (sets[i].rtl)) == SIGN_EXTRACT)
+ if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT)
{
rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
/* Now deal with the destination. */
do_not_record = 0;
- /* Look within any SIGN_EXTRACT or ZERO_EXTRACT
- to the MEM or REG within it. */
- while (GET_CODE (dest) == SIGN_EXTRACT
+ /* Look within any ZERO_EXTRACT to the MEM or REG within it. */
+ while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
because the value in it after the store
may not equal what was stored, due to truncation. */
- if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT
- || GET_CODE (SET_DEST (sets[i].rtl)) == SIGN_EXTRACT)
+ if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT)
{
rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
void
cselib_invalidate_rtx (rtx dest)
{
- while (GET_CODE (dest) == STRICT_LOW_PART || GET_CODE (dest) == SIGN_EXTRACT
- || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SUBREG)
+ while (GET_CODE (dest) == SUBREG
+ || GET_CODE (dest) == ZERO_EXTRACT
+ || GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
if (REG_P (dest))
the reg-def lists contain all the refs that define a given register
while the insn-use lists contain all the refs used by an insn.
-Note that the reg-def and reg-use chains are generally short (except for the
-hard registers) and thus it is much faster to search these chains
+Note that the reg-def and reg-use chains are generally short (except for
+the hard registers) and thus it is much faster to search these chains
rather than searching the def or use bitmaps.
If the insns are in SSA form then the reg-def and use-def lists
even though reg 41 is decremented before it is used for the memory
address in this second example.
-A set to a REG inside a ZERO_EXTRACT, SIGN_EXTRACT, or SUBREG invokes
-a read-modify write operation. We generate both a use and a def
-and again mark them read/write.
-*/
+A set to a REG inside a ZERO_EXTRACT, or a set to a non-paradoxical SUBREG
+for which the number of word_mode units covered by the outer mode is
+smaller than that covered by the inner mode, invokes a read-modify-write.
+operation. We generate both a use and a def and again mark them
+read/write.
+Paradoxical subreg writes don't leave a trace of the old content, so they
+are write-only operations. */
#include "config.h"
#include "system.h"
}
-/* Return nonzero if writes to paradoxical SUBREGs, or SUBREGs which
- are too narrow, are read-modify-write. */
+/* A set to a non-paradoxical SUBREG for which the number of word_mode units
+ covered by the outer mode is smaller than that covered by the inner mode,
+ is a read-modify-write operation.
+ This function returns true iff the SUBREG X is such a SUBREG. */
bool
read_modify_subreg_p (rtx x)
{
return false;
isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
osize = GET_MODE_SIZE (GET_MODE (x));
- /* Paradoxical subreg writes don't leave a trace of the old content. */
return (isize > osize && isize > UNITS_PER_WORD);
}
be handy for the reg allocator. */
while (GET_CODE (dst) == STRICT_LOW_PART
|| GET_CODE (dst) == ZERO_EXTRACT
- || GET_CODE (dst) == SIGN_EXTRACT
|| ((df->flags & DF_FOR_REGALLOC) == 0
&& read_modify_subreg_p (dst)))
{
@cindex bit-fields
Special expression codes exist to represent bit-field instructions.
-These types of expressions are lvalues in RTL; they may appear
-on the left side of an assignment, indicating insertion of a value
-into the specified bit-field.
@table @code
@findex sign_extract
The mode @var{m} is the same as the mode that would be used for
@var{loc} if it were a register.
+A @code{sign_extract} can not appear as an lvalue, or part thereof,
+in RTL.
+
@findex zero_extract
@item (zero_extract:@var{m} @var{loc} @var{size} @var{pos})
Like @code{sign_extract} but refers to an unsigned or zero-extended
bit-field. The same sequence of bits are extracted, but they
are filled to an entire word with zeros instead of by sign-extension.
+
+Unlike @code{sign_extract}, this type of expressions can be lvalues
+in RTL; they may appear on the left side of an assignment, indicating
+insertion of a value into the specified bit-field.
@end table
@node Vector Operations
the mode of the register, the rest of the register can be changed in
an undefined way.
-If @var{lval} is a @code{strict_low_part} or @code{zero_extract}
-of a @code{subreg}, then the part of the register specified by the
-machine mode of the @code{subreg} is given the value @var{x} and
-the rest of the register is not changed.
+If @var{lval} is a @code{strict_low_part} of a subreg, then the part
+of the register specified by the machine mode of the @code{subreg} is
+given the value @var{x} and the rest of the register is not changed.
+
+If @var{lval} is a @code{zero_extract}, then the referenced part of
+the bit-field (a memory or register reference) specified by the
+@code{zero_extract} is given the value @var{x} and the rest of the
+bit-field is not changed. Note that @code{sign_extract} can not
+appear in @var{lval}.
If @var{lval} is @code{(cc0)}, it has no machine mode, and @var{x} may
be either a @code{compare} expression or a value that may have any mode.
flags);
return;
- case ZERO_EXTRACT:
case SIGN_EXTRACT:
+ /* SIGN_EXTRACT cannot be an lvalue. */
+ gcc_unreachable ();
+
+ case ZERO_EXTRACT:
case STRICT_LOW_PART:
/* ??? Assumes STRICT_LOW_PART not used on multi-word registers. */
do
reg = XEXP (reg, 0);
while (GET_CODE (reg) == SUBREG
|| GET_CODE (reg) == ZERO_EXTRACT
- || GET_CODE (reg) == SIGN_EXTRACT
|| GET_CODE (reg) == STRICT_LOW_PART);
if (MEM_P (reg))
break;
then this SET is not needed. */
while (GET_CODE (testreg) == STRICT_LOW_PART
|| GET_CODE (testreg) == ZERO_EXTRACT
- || GET_CODE (testreg) == SIGN_EXTRACT
|| GET_CODE (testreg) == SUBREG)
{
#ifdef CANNOT_CHANGE_MODE_CLASS
{
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
have a note, and have no special SET, add a REG_EQUAL note to not
lose information. */
if (!success && note == 0 && set != 0
- && GET_CODE (XEXP (set, 0)) != ZERO_EXTRACT
- && GET_CODE (XEXP (set, 0)) != SIGN_EXTRACT)
+ && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT)
note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
}
rtx pat = PATTERN (insn);
rtx dest = SET_DEST (pat);
- if (GET_CODE (dest) == SIGN_EXTRACT
- || GET_CODE (dest) == ZERO_EXTRACT)
+ if (GET_CODE (dest) == ZERO_EXTRACT)
dest = XEXP (dest, 0);
/* Check for memory stores to aliased objects. */
rtx dest = SET_DEST (x);
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
if (REG_P (dest))
dest_reg, insn,
inc_val, mult_val, location);
- while (GET_CODE (dest) == SIGN_EXTRACT
+ while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
if (dest == x)
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
/* note_stores might have stripped a STRICT_LOW_PART, so we have to be
careful with registers / register parts that are not full words.
-
- Similarly for ZERO_EXTRACT and SIGN_EXTRACT. */
+ Similarly for ZERO_EXTRACT. */
if (GET_CODE (set) != SET
|| GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
- || GET_CODE (SET_DEST (set)) == SIGN_EXTRACT
|| GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
{
for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
if (SCALAR_INT_MODE_P (mode)
&& hard_regno_nregs[regno][mode] == 1 && GET_CODE (set) == SET
&& GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
- && GET_CODE (SET_DEST (set)) != SIGN_EXTRACT
&& GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
{
rtx src = SET_SRC (set);
rtx dest = SET_DEST (pat);
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
if (REG_P (dest))
rtx dest = SET_DEST (v1);
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
if (REG_P (dest))
case SET:
/* Usually, the first operand of SET is set, not referenced. But
registers used to access memory are referenced. SET_DEST is
- also referenced if it is a ZERO_EXTRACT or SIGN_EXTRACT. */
+ also referenced if it is a ZERO_EXTRACT. */
mark_referenced_resources (SET_SRC (x), res, 0);
x = SET_DEST (x);
- if (GET_CODE (x) == SIGN_EXTRACT
- || GET_CODE (x) == ZERO_EXTRACT
+ if (GET_CODE (x) == ZERO_EXTRACT
|| GET_CODE (x) == STRICT_LOW_PART)
mark_referenced_resources (x, res, 0);
else if (GET_CODE (x) == SUBREG)
If BITS_BIG_ENDIAN is defined, the first bit is the msb and
operand 2 counts from the msb of the memory unit.
Otherwise, the first bit is the lsb and operand 2 counts from
- the lsb of the memory unit. */
+ the lsb of the memory unit.
+ This kind of expression can not appear as an lvalue in RTL. */
DEF_RTL_EXPR(SIGN_EXTRACT, "sign_extract", "eee", RTX_BITFIELD_OPS)
-/* Similar for unsigned bit-field. */
+/* Similar for unsigned bit-field.
+ But note! This kind of expression _can_ appear as an lvalue. */
DEF_RTL_EXPR(ZERO_EXTRACT, "zero_extract", "eee", RTX_BITFIELD_OPS)
/* For RISC machines. These save memory when splitting insns. */
if (MEM_P (dst) && MEM_P (src))
return rtx_equal_p (dst, src) && !side_effects_p (dst);
- if (GET_CODE (dst) == SIGN_EXTRACT
- || GET_CODE (dst) == ZERO_EXTRACT)
+ if (GET_CODE (dst) == ZERO_EXTRACT)
return rtx_equal_p (XEXP (dst, 0), src)
&& ! BYTES_BIG_ENDIAN && XEXP (dst, 2) == const0_rtx
&& !side_effects_p (src);
&& (!REG_P (SUBREG_REG (dest))
|| REGNO (SUBREG_REG (dest)) >= FIRST_PSEUDO_REGISTER))
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
This will be true if X is (cc0) or if X is a register and
X dies in INSN or because INSN entirely sets X.
- "Entirely set" means set directly and not through a SUBREG,
- ZERO_EXTRACT or SIGN_EXTRACT, so no trace of the old contents remains.
+ "Entirely set" means set directly and not through a SUBREG, or
+ ZERO_EXTRACT, so no trace of the old contents remains.
Likewise, REG_INC does not count.
REG may be a hard or pseudo reg. Renumbering is not taken into account,
}
while (GET_CODE (dest) == STRICT_LOW_PART || GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SIGN_EXTRACT)
+ || GET_CODE (dest) == ZERO_EXTRACT)
{
if (GET_CODE (dest) == STRICT_LOW_PART
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| read_modify_subreg_p (dest))
{
/* These both read and modify the result. We must handle
sched_analyze_2 (deps, XEXP (dest, 0), insn);
}
- if (GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SIGN_EXTRACT)
+ if (GET_CODE (dest) == ZERO_EXTRACT)
{
/* The second and third arguments are values read by this insn. */
sched_analyze_2 (deps, XEXP (dest, 1), insn);
if (reg == 0)
return 1;
- while (GET_CODE (reg) == SUBREG || GET_CODE (reg) == ZERO_EXTRACT
- || GET_CODE (reg) == SIGN_EXTRACT
+ while (GET_CODE (reg) == SUBREG
+ || GET_CODE (reg) == ZERO_EXTRACT
|| GET_CODE (reg) == STRICT_LOW_PART)
reg = XEXP (reg, 0);
if (reg == 0)
return;
- while (GET_CODE (reg) == SUBREG || GET_CODE (reg) == ZERO_EXTRACT
- || GET_CODE (reg) == SIGN_EXTRACT
+ while (GET_CODE (reg) == SUBREG
+ || GET_CODE (reg) == ZERO_EXTRACT
|| GET_CODE (reg) == STRICT_LOW_PART)
reg = XEXP (reg, 0);