#include "basic-block.h"
#include "real.h"
#include "regs.h"
+#include "function.h"
/* Forward declarations */
static int global_reg_mentioned_p_1 (rtx *, void *);
static bool hoist_test_store (rtx, rtx, regset);
static void hoist_update_store (rtx, rtx *, rtx, rtx);
+static unsigned HOST_WIDE_INT cached_nonzero_bits (rtx, enum machine_mode,
+ rtx, enum machine_mode,
+ unsigned HOST_WIDE_INT);
+static unsigned HOST_WIDE_INT nonzero_bits1 (rtx, enum machine_mode, rtx,
+ enum machine_mode,
+ unsigned HOST_WIDE_INT);
+static unsigned int cached_num_sign_bit_copies (rtx, enum machine_mode, rtx,
+ enum machine_mode,
+ unsigned int);
+static unsigned int num_sign_bit_copies1 (rtx, enum machine_mode, rtx,
+ enum machine_mode, unsigned int);
+
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file
and set by `-m...' switches. Must be defined in rtlanal.c. */
case MEM:
return ! RTX_UNCHANGING_P (x) || rtx_unstable_p (XEXP (x, 0));
- case QUEUED:
- return 1;
-
- case ADDRESSOF:
case CONST:
case CONST_INT:
case CONST_DOUBLE:
case MEM:
return ! RTX_UNCHANGING_P (x) || rtx_varies_p (XEXP (x, 0), for_alias);
- case QUEUED:
- return 1;
-
case CONST:
case CONST_INT:
case CONST_DOUBLE:
case LABEL_REF:
return 0;
- case ADDRESSOF:
- /* This will resolve to some offset from the frame pointer. */
- return 0;
-
case REG:
/* Note that we have to test for the actual rtx used for the frame
and arg pointers and not just the register number in case we have
case LABEL_REF:
return 0;
- case ADDRESSOF:
- /* This will resolve to some offset from the frame pointer. */
- return 0;
-
case REG:
/* As in rtx_varies_p, we have to use the actual rtx, not reg number. */
if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
case LABEL_REF:
return true;
- case ADDRESSOF:
- /* This will resolve to some offset from the frame pointer. */
- return true;
-
case REG:
/* As in rtx_varies_p, we have to use the actual rtx, not reg number. */
if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
x = XEXP (x, 1);
/* Search backwards and locate the expression stored in X. */
- for (old_x = NULL_RTX; GET_CODE (x) == REG && x != old_x;
+ for (old_x = NULL_RTX; REG_P (x) && x != old_x;
old_x = x, x = find_last_value (x, &insn, NULL_RTX, 0))
;
if (y == pc_rtx || y == pic_offset_table_rtx)
break;
- for (old_y = NULL_RTX; GET_CODE (y) == REG && y != old_y;
+ for (old_y = NULL_RTX; REG_P (y) && y != old_y;
old_y = y, y = find_last_value (y, &old_insn, NULL_RTX, 0))
;
x = XEXP (x, 1 - i);
- for (old_x = NULL_RTX; GET_CODE (x) == REG && x != old_x;
+ for (old_x = NULL_RTX; REG_P (x) && x != old_x;
old_x = x, x = find_last_value (x, &insn, NULL_RTX, 0))
;
}
{
x = XEXP (x, 0);
- for (old_x = NULL_RTX; GET_CODE (x) == REG && x != old_x;
+ for (old_x = NULL_RTX; REG_P (x) && x != old_x;
old_x = x, x = find_last_value (x, &insn, NULL_RTX, 0))
;
}
/* If X isn't a MEM then this isn't a tablejump we understand. */
- if (GET_CODE (x) != MEM)
+ if (!MEM_P (x))
return NULL_RTX;
/* Strip off the MEM. */
x = XEXP (x, 0);
- for (old_x = NULL_RTX; GET_CODE (x) == REG && x != old_x;
+ for (old_x = NULL_RTX; REG_P (x) && x != old_x;
old_x = x, x = find_last_value (x, &insn, NULL_RTX, 0))
;
old_insn = insn;
y = XEXP (x, i);
- for (old_y = NULL_RTX; GET_CODE (y) == REG && y != old_y;
+ for (old_y = NULL_RTX; REG_P (y) && y != old_y;
old_y = y, y = find_last_value (y, &old_insn, NULL_RTX, 0))
;
switch (GET_CODE (x))
{
case SUBREG:
- if (GET_CODE (SUBREG_REG (x)) == REG)
+ if (REG_P (SUBREG_REG (x)))
{
if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
&& global_regs[subreg_regno (x)])
{
if (INSN_P (x))
{
- if (GET_CODE (x) == CALL_INSN)
+ if (CALL_P (x))
{
if (! CONST_OR_PURE_CALL_P (x))
return 1;
return 0;
case MEM:
- if (GET_CODE (find) == MEM && rtx_equal_p (x, find))
+ if (MEM_P (find) && rtx_equal_p (x, find))
return 1;
break;
{
/* Compare registers by number. */
case REG:
- return GET_CODE (reg) == REG && REGNO (in) == REGNO (reg);
+ return REG_P (reg) && REGNO (in) == REGNO (reg);
/* These codes have no constituent expressions
and are unique. */
if (beg == end)
return 0;
for (p = NEXT_INSN (beg); p != end; p = NEXT_INSN (p))
- if (GET_CODE (p) == CODE_LABEL)
+ if (LABEL_P (p))
return 0;
return 1;
}
{
rtx p;
for (p = NEXT_INSN (beg); p != end; p = NEXT_INSN (p))
- if (GET_CODE (p) == JUMP_INSN)
+ if (JUMP_P (p))
return 0;
return 1;
}
for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn))
if (INSN_P (insn)
&& (reg_overlap_mentioned_p (reg, PATTERN (insn))
- || (GET_CODE (insn) == CALL_INSN
+ || (CALL_P (insn)
&& (find_reg_fusage (insn, USE, reg)
|| find_reg_fusage (insn, CLOBBER, reg)))))
return 1;
it is mentioned in the destination. */
if (GET_CODE (SET_DEST (body)) != CC0
&& GET_CODE (SET_DEST (body)) != PC
- && GET_CODE (SET_DEST (body)) != REG
+ && !REG_P (SET_DEST (body))
&& ! (GET_CODE (SET_DEST (body)) == SUBREG
- && GET_CODE (SUBREG_REG (SET_DEST (body))) == REG
+ && REG_P (SUBREG_REG (SET_DEST (body)))
&& (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (body))))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SET_DEST (body)))
return 0;
case CLOBBER:
- if (GET_CODE (XEXP (body, 0)) == MEM)
+ if (MEM_P (XEXP (body, 0)))
if (reg_overlap_mentioned_p (x, XEXP (XEXP (body, 0), 0)))
return 1;
return 0;
for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn))
if (INSN_P (insn)
&& (reg_referenced_p (reg, PATTERN (insn))
- || (GET_CODE (insn) == CALL_INSN
+ || (CALL_P (insn)
&& find_reg_fusage (insn, USE, reg))))
return 1;
return 0;
check if a side-effect of the insn clobbers REG. */
if (INSN_P (insn)
&& (FIND_REG_INC_NOTE (insn, reg)
- || (GET_CODE (insn) == CALL_INSN
- /* We'd like to test call_used_regs here, but rtlanal.c can't
- reference that variable due to its use in genattrtab. So
- we'll just be more conservative.
-
- ??? Unless we could ensure that the CALL_INSN_FUNCTION_USAGE
- information holds all clobbered registers. */
- && ((GET_CODE (reg) == REG
- && REGNO (reg) < FIRST_PSEUDO_REGISTER)
- || GET_CODE (reg) == MEM
+ || (CALL_P (insn)
+ && ((REG_P (reg)
+ && REGNO (reg) < FIRST_PSEUDO_REGISTER
+ && TEST_HARD_REG_BIT (regs_invalidated_by_call,
+ REGNO (reg)))
+ || MEM_P (reg)
|| find_reg_fusage (insn, CLOBBER, reg)))))
return 1;
{
struct set_of_data *data = (struct set_of_data *) (data1);
if (rtx_equal_p (x, data->pat)
- || (GET_CODE (x) != MEM && reg_overlap_mentioned_p (data->pat, x)))
+ || (!MEM_P (x) && reg_overlap_mentioned_p (data->pat, x)))
data->found = pat;
}
if (dst == pc_rtx && src == pc_rtx)
return 1;
- if (GET_CODE (dst) == MEM && GET_CODE (src) == MEM)
+ if (MEM_P (dst) && MEM_P (src))
return rtx_equal_p (dst, src) && !side_effects_p (dst);
if (GET_CODE (dst) == SIGN_EXTRACT
dst = SUBREG_REG (dst);
}
- return (GET_CODE (src) == REG && GET_CODE (dst) == REG
+ return (REG_P (src) && REG_P (dst)
&& REGNO (src) == REGNO (dst));
}
\f
{
rtx p;
- for (p = PREV_INSN (*pinsn); p && GET_CODE (p) != CODE_LABEL;
+ for (p = PREV_INSN (*pinsn); p && !LABEL_P (p);
p = PREV_INSN (p))
if (INSN_P (p))
{
|| ! modified_between_p (src, PREV_INSN (p), valid_to))
/* Reject hard registers because we don't usually want
to use them; we'd rather use a pseudo. */
- && (! (GET_CODE (src) == REG
+ && (! (REG_P (src)
&& REGNO (src) < FIRST_PSEUDO_REGISTER) || allow_hwreg))
{
*pinsn = p;
case SUBREG:
/* If this is a SUBREG of a hard reg, we can see exactly which
registers are being modified. Otherwise, handle normally. */
- if (GET_CODE (SUBREG_REG (x)) == REG
+ if (REG_P (SUBREG_REG (x))
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
unsigned int inner_regno = subreg_regno (x);
treat each word individually. */
&& ((GET_CODE (SET_DEST (x)) == SUBREG
&& loc != &SUBREG_REG (SET_DEST (x))
- && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
+ && REG_P (SUBREG_REG (SET_DEST (x)))
&& REGNO (SUBREG_REG (SET_DEST (x))) >= FIRST_PSEUDO_REGISTER
&& refers_to_regno_p (regno, endregno,
SUBREG_REG (SET_DEST (x)), loc))
- || (GET_CODE (SET_DEST (x)) != REG
+ || (!REG_P (SET_DEST (x))
&& refers_to_regno_p (regno, endregno, SET_DEST (x), loc))))
return 1;
const char *fmt;
int i;
- if (GET_CODE (in) == MEM)
+ if (MEM_P (in))
return 1;
fmt = GET_RTX_FORMAT (GET_CODE (in));
rtx dest = SET_DEST (x);
while ((GET_CODE (dest) == SUBREG
- && (GET_CODE (SUBREG_REG (dest)) != REG
+ && (!REG_P (SUBREG_REG (dest))
|| REGNO (SUBREG_REG (dest)) >= FIRST_PSEUDO_REGISTER))
|| GET_CODE (dest) == ZERO_EXTRACT
|| GET_CODE (dest) == SIGN_EXTRACT
return;
case CLOBBER:
- if (GET_CODE (XEXP (body, 0)) == MEM)
+ if (MEM_P (XEXP (body, 0)))
(*fun) (&XEXP (XEXP (body, 0), 0), data);
return;
while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
- if (GET_CODE (dest) == MEM)
+ if (MEM_P (dest))
(*fun) (&XEXP (dest, 0), data);
}
return;
if (GET_CODE (x) == CC0)
return 1;
- if (GET_CODE (x) != REG)
+ if (!REG_P (x))
abort ();
regno = REGNO (x);
if (find_regno_note (insn, REG_DEAD, test_regno))
return 1;
- if (GET_CODE (insn) == CALL_INSN
+ if (CALL_P (insn)
&& find_regno_fusage (insn, CLOBBER, test_regno))
return 1;
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
dest = SUBREG_REG (dest);
- if (GET_CODE (dest) != REG)
+ if (!REG_P (dest))
return 0;
regno = REGNO (dest);
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
dest = SUBREG_REG (dest);
- if (GET_CODE (dest) != REG)
+ if (!REG_P (dest))
continue;
regno = REGNO (dest);
if (REG_NOTE_KIND (link) == kind
/* Verify that it is a register, so that scratch and MEM won't cause a
problem here. */
- && GET_CODE (XEXP (link, 0)) == REG
+ && REG_P (XEXP (link, 0))
&& REGNO (XEXP (link, 0)) <= regno
&& ((REGNO (XEXP (link, 0))
+ (REGNO (XEXP (link, 0)) >= FIRST_PSEUDO_REGISTER ? 1
{
/* If it's not a CALL_INSN, it can't possibly have a
CALL_INSN_FUNCTION_USAGE field, so don't bother checking. */
- if (GET_CODE (insn) != CALL_INSN)
+ if (!CALL_P (insn))
return 0;
if (! datum)
abort ();
- if (GET_CODE (datum) != REG)
+ if (!REG_P (datum))
{
rtx link;
to pseudo registers, so don't bother checking. */
if (regno >= FIRST_PSEUDO_REGISTER
- || GET_CODE (insn) != CALL_INSN )
+ || !CALL_P (insn) )
return 0;
for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
rtx op, reg;
if (GET_CODE (op = XEXP (link, 0)) == code
- && GET_CODE (reg = XEXP (op, 0)) == REG
+ && REG_P (reg = XEXP (op, 0))
&& (regnote = REGNO (reg)) <= regno
&& regnote + hard_regno_nregs[regnote][GET_MODE (reg)] > regno)
return 1;
{
rtx link;
- if (GET_CODE (insn) != CALL_INSN || ! CONST_OR_PURE_CALL_P (insn))
+ if (!CALL_P (insn) || ! CONST_OR_PURE_CALL_P (insn))
return 0;
/* Look for the note that differentiates const and pure functions. */
rtx u, m;
if (GET_CODE (u = XEXP (link, 0)) == USE
- && GET_CODE (m = XEXP (u, 0)) == MEM && GET_MODE (m) == BLKmode
+ && MEM_P (m = XEXP (u, 0)) && GET_MODE (m) == BLKmode
&& GET_CODE (XEXP (m, 0)) == SCRATCH)
return 1;
}
case GT:
case LE:
case LT:
+ case LTGT:
case COMPARE:
/* Some floating point comparisons may trap. */
if (!flag_trapping_math)
case SUBREG:
/* Prevent making nested SUBREGs. */
- if (GET_CODE (SUBREG_REG (x)) == REG && REGNO (SUBREG_REG (x)) < nregs
+ if (REG_P (SUBREG_REG (x)) && REGNO (SUBREG_REG (x)) < nregs
&& reg_map[REGNO (SUBREG_REG (x))] != 0
&& GET_CODE (reg_map[REGNO (SUBREG_REG (x))]) == SUBREG)
{
if (replace_dest)
SET_DEST (x) = replace_regs (SET_DEST (x), reg_map, nregs, 0);
- else if (GET_CODE (SET_DEST (x)) == MEM
+ else if (MEM_P (SET_DEST (x))
|| GET_CODE (SET_DEST (x)) == STRICT_LOW_PART)
/* Even if we are not to replace destinations, replace register if it
is CONTAINED in destination (destination is memory or
/* If this is a JUMP_INSN, then we also need to fix the JUMP_LABEL
field. This is not handled by for_each_rtx because it doesn't
handle unprinted ('0') fields. */
- if (GET_CODE (l) == JUMP_INSN && JUMP_LABEL (l) == old_label)
+ if (JUMP_P (l) && JUMP_LABEL (l) == old_label)
JUMP_LABEL (l) = new_label;
if ((GET_CODE (l) == LABEL_REF
return y == NULL_RTX;
/* Return true if a label_ref *BODY refers to label Y. */
- if (GET_CODE (*body) == LABEL_REF && GET_CODE (y) == CODE_LABEL)
+ if (GET_CODE (*body) == LABEL_REF && LABEL_P (y))
return XEXP (*body, 0) == y;
/* If *BODY is a reference to pool constant traverse the constant. */
{
rtx label, table;
- if (GET_CODE (insn) == JUMP_INSN
+ if (JUMP_P (insn)
&& (label = JUMP_LABEL (insn)) != NULL_RTX
&& (table = next_active_insn (label)) != NULL_RTX
- && GET_CODE (table) == JUMP_INSN
+ && JUMP_P (table)
&& (GET_CODE (PATTERN (table)) == ADDR_VEC
|| GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
{
computed_jump_p (rtx insn)
{
int i;
- if (GET_CODE (insn) == JUMP_INSN)
+ if (JUMP_P (insn))
{
rtx pat = PATTERN (insn);
int i, j;
rtx tem;
- if (GET_CODE (x) == REG && REGNO (x) == regno)
+ if (REG_P (x) && REGNO (x) == regno)
return x;
fmt = GET_RTX_FORMAT (GET_CODE (x));
while (r)
{
- if (GET_CODE (r) == NOTE)
+ if (NOTE_P (r))
{
switch (NOTE_LINE_NUMBER (r))
{
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
- if (loc == &in->u.fld[i].rtx)
+ if (loc == &in->u.fld[i].rt_rtx)
return 1;
if (fmt[i] == 'e')
{
parm.nregs = 0;
for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1))
if (GET_CODE (XEXP (p, 0)) == USE
- && GET_CODE (XEXP (XEXP (p, 0), 0)) == REG)
+ && REG_P (XEXP (XEXP (p, 0), 0)))
{
if (REGNO (XEXP (XEXP (p, 0), 0)) >= FIRST_PSEUDO_REGISTER)
abort ();
/* It is possible that some loads got CSEed from one call to
another. Stop in that case. */
- if (GET_CODE (before) == CALL_INSN)
+ if (CALL_P (before))
break;
/* Our caller needs either ensure that we will find all sets
(in case code has not been optimized yet), or take care
for possible labels in a way by setting boundary to preceding
CODE_LABEL. */
- if (GET_CODE (before) == CODE_LABEL)
+ if (LABEL_P (before))
{
if (before != boundary)
abort ();
if (INSN_P (insn) && (set = single_set (insn)) != NULL)
{
- if (GET_CODE (SET_DEST (set)) == REG
+ if (REG_P (SET_DEST (set))
&& REGNO (SET_DEST (set)) < FIRST_PSEUDO_REGISTER
&& fixed_regs[REGNO (SET_DEST (set))]
&& general_operand (SET_SRC (set), VOIDmode))
return true;
- if (GET_CODE (SET_SRC (set)) == REG
+ if (REG_P (SET_SRC (set))
&& FUNCTION_VALUE_REGNO_P (REGNO (SET_SRC (set)))
- && GET_CODE (SET_DEST (set)) == REG
+ && REG_P (SET_DEST (set))
&& REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
return true;
/* There may be a stack pop just after the call and before the store
return false;
/* We can move CALL_INSN, but we need to check that all caller clobbered
regs are dead. */
- if (GET_CODE (insn) == CALL_INSN)
+ if (CALL_P (insn))
return false;
/* In future we will handle hoisting of libcall sequences, but
give up for now. */
int
address_cost (rtx x, enum machine_mode mode)
{
- /* The address_cost target hook does not deal with ADDRESSOF nodes. But,
- during CSE, such nodes are present. Using an ADDRESSOF node which
- refers to the address of a REG is a good thing because we can then
- turn (MEM (ADDRESSOF (REG))) into just plain REG. */
-
- if (GET_CODE (x) == ADDRESSOF && REG_P (XEXP ((x), 0)))
- return -1;
-
/* We may be asked for cost of various unusual addresses, such as operands
of push instruction. It is not worthwhile to complicate writing
of the target hook by such cases. */
{
return rtx_cost (x, MEM);
}
+\f
+
+unsigned HOST_WIDE_INT
+nonzero_bits (rtx x, enum machine_mode mode)
+{
+ return cached_nonzero_bits (x, mode, NULL_RTX, VOIDmode, 0);
+}
+
+unsigned int
+num_sign_bit_copies (rtx x, enum machine_mode mode)
+{
+ return cached_num_sign_bit_copies (x, mode, NULL_RTX, VOIDmode, 0);
+}
+
+/* The function cached_nonzero_bits is a wrapper around nonzero_bits1.
+ It avoids exponential behavior in nonzero_bits1 when X has
+ identical subexpressions on the first or the second level. */
+
+static unsigned HOST_WIDE_INT
+cached_nonzero_bits (rtx x, enum machine_mode mode, rtx known_x,
+ enum machine_mode known_mode,
+ unsigned HOST_WIDE_INT known_ret)
+{
+ if (x == known_x && mode == known_mode)
+ return known_ret;
+
+ /* Try to find identical subexpressions. If found call
+ nonzero_bits1 on X with the subexpressions as KNOWN_X and the
+ precomputed value for the subexpression as KNOWN_RET. */
+
+ if (ARITHMETIC_P (x))
+ {
+ rtx x0 = XEXP (x, 0);
+ rtx x1 = XEXP (x, 1);
+
+ /* Check the first level. */
+ if (x0 == x1)
+ return nonzero_bits1 (x, mode, x0, mode,
+ cached_nonzero_bits (x0, mode, known_x,
+ known_mode, known_ret));
+
+ /* Check the second level. */
+ if (ARITHMETIC_P (x0)
+ && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+ return nonzero_bits1 (x, mode, x1, mode,
+ cached_nonzero_bits (x1, mode, known_x,
+ known_mode, known_ret));
+
+ if (ARITHMETIC_P (x1)
+ && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+ return nonzero_bits1 (x, mode, x0, mode,
+ cached_nonzero_bits (x0, mode, known_x,
+ known_mode, known_ret));
+ }
+
+ return nonzero_bits1 (x, mode, known_x, known_mode, known_ret);
+}
+
+/* We let num_sign_bit_copies recur into nonzero_bits as that is useful.
+ We don't let nonzero_bits recur into num_sign_bit_copies, because that
+ is less useful. We can't allow both, because that results in exponential
+ run time recursion. There is a nullstone testcase that triggered
+ this. This macro avoids accidental uses of num_sign_bit_copies. */
+#define cached_num_sign_bit_copies sorry_i_am_preventing_exponential_behavior
+
+/* Given an expression, X, compute which bits in X can be nonzero.
+ We don't care about bits outside of those defined in MODE.
+
+ For most X this is simply GET_MODE_MASK (GET_MODE (MODE)), but if X is
+ an arithmetic operation, we can do better. */
+
+static unsigned HOST_WIDE_INT
+nonzero_bits1 (rtx x, enum machine_mode mode, rtx known_x,
+ enum machine_mode known_mode,
+ unsigned HOST_WIDE_INT known_ret)
+{
+ unsigned HOST_WIDE_INT nonzero = GET_MODE_MASK (mode);
+ unsigned HOST_WIDE_INT inner_nz;
+ enum rtx_code code;
+ unsigned int mode_width = GET_MODE_BITSIZE (mode);
+
+ /* For floating-point values, assume all bits are needed. */
+ if (FLOAT_MODE_P (GET_MODE (x)) || FLOAT_MODE_P (mode))
+ return nonzero;
+
+ /* If X is wider than MODE, use its mode instead. */
+ if (GET_MODE_BITSIZE (GET_MODE (x)) > mode_width)
+ {
+ mode = GET_MODE (x);
+ nonzero = GET_MODE_MASK (mode);
+ mode_width = GET_MODE_BITSIZE (mode);
+ }
+
+ if (mode_width > HOST_BITS_PER_WIDE_INT)
+ /* Our only callers in this case look for single bit values. So
+ just return the mode mask. Those tests will then be false. */
+ return nonzero;
+
+#ifndef WORD_REGISTER_OPERATIONS
+ /* If MODE is wider than X, but both are a single word for both the host
+ and target machines, we can compute this from which bits of the
+ object might be nonzero in its own mode, taking into account the fact
+ that on many CISC machines, accessing an object in a wider mode
+ causes the high-order bits to become undefined. So they are
+ not known to be zero. */
+
+ if (GET_MODE (x) != VOIDmode && GET_MODE (x) != mode
+ && GET_MODE_BITSIZE (GET_MODE (x)) <= BITS_PER_WORD
+ && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
+ && GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (GET_MODE (x)))
+ {
+ nonzero &= cached_nonzero_bits (x, GET_MODE (x),
+ known_x, known_mode, known_ret);
+ nonzero |= GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x));
+ return nonzero;
+ }
+#endif
+
+ code = GET_CODE (x);
+ switch (code)
+ {
+ case REG:
+#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
+ /* If pointers extend unsigned and this is a pointer in Pmode, say that
+ all the bits above ptr_mode are known to be zero. */
+ if (POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
+ && REG_POINTER (x))
+ nonzero &= GET_MODE_MASK (ptr_mode);
+#endif
+
+ /* Include declared information about alignment of pointers. */
+ /* ??? We don't properly preserve REG_POINTER changes across
+ pointer-to-integer casts, so we can't trust it except for
+ things that we know must be pointers. See execute/960116-1.c. */
+ if ((x == stack_pointer_rtx
+ || x == frame_pointer_rtx
+ || x == arg_pointer_rtx)
+ && REGNO_POINTER_ALIGN (REGNO (x)))
+ {
+ unsigned HOST_WIDE_INT alignment
+ = REGNO_POINTER_ALIGN (REGNO (x)) / BITS_PER_UNIT;
+
+#ifdef PUSH_ROUNDING
+ /* If PUSH_ROUNDING is defined, it is possible for the
+ stack to be momentarily aligned only to that amount,
+ so we pick the least alignment. */
+ if (x == stack_pointer_rtx && PUSH_ARGS)
+ alignment = MIN ((unsigned HOST_WIDE_INT) PUSH_ROUNDING (1),
+ alignment);
+#endif
+
+ nonzero &= ~(alignment - 1);
+ }
+
+ {
+ unsigned HOST_WIDE_INT nonzero_for_hook = nonzero;
+ rtx new = rtl_hooks.reg_nonzero_bits (x, mode, known_x,
+ known_mode, known_ret,
+ &nonzero_for_hook);
+
+ if (new)
+ nonzero_for_hook &= cached_nonzero_bits (new, mode, known_x,
+ known_mode, known_ret);
+
+ return nonzero_for_hook;
+ }
+
+ case CONST_INT:
+#ifdef SHORT_IMMEDIATES_SIGN_EXTEND
+ /* If X is negative in MODE, sign-extend the value. */
+ if (INTVAL (x) > 0 && mode_width < BITS_PER_WORD
+ && 0 != (INTVAL (x) & ((HOST_WIDE_INT) 1 << (mode_width - 1))))
+ return (INTVAL (x) | ((HOST_WIDE_INT) (-1) << mode_width));
+#endif
+
+ return INTVAL (x);
+
+ case MEM:
+#ifdef LOAD_EXTEND_OP
+ /* In many, if not most, RISC machines, reading a byte from memory
+ zeros the rest of the register. Noticing that fact saves a lot
+ of extra zero-extends. */
+ if (LOAD_EXTEND_OP (GET_MODE (x)) == ZERO_EXTEND)
+ nonzero &= GET_MODE_MASK (GET_MODE (x));
+#endif
+ break;
+
+ case EQ: case NE:
+ case UNEQ: case LTGT:
+ case GT: case GTU: case UNGT:
+ case LT: case LTU: case UNLT:
+ case GE: case GEU: case UNGE:
+ case LE: case LEU: case UNLE:
+ case UNORDERED: case ORDERED:
+
+ /* If this produces an integer result, we know which bits are set.
+ Code here used to clear bits outside the mode of X, but that is
+ now done above. */
+
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && mode_width <= HOST_BITS_PER_WIDE_INT)
+ nonzero = STORE_FLAG_VALUE;
+ break;
+
+ case NEG:
+#if 0
+ /* Disabled to avoid exponential mutual recursion between nonzero_bits
+ and num_sign_bit_copies. */
+ if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x))
+ == GET_MODE_BITSIZE (GET_MODE (x)))
+ nonzero = 1;
+#endif
+
+ if (GET_MODE_SIZE (GET_MODE (x)) < mode_width)
+ nonzero |= (GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x)));
+ break;
+
+ case ABS:
+#if 0
+ /* Disabled to avoid exponential mutual recursion between nonzero_bits
+ and num_sign_bit_copies. */
+ if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x))
+ == GET_MODE_BITSIZE (GET_MODE (x)))
+ nonzero = 1;
+#endif
+ break;
+
+ case TRUNCATE:
+ nonzero &= (cached_nonzero_bits (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret)
+ & GET_MODE_MASK (mode));
+ break;
+
+ case ZERO_EXTEND:
+ nonzero &= cached_nonzero_bits (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ if (GET_MODE (XEXP (x, 0)) != VOIDmode)
+ nonzero &= GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
+ break;
+
+ case SIGN_EXTEND:
+ /* If the sign bit is known clear, this is the same as ZERO_EXTEND.
+ Otherwise, show all the bits in the outer mode but not the inner
+ may be nonzero. */
+ inner_nz = cached_nonzero_bits (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ if (GET_MODE (XEXP (x, 0)) != VOIDmode)
+ {
+ inner_nz &= GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
+ if (inner_nz
+ & (((HOST_WIDE_INT) 1
+ << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1))))
+ inner_nz |= (GET_MODE_MASK (mode)
+ & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0))));
+ }
+
+ nonzero &= inner_nz;
+ break;
+
+ case AND:
+ nonzero &= cached_nonzero_bits (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret)
+ & cached_nonzero_bits (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+ break;
+
+ case XOR: case IOR:
+ case UMIN: case UMAX: case SMIN: case SMAX:
+ {
+ unsigned HOST_WIDE_INT nonzero0 =
+ cached_nonzero_bits (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+
+ /* Don't call nonzero_bits for the second time if it cannot change
+ anything. */
+ if ((nonzero & nonzero0) != nonzero)
+ nonzero &= nonzero0
+ | cached_nonzero_bits (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+ }
+ break;
+
+ case PLUS: case MINUS:
+ case MULT:
+ case DIV: case UDIV:
+ case MOD: case UMOD:
+ /* We can apply the rules of arithmetic to compute the number of
+ high- and low-order zero bits of these operations. We start by
+ computing the width (position of the highest-order nonzero bit)
+ and the number of low-order zero bits for each value. */
+ {
+ unsigned HOST_WIDE_INT nz0 =
+ cached_nonzero_bits (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ unsigned HOST_WIDE_INT nz1 =
+ cached_nonzero_bits (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+ int sign_index = GET_MODE_BITSIZE (GET_MODE (x)) - 1;
+ int width0 = floor_log2 (nz0) + 1;
+ int width1 = floor_log2 (nz1) + 1;
+ int low0 = floor_log2 (nz0 & -nz0);
+ int low1 = floor_log2 (nz1 & -nz1);
+ HOST_WIDE_INT op0_maybe_minusp
+ = (nz0 & ((HOST_WIDE_INT) 1 << sign_index));
+ HOST_WIDE_INT op1_maybe_minusp
+ = (nz1 & ((HOST_WIDE_INT) 1 << sign_index));
+ unsigned int result_width = mode_width;
+ int result_low = 0;
+
+ switch (code)
+ {
+ case PLUS:
+ result_width = MAX (width0, width1) + 1;
+ result_low = MIN (low0, low1);
+ break;
+ case MINUS:
+ result_low = MIN (low0, low1);
+ break;
+ case MULT:
+ result_width = width0 + width1;
+ result_low = low0 + low1;
+ break;
+ case DIV:
+ if (width1 == 0)
+ break;
+ if (! op0_maybe_minusp && ! op1_maybe_minusp)
+ result_width = width0;
+ break;
+ case UDIV:
+ if (width1 == 0)
+ break;
+ result_width = width0;
+ break;
+ case MOD:
+ if (width1 == 0)
+ break;
+ if (! op0_maybe_minusp && ! op1_maybe_minusp)
+ result_width = MIN (width0, width1);
+ result_low = MIN (low0, low1);
+ break;
+ case UMOD:
+ if (width1 == 0)
+ break;
+ result_width = MIN (width0, width1);
+ result_low = MIN (low0, low1);
+ break;
+ default:
+ abort ();
+ }
+
+ if (result_width < mode_width)
+ nonzero &= ((HOST_WIDE_INT) 1 << result_width) - 1;
+
+ if (result_low > 0)
+ nonzero &= ~(((HOST_WIDE_INT) 1 << result_low) - 1);
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+ /* If pointers extend unsigned and this is an addition or subtraction
+ to a pointer in Pmode, all the bits above ptr_mode are known to be
+ zero. */
+ if (POINTERS_EXTEND_UNSIGNED > 0 && GET_MODE (x) == Pmode
+ && (code == PLUS || code == MINUS)
+ && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
+ nonzero &= GET_MODE_MASK (ptr_mode);
+#endif
+ }
+ break;
+
+ case ZERO_EXTRACT:
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT)
+ nonzero &= ((HOST_WIDE_INT) 1 << INTVAL (XEXP (x, 1))) - 1;
+ break;
+
+ case SUBREG:
+ /* If this is a SUBREG formed for a promoted variable that has
+ been zero-extended, we know that at least the high-order bits
+ are zero, though others might be too. */
+
+ if (SUBREG_PROMOTED_VAR_P (x) && SUBREG_PROMOTED_UNSIGNED_P (x) > 0)
+ nonzero = GET_MODE_MASK (GET_MODE (x))
+ & cached_nonzero_bits (SUBREG_REG (x), GET_MODE (x),
+ known_x, known_mode, known_ret);
+
+ /* If the inner mode is a single word for both the host and target
+ machines, we can compute this from which bits of the inner
+ object might be nonzero. */
+ if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) <= BITS_PER_WORD
+ && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
+ <= HOST_BITS_PER_WIDE_INT))
+ {
+ nonzero &= cached_nonzero_bits (SUBREG_REG (x), mode,
+ known_x, known_mode, known_ret);
+
+#if defined (WORD_REGISTER_OPERATIONS) && defined (LOAD_EXTEND_OP)
+ /* If this is a typical RISC machine, we only have to worry
+ about the way loads are extended. */
+ if ((LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
+ ? (((nonzero
+ & (((unsigned HOST_WIDE_INT) 1
+ << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1))))
+ != 0))
+ : LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) != ZERO_EXTEND)
+ || !MEM_P (SUBREG_REG (x)))
+#endif
+ {
+ /* On many CISC machines, accessing an object in a wider mode
+ causes the high-order bits to become undefined. So they are
+ not known to be zero. */
+ if (GET_MODE_SIZE (GET_MODE (x))
+ > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ nonzero |= (GET_MODE_MASK (GET_MODE (x))
+ & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (x))));
+ }
+ }
+ break;
+
+ case ASHIFTRT:
+ case LSHIFTRT:
+ case ASHIFT:
+ case ROTATE:
+ /* The nonzero bits are in two classes: any bits within MODE
+ that aren't in GET_MODE (x) are always significant. The rest of the
+ nonzero bits are those that are significant in the operand of
+ the shift when shifted the appropriate number of bits. This
+ shows that high-order bits are cleared by the right shift and
+ low-order bits by left shifts. */
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) >= 0
+ && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT)
+ {
+ enum machine_mode inner_mode = GET_MODE (x);
+ unsigned int width = GET_MODE_BITSIZE (inner_mode);
+ int count = INTVAL (XEXP (x, 1));
+ unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (inner_mode);
+ unsigned HOST_WIDE_INT op_nonzero =
+ cached_nonzero_bits (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ unsigned HOST_WIDE_INT inner = op_nonzero & mode_mask;
+ unsigned HOST_WIDE_INT outer = 0;
+
+ if (mode_width > width)
+ outer = (op_nonzero & nonzero & ~mode_mask);
+
+ if (code == LSHIFTRT)
+ inner >>= count;
+ else if (code == ASHIFTRT)
+ {
+ inner >>= count;
+
+ /* If the sign bit may have been nonzero before the shift, we
+ need to mark all the places it could have been copied to
+ by the shift as possibly nonzero. */
+ if (inner & ((HOST_WIDE_INT) 1 << (width - 1 - count)))
+ inner |= (((HOST_WIDE_INT) 1 << count) - 1) << (width - count);
+ }
+ else if (code == ASHIFT)
+ inner <<= count;
+ else
+ inner = ((inner << (count % width)
+ | (inner >> (width - (count % width)))) & mode_mask);
+
+ nonzero &= (outer | inner);
+ }
+ break;
+
+ case FFS:
+ case POPCOUNT:
+ /* This is at most the number of bits in the mode. */
+ nonzero = ((HOST_WIDE_INT) 2 << (floor_log2 (mode_width))) - 1;
+ break;
+
+ case CLZ:
+ /* If CLZ has a known value at zero, then the nonzero bits are
+ that value, plus the number of bits in the mode minus one. */
+ if (CLZ_DEFINED_VALUE_AT_ZERO (mode, nonzero))
+ nonzero |= ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width))) - 1;
+ else
+ nonzero = -1;
+ break;
+
+ case CTZ:
+ /* If CTZ has a known value at zero, then the nonzero bits are
+ that value, plus the number of bits in the mode minus one. */
+ if (CTZ_DEFINED_VALUE_AT_ZERO (mode, nonzero))
+ nonzero |= ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width))) - 1;
+ else
+ nonzero = -1;
+ break;
+
+ case PARITY:
+ nonzero = 1;
+ break;
+
+ case IF_THEN_ELSE:
+ {
+ unsigned HOST_WIDE_INT nonzero_true =
+ cached_nonzero_bits (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+
+ /* Don't call nonzero_bits for the second time if it cannot change
+ anything. */
+ if ((nonzero & nonzero_true) != nonzero)
+ nonzero &= nonzero_true
+ | cached_nonzero_bits (XEXP (x, 2), mode,
+ known_x, known_mode, known_ret);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return nonzero;
+}
+
+/* See the macro definition above. */
+#undef cached_num_sign_bit_copies
+
+\f
+/* The function cached_num_sign_bit_copies is a wrapper around
+ num_sign_bit_copies1. It avoids exponential behavior in
+ num_sign_bit_copies1 when X has identical subexpressions on the
+ first or the second level. */
+
+static unsigned int
+cached_num_sign_bit_copies (rtx x, enum machine_mode mode, rtx known_x,
+ enum machine_mode known_mode,
+ unsigned int known_ret)
+{
+ if (x == known_x && mode == known_mode)
+ return known_ret;
+
+ /* Try to find identical subexpressions. If found call
+ num_sign_bit_copies1 on X with the subexpressions as KNOWN_X and
+ the precomputed value for the subexpression as KNOWN_RET. */
+
+ if (ARITHMETIC_P (x))
+ {
+ rtx x0 = XEXP (x, 0);
+ rtx x1 = XEXP (x, 1);
+
+ /* Check the first level. */
+ if (x0 == x1)
+ return
+ num_sign_bit_copies1 (x, mode, x0, mode,
+ cached_num_sign_bit_copies (x0, mode, known_x,
+ known_mode,
+ known_ret));
+
+ /* Check the second level. */
+ if (ARITHMETIC_P (x0)
+ && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+ return
+ num_sign_bit_copies1 (x, mode, x1, mode,
+ cached_num_sign_bit_copies (x1, mode, known_x,
+ known_mode,
+ known_ret));
+
+ if (ARITHMETIC_P (x1)
+ && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+ return
+ num_sign_bit_copies1 (x, mode, x0, mode,
+ cached_num_sign_bit_copies (x0, mode, known_x,
+ known_mode,
+ known_ret));
+ }
+
+ return num_sign_bit_copies1 (x, mode, known_x, known_mode, known_ret);
+}
+
+/* Return the number of bits at the high-order end of X that are known to
+ be equal to the sign bit. X will be used in mode MODE; if MODE is
+ VOIDmode, X will be used in its own mode. The returned value will always
+ be between 1 and the number of bits in MODE. */
+
+static unsigned int
+num_sign_bit_copies1 (rtx x, enum machine_mode mode, rtx known_x,
+ enum machine_mode known_mode,
+ unsigned int known_ret)
+{
+ enum rtx_code code = GET_CODE (x);
+ unsigned int bitwidth = GET_MODE_BITSIZE (mode);
+ int num0, num1, result;
+ unsigned HOST_WIDE_INT nonzero;
+
+ /* If we weren't given a mode, use the mode of X. If the mode is still
+ VOIDmode, we don't know anything. Likewise if one of the modes is
+ floating-point. */
+
+ if (mode == VOIDmode)
+ mode = GET_MODE (x);
+
+ if (mode == VOIDmode || FLOAT_MODE_P (mode) || FLOAT_MODE_P (GET_MODE (x)))
+ return 1;
+
+ /* For a smaller object, just ignore the high bits. */
+ if (bitwidth < GET_MODE_BITSIZE (GET_MODE (x)))
+ {
+ num0 = cached_num_sign_bit_copies (x, GET_MODE (x),
+ known_x, known_mode, known_ret);
+ return MAX (1,
+ num0 - (int) (GET_MODE_BITSIZE (GET_MODE (x)) - bitwidth));
+ }
+
+ if (GET_MODE (x) != VOIDmode && bitwidth > GET_MODE_BITSIZE (GET_MODE (x)))
+ {
+#ifndef WORD_REGISTER_OPERATIONS
+ /* If this machine does not do all register operations on the entire
+ register and MODE is wider than the mode of X, we can say nothing
+ at all about the high-order bits. */
+ return 1;
+#else
+ /* Likewise on machines that do, if the mode of the object is smaller
+ than a word and loads of that size don't sign extend, we can say
+ nothing about the high order bits. */
+ if (GET_MODE_BITSIZE (GET_MODE (x)) < BITS_PER_WORD
+#ifdef LOAD_EXTEND_OP
+ && LOAD_EXTEND_OP (GET_MODE (x)) != SIGN_EXTEND
+#endif
+ )
+ return 1;
+#endif
+ }
+
+ switch (code)
+ {
+ case REG:
+
+#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
+ /* If pointers extend signed and this is a pointer in Pmode, say that
+ all the bits above ptr_mode are known to be sign bit copies. */
+ if (! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode && mode == Pmode
+ && REG_POINTER (x))
+ return GET_MODE_BITSIZE (Pmode) - GET_MODE_BITSIZE (ptr_mode) + 1;
+#endif
+
+ {
+ unsigned int copies_for_hook = 1, copies = 1;
+ rtx new = rtl_hooks.reg_num_sign_bit_copies (x, mode, known_x,
+ known_mode, known_ret,
+ &copies_for_hook);
+
+ if (new)
+ copies = cached_num_sign_bit_copies (new, mode, known_x,
+ known_mode, known_ret);
+
+ if (copies > 1 || copies_for_hook > 1)
+ return MAX (copies, copies_for_hook);
+
+ /* Else, use nonzero_bits to guess num_sign_bit_copies (see below). */
+ }
+ break;
+
+ case MEM:
+#ifdef LOAD_EXTEND_OP
+ /* Some RISC machines sign-extend all loads of smaller than a word. */
+ if (LOAD_EXTEND_OP (GET_MODE (x)) == SIGN_EXTEND)
+ return MAX (1, ((int) bitwidth
+ - (int) GET_MODE_BITSIZE (GET_MODE (x)) + 1));
+#endif
+ break;
+
+ case CONST_INT:
+ /* If the constant is negative, take its 1's complement and remask.
+ Then see how many zero bits we have. */
+ nonzero = INTVAL (x) & GET_MODE_MASK (mode);
+ if (bitwidth <= HOST_BITS_PER_WIDE_INT
+ && (nonzero & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)
+ nonzero = (~nonzero) & GET_MODE_MASK (mode);
+
+ return (nonzero == 0 ? bitwidth : bitwidth - floor_log2 (nonzero) - 1);
+
+ case SUBREG:
+ /* If this is a SUBREG for a promoted object that is sign-extended
+ and we are looking at it in a wider mode, we know that at least the
+ high-order bits are known to be sign bit copies. */
+
+ if (SUBREG_PROMOTED_VAR_P (x) && ! SUBREG_PROMOTED_UNSIGNED_P (x))
+ {
+ num0 = cached_num_sign_bit_copies (SUBREG_REG (x), mode,
+ known_x, known_mode, known_ret);
+ return MAX ((int) bitwidth
+ - (int) GET_MODE_BITSIZE (GET_MODE (x)) + 1,
+ num0);
+ }
+
+ /* For a smaller object, just ignore the high bits. */
+ if (bitwidth <= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))))
+ {
+ num0 = cached_num_sign_bit_copies (SUBREG_REG (x), VOIDmode,
+ known_x, known_mode, known_ret);
+ return MAX (1, (num0
+ - (int) (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
+ - bitwidth)));
+ }
+
+#ifdef WORD_REGISTER_OPERATIONS
+#ifdef LOAD_EXTEND_OP
+ /* For paradoxical SUBREGs on machines where all register operations
+ affect the entire register, just look inside. Note that we are
+ passing MODE to the recursive call, so the number of sign bit copies
+ will remain relative to that mode, not the inner mode. */
+
+ /* This works only if loads sign extend. Otherwise, if we get a
+ reload for the inner part, it may be loaded from the stack, and
+ 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))))
+ && 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,
+ known_x, known_mode, known_ret);
+#endif
+#endif
+ break;
+
+ case SIGN_EXTRACT:
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ return MAX (1, (int) bitwidth - INTVAL (XEXP (x, 1)));
+ break;
+
+ case SIGN_EXTEND:
+ return (bitwidth - GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
+ + cached_num_sign_bit_copies (XEXP (x, 0), VOIDmode,
+ known_x, known_mode, known_ret));
+
+ case TRUNCATE:
+ /* For a smaller object, just ignore the high bits. */
+ num0 = cached_num_sign_bit_copies (XEXP (x, 0), VOIDmode,
+ known_x, known_mode, known_ret);
+ return MAX (1, (num0 - (int) (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
+ - bitwidth)));
+
+ case NOT:
+ return cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+
+ case ROTATE: case ROTATERT:
+ /* If we are rotating left by a number of bits less than the number
+ of sign bit copies, we can just subtract that amount from the
+ number. */
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) >= 0
+ && INTVAL (XEXP (x, 1)) < (int) bitwidth)
+ {
+ num0 = cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ return MAX (1, num0 - (code == ROTATE ? INTVAL (XEXP (x, 1))
+ : (int) bitwidth - INTVAL (XEXP (x, 1))));
+ }
+ break;
+
+ case NEG:
+ /* In general, this subtracts one sign bit copy. But if the value
+ is known to be positive, the number of sign bit copies is the
+ same as that of the input. Finally, if the input has just one bit
+ that might be nonzero, all the bits are copies of the sign bit. */
+ num0 = cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ if (bitwidth > HOST_BITS_PER_WIDE_INT)
+ return num0 > 1 ? num0 - 1 : 1;
+
+ nonzero = nonzero_bits (XEXP (x, 0), mode);
+ if (nonzero == 1)
+ return bitwidth;
+
+ if (num0 > 1
+ && (((HOST_WIDE_INT) 1 << (bitwidth - 1)) & nonzero))
+ num0--;
+
+ return num0;
+
+ case IOR: case AND: case XOR:
+ case SMIN: case SMAX: case UMIN: case UMAX:
+ /* Logical operations will preserve the number of sign-bit copies.
+ MIN and MAX operations always return one of the operands. */
+ num0 = cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ num1 = cached_num_sign_bit_copies (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+ return MIN (num0, num1);
+
+ case PLUS: case MINUS:
+ /* For addition and subtraction, we can have a 1-bit carry. However,
+ if we are subtracting 1 from a positive number, there will not
+ be such a carry. Furthermore, if the positive number is known to
+ be 0 or 1, we know the result is either -1 or 0. */
+
+ if (code == PLUS && XEXP (x, 1) == constm1_rtx
+ && bitwidth <= HOST_BITS_PER_WIDE_INT)
+ {
+ nonzero = nonzero_bits (XEXP (x, 0), mode);
+ if ((((HOST_WIDE_INT) 1 << (bitwidth - 1)) & nonzero) == 0)
+ return (nonzero == 1 || nonzero == 0 ? bitwidth
+ : bitwidth - floor_log2 (nonzero) - 1);
+ }
+
+ num0 = cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ num1 = cached_num_sign_bit_copies (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+ result = MAX (1, MIN (num0, num1) - 1);
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+ /* If pointers extend signed and this is an addition or subtraction
+ to a pointer in Pmode, all the bits above ptr_mode are known to be
+ sign bit copies. */
+ if (! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
+ && (code == PLUS || code == MINUS)
+ && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
+ result = MAX ((int) (GET_MODE_BITSIZE (Pmode)
+ - GET_MODE_BITSIZE (ptr_mode) + 1),
+ result);
+#endif
+ return result;
+
+ case MULT:
+ /* The number of bits of the product is the sum of the number of
+ bits of both terms. However, unless one of the terms if known
+ to be positive, we must allow for an additional bit since negating
+ a negative number can remove one sign bit copy. */
+
+ num0 = cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ num1 = cached_num_sign_bit_copies (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+
+ result = bitwidth - (bitwidth - num0) - (bitwidth - num1);
+ if (result > 0
+ && (bitwidth > HOST_BITS_PER_WIDE_INT
+ || (((nonzero_bits (XEXP (x, 0), mode)
+ & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)
+ && ((nonzero_bits (XEXP (x, 1), mode)
+ & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0))))
+ result--;
+
+ return MAX (1, result);
+
+ case UDIV:
+ /* The result must be <= the first operand. If the first operand
+ has the high bit set, we know nothing about the number of sign
+ bit copies. */
+ if (bitwidth > HOST_BITS_PER_WIDE_INT)
+ return 1;
+ else if ((nonzero_bits (XEXP (x, 0), mode)
+ & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)
+ return 1;
+ else
+ return cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+
+ case UMOD:
+ /* The result must be <= the second operand. */
+ return cached_num_sign_bit_copies (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+
+ case DIV:
+ /* Similar to unsigned division, except that we have to worry about
+ the case where the divisor is negative, in which case we have
+ to add 1. */
+ result = cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ if (result > 1
+ && (bitwidth > HOST_BITS_PER_WIDE_INT
+ || (nonzero_bits (XEXP (x, 1), mode)
+ & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0))
+ result--;
+
+ return result;
+
+ case MOD:
+ result = cached_num_sign_bit_copies (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+ if (result > 1
+ && (bitwidth > HOST_BITS_PER_WIDE_INT
+ || (nonzero_bits (XEXP (x, 1), mode)
+ & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0))
+ result--;
+
+ return result;
+
+ case ASHIFTRT:
+ /* Shifts by a constant add to the number of bits equal to the
+ sign bit. */
+ num0 = cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) > 0)
+ num0 = MIN ((int) bitwidth, num0 + INTVAL (XEXP (x, 1)));
+
+ return num0;
+
+ case ASHIFT:
+ /* Left shifts destroy copies. */
+ if (GET_CODE (XEXP (x, 1)) != CONST_INT
+ || INTVAL (XEXP (x, 1)) < 0
+ || INTVAL (XEXP (x, 1)) >= (int) bitwidth)
+ return 1;
+
+ num0 = cached_num_sign_bit_copies (XEXP (x, 0), mode,
+ known_x, known_mode, known_ret);
+ return MAX (1, num0 - INTVAL (XEXP (x, 1)));
+
+ case IF_THEN_ELSE:
+ num0 = cached_num_sign_bit_copies (XEXP (x, 1), mode,
+ known_x, known_mode, known_ret);
+ num1 = cached_num_sign_bit_copies (XEXP (x, 2), mode,
+ known_x, known_mode, known_ret);
+ return MIN (num0, num1);
+
+ case EQ: case NE: case GE: case GT: case LE: case LT:
+ case UNEQ: case LTGT: case UNGE: case UNGT: case UNLE: case UNLT:
+ case GEU: case GTU: case LEU: case LTU:
+ case UNORDERED: case ORDERED:
+ /* If the constant is negative, take its 1's complement and remask.
+ Then see how many zero bits we have. */
+ nonzero = STORE_FLAG_VALUE;
+ if (bitwidth <= HOST_BITS_PER_WIDE_INT
+ && (nonzero & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)
+ nonzero = (~nonzero) & GET_MODE_MASK (mode);
+
+ return (nonzero == 0 ? bitwidth : bitwidth - floor_log2 (nonzero) - 1);
+
+ default:
+ break;
+ }
+
+ /* If we haven't been able to figure it out by one of the above rules,
+ see if some of the high-order bits are known to be zero. If so,
+ count those bits and return one less than that amount. If we can't
+ safely compute the mask for this mode, always return BITWIDTH. */
+
+ bitwidth = GET_MODE_BITSIZE (mode);
+ if (bitwidth > HOST_BITS_PER_WIDE_INT)
+ return 1;
+
+ nonzero = nonzero_bits (x, mode);
+ return nonzero & ((HOST_WIDE_INT) 1 << (bitwidth - 1))
+ ? 1 : bitwidth - floor_log2 (nonzero) - 1;
+}
+
+/* Calculate the rtx_cost of a single instruction. A return value of
+ zero indicates an instruction pattern without a known cost. */
+
+int
+insn_rtx_cost (rtx pat)
+{
+ int i, cost;
+ rtx set;
+
+ /* Extract the single set rtx from the instruction pattern.
+ We can't use single_set since we only have the pattern. */
+ if (GET_CODE (pat) == SET)
+ set = pat;
+ else if (GET_CODE (pat) == PARALLEL)
+ {
+ set = NULL_RTX;
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx x = XVECEXP (pat, 0, i);
+ if (GET_CODE (x) == SET)
+ {
+ if (set)
+ return 0;
+ set = x;
+ }
+ }
+ if (!set)
+ return 0;
+ }
+ else
+ return 0;
+
+ cost = rtx_cost (SET_SRC (set), SET);
+ return cost > 0 ? cost : COSTS_N_INSNS (1);
+}