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. */
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)
{
/* (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 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;