/* Optimize by combining instructions for GNU compiler.
- Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc.
This file is part of GNU CC.
combine anyway. */
#include "config.h"
+/* Must precede rtl.h for FFS. */
+#include <stdio.h>
+
#include "gvarargs.h"
#include "rtl.h"
#include "flags.h"
#include "insn-attr.h"
#include "recog.h"
#include "real.h"
-#include <stdio.h>
/* It is not safe to use ordinary gen_lowpart in combine.
Use gen_lowpart_for_combine instead. See comments there. */
&& REGNO (x) >= FIRST_PSEUDO_REGISTER
&& reg_n_sets[REGNO (x)] > 1
&& reg_basic_block[REGNO (x)] < 0
+ /* If this register is undefined at the start of the file, we can't
+ say what its contents were. */
+ && ! (basic_block_live_at_start[0][REGNO (x) / REGSET_ELT_BITS]
+ & ((REGSET_ELT_TYPE) 1 << (REGNO (x) % REGSET_ELT_BITS)))
&& GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
{
if (GET_CODE (set) == CLOBBER)
- return;
+ {
+ reg_nonzero_bits[REGNO (x)] = GET_MODE_MASK (GET_MODE (x));
+ reg_sign_bit_copies[REGNO (x)] = 0;
+ return;
+ }
/* If this is a complex assignment, see if we can convert it into a
simple assignment. */
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (set)))))
&& SUBREG_REG (SET_DEST (set)) == x))
{
+ rtx src = SET_SRC (set);
+
+#ifdef SHORT_IMMEDIATES_SIGN_EXTEND
+ /* If X is narrower than a word and SRC is a non-negative
+ constant that would appear negative in the mode of X,
+ sign-extend it for use in reg_nonzero_bits because some
+ machines (maybe most) will actually do the sign-extension
+ and this is the conservative approach.
+
+ ??? For 2.5, try to tighten up the MD files in this regard
+ instead of this kludge. */
+
+ if (GET_MODE_BITSIZE (GET_MODE (x)) < BITS_PER_WORD
+ && GET_CODE (src) == CONST_INT
+ && INTVAL (src) > 0
+ && 0 != (INTVAL (src)
+ & ((HOST_WIDE_INT) 1
+ << GET_MODE_BITSIZE (GET_MODE (x)))))
+ src = GEN_INT (INTVAL (src)
+ | ((HOST_WIDE_INT) (-1)
+ << GET_MODE_BITSIZE (GET_MODE (x))));
+#endif
+
reg_nonzero_bits[REGNO (x)]
- |= nonzero_bits (SET_SRC (set), nonzero_bits_mode);
+ |= nonzero_bits (src, nonzero_bits_mode);
num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x));
if (reg_sign_bit_copies[REGNO (x)] == 0
|| reg_sign_bit_copies[REGNO (x)] > num)
return 0;
/* If DEST is used in I3, it is being killed in this insn,
- so record that for later. */
+ so record that for later.
+ Never add REG_DEAD notes for the FRAME_POINTER_REGNUM or the
+ STACK_POINTER_REGNUM, since these are always considered to be
+ live. Similarly for ARG_POINTER_REGNUM if it is fixed. */
if (pi3dest_killed && GET_CODE (dest) == REG
- && reg_referenced_p (dest, PATTERN (i3)))
+ && reg_referenced_p (dest, PATTERN (i3))
+ && REGNO (dest) != FRAME_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ && (REGNO (dest) != ARG_POINTER_REGNUM
+ || ! fixed_regs [REGNO (dest)])
+#endif
+ && REGNO (dest) != STACK_POINTER_REGNUM)
{
if (*pi3dest_killed)
return 0;
x = temp, code = GET_CODE (temp);
/* First see if we can apply the inverse distributive law. */
- if (code == PLUS || code == MINUS || code == IOR || code == XOR)
+ if (code == PLUS || code == MINUS
+ || code == AND || code == IOR || code == XOR)
{
x = apply_distributive_law (x);
code = GET_CODE (x);
|| code == MULT || code == AND || code == IOR || code == XOR
|| code == DIV || code == UDIV
|| code == SMAX || code == SMIN || code == UMAX || code == UMIN)
- && GET_MODE_CLASS (mode) == MODE_INT)
+ && INTEGRAL_MODE_P (mode))
{
if (GET_CODE (XEXP (x, 0)) == code)
{
return temp;
}
+ /* If we want a subreg of a constant, at offset 0,
+ take the low bits. On a little-endian machine, that's
+ always valid. On a big-endian machine, it's valid
+ only if the constant's mode fits in one word. */
if (CONSTANT_P (SUBREG_REG (x)) && subreg_lowpart_p (x)
- && GET_MODE_SIZE (mode) < GET_MODE_SIZE (op0_mode))
+ && GET_MODE_SIZE (mode) < GET_MODE_SIZE (op0_mode)
+#if WORDS_BIG_ENDIAN
+ && GET_MODE_BITSIZE (op0_mode) <= BITS_PER_WORD
+#endif
+ )
return gen_lowpart_for_combine (mode, SUBREG_REG (x));
/* If we are narrowing the object, we need to see if we can simplify
/* (neg (minus X Y)) can become (minus Y X). */
if (GET_CODE (XEXP (x, 0)) == MINUS
- && (GET_MODE_CLASS (mode) != MODE_FLOAT
+ && (! FLOAT_MODE_P (mode)
/* x-y != -(y-x) with IEEE floating point. */
|| TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT))
{
/* In IEEE floating point, x-0 is not the same as x. */
if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) == MODE_INT)
+ || ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0))))
&& XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
return XEXP (x, 0);
break;
goto restart;
}
- /* If only the low-order bit of X is possible nonzero, (plus x -1)
+ /* (plus (comparison A B) C) can become (neg (rev-comp A B)) if
+ C is 1 and STORE_FLAG_VALUE is -1 or if C is -1 and STORE_FLAG_VALUE
+ is 1. This produces better code than the alternative immediately
+ below. */
+ if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
+ && reversible_comparison_p (XEXP (x, 0))
+ && ((STORE_FLAG_VALUE == -1 && XEXP (x, 1) == const1_rtx)
+ || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx)))
+ {
+ x = gen_binary (reverse_condition (GET_CODE (XEXP (x, 0))),
+ mode, XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 0), 1));
+ x = gen_unary (NEG, mode, x);
+ goto restart;
+ }
+
+ /* If only the low-order bit of X is possibly nonzero, (plus x -1)
can become (ashiftrt (ashift (xor x 1) C) C) where C is
the bitsize of the mode - 1. This allows simplification of
"a = (b & 8) == 0;" */
/* Look for MIN or MAX. */
- if (GET_MODE_CLASS (mode) == MODE_INT
+ if (! FLOAT_MODE_P (mode)
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1))
&& rtx_equal_p (XEXP (XEXP (x, 0), 1), XEXP (x, 2))
return temp;
}
}
+
+ /* If we have (if_then_else (ne A 0) C1 0) and either A is known to
+ be 0 or 1 and C1 is a single bit or A is known to be 0 or -1 and
+ C1 is the negation of a single bit, we can convert this operation
+ to a shift. We can actually do this in more general cases, but it
+ doesn't seem worth it. */
+
+ if (GET_CODE (XEXP (x, 0)) == NE && XEXP (XEXP (x, 0), 1) == const0_rtx
+ && XEXP (x, 2) == const0_rtx && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && ((1 == nonzero_bits (XEXP (XEXP (x, 0), 0), mode)
+ && (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0)
+ || ((num_sign_bit_copies (XEXP (XEXP (x, 0), 0), mode)
+ == GET_MODE_BITSIZE (mode))
+ && (i = exact_log2 (- INTVAL (XEXP (x, 1)))) >= 0)))
+ return
+ simplify_shift_const (NULL_RTX, ASHIFT, mode,
+ gen_lowpart_for_combine (mode,
+ XEXP (XEXP (x, 0), 0)),
+ i);
break;
case ZERO_EXTRACT:
means that we only care about the low bits of the result.
However, on most machines (those with neither BYTE_LOADS_ZERO_EXTEND
- nor BYTES_LOADS_SIGN_EXTEND defined), we cannot perform a
+ nor BYTE_LOADS_SIGN_EXTEND defined), we cannot perform a
narrower operation that requested since the high-order bits will
be undefined. On machine where BYTE_LOADS_*_EXTEND is defined,
however, this transformation is safe as long as M1 and M2 have
gen_binary (GET_CODE (XEXP (x, 0)), mode, new,
GEN_INT (newop1)),
INTVAL (c2) - INTVAL (c1),
- NULL_RTX, mode_width - INTVAL (c1),
+ NULL_RTX, mode_width - INTVAL (c2),
code == LSHIFTRT, 0, in_code == COMPARE);
}
/* Distributivity is not true for floating point.
It can change the value. So don't do it.
-- rms and moshier@world.std.com. */
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+ if (FLOAT_MODE_P (GET_MODE (x)))
return x;
/* The outer operation can only be one of the following: */
case XOR:
/* If VAROP is (ior (lshiftrt FOO C1) C2), try to commute the IOR and
LSHIFT so we end up with an (and (lshiftrt (ior ...) ...) ...)
- operation which may be a bitfield extraction. */
+ operation which may be a bitfield extraction. Ensure
+ that the constant we form is not wider than the mode of
+ VAROP. */
if (GET_CODE (XEXP (varop, 0)) == LSHIFTRT
&& GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT
&& INTVAL (XEXP (XEXP (varop, 0), 1)) >= 0
&& INTVAL (XEXP (XEXP (varop, 0), 1)) < HOST_BITS_PER_WIDE_INT
&& GET_CODE (XEXP (varop, 1)) == CONST_INT
+ && ((INTVAL (XEXP (XEXP (varop, 0), 1))
+ + floor_log2 (INTVAL (XEXP (varop, 1))))
+ < GET_MODE_BITSIZE (GET_MODE (varop)))
&& (INTVAL (XEXP (varop, 1))
& ~ nonzero_bits (XEXP (varop, 0), GET_MODE (varop)) == 0))
{
XEXP (varop, 1), constop))));
case NOT:
- /* (and (not FOO)) is (and (xor FOO CONST_OP)) so if FOO is an
- LSHIFTRT we can do the same as above. */
+ /* (and (not FOO)) is (and (xor FOO CONST)), so if FOO is an
+ LSHIFTRT, we can do the same as above. Ensure that the constant
+ we form is not wider than the mode of VAROP. */
if (GET_CODE (XEXP (varop, 0)) == LSHIFTRT
&& GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT
&& INTVAL (XEXP (XEXP (varop, 0), 1)) >= 0
+ && (INTVAL (XEXP (XEXP (varop, 0), 1)) + floor_log2 (constop)
+ < GET_MODE_BITSIZE (GET_MODE (varop)))
&& INTVAL (XEXP (XEXP (varop, 0), 1)) < HOST_BITS_PER_WIDE_INT)
{
temp = GEN_INT (constop << INTVAL (XEXP (XEXP (varop, 0), 1)));
+ num_sign_bit_copies (XEXP (varop, 0),
GET_MODE (XEXP (varop, 0))))
>= GET_MODE_BITSIZE (GET_MODE (varop)))
- && exact_log2 (constop + 1) >= 0)
+ && exact_log2 (constop + 1) >= 0
+ && (num_sign_bit_copies (XEXP (varop, 0),
+ GET_MODE (XEXP (varop, 0)))
+ >= exact_log2 (constop + 1)))
varop
= gen_rtx_combine (LSHIFTRT, GET_MODE (varop), XEXP (varop, 0),
GEN_INT (GET_MODE_BITSIZE (GET_MODE (varop))
return reg_last_set_nonzero_bits[REGNO (x)];
tem = get_last_value (x);
+
if (tem)
- return nonzero_bits (tem, mode);
+ {
+#ifdef SHORT_IMMEDIATES_SIGN_EXTEND
+ /* If X is narrower than MODE and TEM is a non-negative
+ constant that would appear negative in the mode of X,
+ sign-extend it for use in reg_nonzero_bits because some
+ machines (maybe most) will actually do the sign-extension
+ and this is the conservative approach.
+
+ ??? For 2.5, try to tighten up the MD files in this regard
+ instead of this kludge. */
+
+ if (GET_MODE_BITSIZE (GET_MODE (x)) < mode_width
+ && GET_CODE (tem) == CONST_INT
+ && INTVAL (tem) > 0
+ && 0 != (INTVAL (tem)
+ & ((HOST_WIDE_INT) 1
+ << GET_MODE_BITSIZE (GET_MODE (x)))))
+ tem = GEN_INT (INTVAL (tem)
+ | ((HOST_WIDE_INT) (-1)
+ << GET_MODE_BITSIZE (GET_MODE (x))));
+#endif
+ return nonzero_bits (tem, mode);
+ }
else if (nonzero_sign_valid && reg_nonzero_bits[REGNO (x)])
return reg_nonzero_bits[REGNO (x)] & nonzero;
else
return nonzero;
case CONST_INT:
+#ifdef SHORT_IMMEDIATES_SIGN_EXTEND
+ /* If X is negative in MODE, sign-extend the value. */
+ if (INTVAL (x) > 0
+ && 0 != (INTVAL (x)
+ & ((HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (GET_MODE (x)))))
+ return (INTVAL (x)
+ | ((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (GET_MODE (x))));
+#endif
+
return INTVAL (x);
#ifdef BYTE_LOADS_ZERO_EXTEND
high-order bits are known to be sign bit copies. */
if (SUBREG_PROMOTED_VAR_P (x) && ! SUBREG_PROMOTED_UNSIGNED_P (x))
- return (GET_MODE_BITSIZE (mode) - GET_MODE_BITSIZE (GET_MODE (x))
- + num_sign_bit_copies (SUBREG_REG (x), GET_MODE (x)));
+ return MAX (bitwidth - GET_MODE_BITSIZE (GET_MODE (x)) + 1,
+ num_sign_bit_copies (SUBREG_REG (x), mode));
/* For a smaller object, just ignore the high bits. */
if (bitwidth <= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))))
return 1;
nonzero = nonzero_bits (x, mode);
- return (nonzero == GET_MODE_MASK (mode)
+ return (nonzero & ((HOST_WIDE_INT) 1 << (bitwidth - 1))
? 1 : bitwidth - floor_log2 (nonzero) - 1);
}
\f
SUBST (XEXP (x, 1), const_rtx);
}
+ /* If we have an outer operation and we just made a shift, it is
+ possible that we could have simplified the shift were it not
+ for the outer operation. So try to do the simplification
+ recursively. */
+
+ if (outer_op != NIL && GET_CODE (x) == code
+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ x = simplify_shift_const (x, code, shift_mode, XEXP (x, 0),
+ INTVAL (XEXP (x, 1)));
+
/* If we were doing a LSHIFTRT in a wider mode than it was originally,
turn off all the bits that the shift would have turned off. */
if (orig_code == LSHIFTRT && result_mode != shift_mode)
&& ((INTVAL (XEXP (op0, 1)) + ! equality_comparison_p)
< HOST_BITS_PER_WIDE_INT)
&& ((const_op
- & ((HOST_WIDE_INT) 1 << INTVAL (XEXP (op0, 1))) - 1) == 0)
+ & (((HOST_WIDE_INT) 1 << INTVAL (XEXP (op0, 1))) - 1)) == 0)
&& mode_width <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (XEXP (op0, 0), mode)
& ~ (mask >> (INTVAL (XEXP (op0, 1))
switch (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))))
{
case MODE_INT:
+ case MODE_PARTIAL_INT:
+ case MODE_COMPLEX_INT:
return 1;
case MODE_CC:
x = get_last_value (XEXP (x, 0));
return (x && GET_CODE (x) == COMPARE
- && GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) == MODE_INT);
+ && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0))));
}
return 0;
all_used = 0;
}
+ /* Check for the case where the register dying partially
+ overlaps the register set by this insn. */
+ if (all_used)
+ for (i = regno; i < endregno; i++)
+ if (dead_or_set_regno_p (place, i))
+ {
+ all_used = 0;
+ break;
+ }
+
if (! all_used)
{
/* Put only REG_DEAD notes for pieces that are