/* Medium-level subroutines: convert bit-field store and extract
and shifts, multiplies and divides to rtl instructions.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "toplev.h"
#include "rtl.h"
#include "tree.h"
#include "recog.h"
#include "langhooks.h"
-static void store_fixed_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, rtx));
-static void store_split_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, rtx));
-static rtx extract_fixed_bit_field PARAMS ((enum machine_mode, rtx,
- unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT,
- rtx, int));
-static rtx mask_rtx PARAMS ((enum machine_mode, int,
- int, int));
-static rtx lshift_value PARAMS ((enum machine_mode, rtx,
- int, int));
-static rtx extract_split_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, int));
-static void do_cmp_and_jump PARAMS ((rtx, rtx, enum rtx_code,
- enum machine_mode, rtx));
-
-/* Non-zero means divides or modulus operations are relatively cheap for
+static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, rtx);
+static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, rtx);
+static rtx extract_fixed_bit_field (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, rtx, int);
+static rtx mask_rtx (enum machine_mode, int, int, int);
+static rtx lshift_value (enum machine_mode, rtx, int, int);
+static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, int);
+static void do_cmp_and_jump (rtx, rtx, enum rtx_code, enum machine_mode, rtx);
+
+/* Nonzero means divides or modulus operations are relatively cheap for
powers of two, so don't use branches; emit the operation instead.
Usually, this will mean that the MD file will emit non-branch
sequences. */
static int mul_highpart_cost[NUM_MACHINE_MODES];
void
-init_expmed ()
+init_expmed (void)
{
rtx reg, shift_insn, shiftadd_insn, shiftsub_insn;
int dummy;
useful if X is a CONST_INT. */
rtx
-negate_rtx (mode, x)
- enum machine_mode mode;
- rtx x;
+negate_rtx (enum machine_mode mode, rtx x)
{
rtx result = simplify_unary_operation (NEG, mode, x, mode);
is false; else the mode of the specified operand. If OPNO is -1,
all the caller cares about is whether the insn is available. */
enum machine_mode
-mode_for_extraction (pattern, opno)
- enum extraction_pattern pattern;
- int opno;
+mode_for_extraction (enum extraction_pattern pattern, int opno)
{
const struct insn_data *data;
else, we use the mode of operand 3. */
rtx
-store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, total_size)
- rtx str_rtx;
- unsigned HOST_WIDE_INT bitsize;
- unsigned HOST_WIDE_INT bitnum;
- enum machine_mode fieldmode;
- rtx value;
- HOST_WIDE_INT total_size;
+store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
+ unsigned HOST_WIDE_INT bitnum, enum machine_mode fieldmode,
+ rtx value, HOST_WIDE_INT total_size)
{
unsigned int unit
= (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
structure fields. */
if (GET_MODE_CLASS (GET_MODE (value)) != MODE_INT
&& GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT)
- value = gen_lowpart (word_mode, value);
+ value = gen_lowpart ((GET_MODE (value) == VOIDmode
+ ? word_mode : int_mode_for_mode (GET_MODE (value))),
+ value);
/* Now OFFSET is nonzero only if OP0 is memory
and is therefore always measured in bytes. */
Note that protect_from_queue has already been done on OP0 and VALUE. */
static void
-store_fixed_bit_field (op0, offset, bitsize, bitpos, value)
- rtx op0;
- unsigned HOST_WIDE_INT offset, bitsize, bitpos;
- rtx value;
+store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset,
+ unsigned HOST_WIDE_INT bitsize,
+ unsigned HOST_WIDE_INT bitpos, rtx value)
{
enum machine_mode mode;
unsigned int total_bits = BITS_PER_WORD;
This does not yet handle fields wider than BITS_PER_WORD. */
static void
-store_split_bit_field (op0, bitsize, bitpos, value)
- rtx op0;
- unsigned HOST_WIDE_INT bitsize, bitpos;
- rtx value;
+store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
+ unsigned HOST_WIDE_INT bitpos, rtx value)
{
unsigned int unit;
unsigned int bitsdone = 0;
if they are equally easy. */
rtx
-extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
- target, mode, tmode, total_size)
- rtx str_rtx;
- unsigned HOST_WIDE_INT bitsize;
- unsigned HOST_WIDE_INT bitnum;
- int unsignedp;
- rtx target;
- enum machine_mode mode, tmode;
- HOST_WIDE_INT total_size;
+extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
+ unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
+ enum machine_mode mode, enum machine_mode tmode,
+ HOST_WIDE_INT total_size)
{
unsigned int unit
= (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
if (tmode == VOIDmode)
tmode = mode;
+
while (GET_CODE (op0) == SUBREG)
{
- int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));
- int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));
-
- offset += SUBREG_BYTE (op0) / UNITS_PER_WORD;
-
- inner_size = MIN (inner_size, BITS_PER_WORD);
-
- if (BYTES_BIG_ENDIAN && (outer_size < inner_size))
+ bitpos += SUBREG_BYTE (op0) * BITS_PER_UNIT;
+ if (bitpos > unit)
{
- bitpos += inner_size - outer_size;
- if (bitpos > unit)
- {
- offset += (bitpos / unit);
- bitpos %= unit;
- }
+ offset += (bitpos / unit);
+ bitpos %= unit;
}
-
op0 = SUBREG_REG (op0);
}
set_mem_expr (op0, 0);
}
- /* ??? We currently assume TARGET is at least as big as BITSIZE.
- If that's wrong, the solution is to test for it and set TARGET to 0
- if needed. */
+ /* Extraction of a full-word or multi-word value from a structure
+ in a register or aligned memory can be done with just a SUBREG.
+ A subword value in the least significant part of a register
+ can also be extracted with a SUBREG. For this, we need the
+ byte offset of the value in op0. */
+
+ byte_offset = bitpos / BITS_PER_UNIT + offset * UNITS_PER_WORD;
/* If OP0 is a register, BITPOS must count within a word.
But as we have it, it counts within whatever size OP0 now has.
&& unit > GET_MODE_BITSIZE (GET_MODE (op0)))
bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
- /* Extracting a full-word or multi-word value
- from a structure in a register or aligned memory.
- This can be done with just SUBREG.
- So too extracting a subword value in
- the least significant part of the register. */
-
- byte_offset = (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
- + (offset * UNITS_PER_WORD);
+ /* ??? We currently assume TARGET is at least as big as BITSIZE.
+ If that's wrong, the solution is to test for it and set TARGET to 0
+ if needed. */
mode1 = (VECTOR_MODE_P (tmode)
? mode
: mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0));
- if (((GET_CODE (op0) != MEM
- && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
- GET_MODE_BITSIZE (GET_MODE (op0)))
- && GET_MODE_SIZE (mode1) != 0
- && byte_offset % GET_MODE_SIZE (mode1) == 0)
- || (GET_CODE (op0) == MEM
- && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (op0))
- || (offset * BITS_PER_UNIT % bitsize == 0
- && MEM_ALIGN (op0) % bitsize == 0))))
- && ((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode)
- && bitpos % BITS_PER_WORD == 0)
- || (mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0) != BLKmode
- /* ??? The big endian test here is wrong. This is correct
- if the value is in a register, and if mode_for_size is not
- the same mode as op0. This causes us to get unnecessarily
- inefficient code from the Thumb port when -mbig-endian. */
- && (BYTES_BIG_ENDIAN
- ? bitpos + bitsize == BITS_PER_WORD
- : bitpos == 0))))
+ if (((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode)
+ && bitpos % BITS_PER_WORD == 0)
+ || (mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0) != BLKmode
+ /* ??? The big endian test here is wrong. This is correct
+ if the value is in a register, and if mode_for_size is not
+ the same mode as op0. This causes us to get unnecessarily
+ inefficient code from the Thumb port when -mbig-endian. */
+ && (BYTES_BIG_ENDIAN
+ ? bitpos + bitsize == BITS_PER_WORD
+ : bitpos == 0)))
+ && ((GET_CODE (op0) != MEM
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (GET_MODE (op0)))
+ && GET_MODE_SIZE (mode1) != 0
+ && byte_offset % GET_MODE_SIZE (mode1) == 0)
+ || (GET_CODE (op0) == MEM
+ && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (op0))
+ || (offset * BITS_PER_UNIT % bitsize == 0
+ && MEM_ALIGN (op0) % bitsize == 0)))))
{
if (mode1 != GET_MODE (op0))
{
If TARGET is not used, create a pseudo-reg of mode TMODE for the value. */
static rtx
-extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
- target, unsignedp)
- enum machine_mode tmode;
- rtx op0, target;
- unsigned HOST_WIDE_INT offset, bitsize, bitpos;
- int unsignedp;
+extract_fixed_bit_field (enum machine_mode tmode, rtx op0,
+ unsigned HOST_WIDE_INT offset,
+ unsigned HOST_WIDE_INT bitsize,
+ unsigned HOST_WIDE_INT bitpos, rtx target,
+ int unsignedp)
{
unsigned int total_bits = BITS_PER_WORD;
enum machine_mode mode;
BITSIZE+BITPOS is too small for MODE. */
static rtx
-mask_rtx (mode, bitpos, bitsize, complement)
- enum machine_mode mode;
- int bitpos, bitsize, complement;
+mask_rtx (enum machine_mode mode, int bitpos, int bitsize, int complement)
{
HOST_WIDE_INT masklow, maskhigh;
- if (bitpos < HOST_BITS_PER_WIDE_INT)
+ if (bitsize == 0)
+ masklow = 0;
+ else if (bitpos < HOST_BITS_PER_WIDE_INT)
masklow = (HOST_WIDE_INT) -1 << bitpos;
else
masklow = 0;
else
maskhigh = (HOST_WIDE_INT) -1 << (bitpos - HOST_BITS_PER_WIDE_INT);
- if (bitpos + bitsize > HOST_BITS_PER_WIDE_INT)
+ if (bitsize == 0)
+ maskhigh = 0;
+ else if (bitpos + bitsize > HOST_BITS_PER_WIDE_INT)
maskhigh &= ((unsigned HOST_WIDE_INT) -1
>> (2 * HOST_BITS_PER_WIDE_INT - bitpos - bitsize));
else
VALUE truncated to BITSIZE bits and then shifted left BITPOS bits. */
static rtx
-lshift_value (mode, value, bitpos, bitsize)
- enum machine_mode mode;
- rtx value;
- int bitpos, bitsize;
+lshift_value (enum machine_mode mode, rtx value, int bitpos, int bitsize)
{
unsigned HOST_WIDE_INT v = INTVAL (value);
HOST_WIDE_INT low, high;
UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend. */
static rtx
-extract_split_bit_field (op0, bitsize, bitpos, unsignedp)
- rtx op0;
- unsigned HOST_WIDE_INT bitsize, bitpos;
- int unsignedp;
+extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
+ unsigned HOST_WIDE_INT bitpos, int unsignedp)
{
unsigned int unit;
unsigned int bitsdone = 0;
/* Add INC into TARGET. */
void
-expand_inc (target, inc)
- rtx target, inc;
+expand_inc (rtx target, rtx inc)
{
rtx value = expand_binop (GET_MODE (target), add_optab,
target, inc,
/* Subtract DEC from TARGET. */
void
-expand_dec (target, dec)
- rtx target, dec;
+expand_dec (rtx target, rtx dec)
{
rtx value = expand_binop (GET_MODE (target), sub_optab,
target, dec,
Return the rtx for where the value is. */
rtx
-expand_shift (code, mode, shifted, amount, target, unsignedp)
- enum tree_code code;
- enum machine_mode mode;
- rtx shifted;
- tree amount;
- rtx target;
- int unsignedp;
+expand_shift (enum tree_code code, enum machine_mode mode, rtx shifted,
+ tree amount, rtx target, int unsignedp)
{
rtx op1, temp = 0;
int left = (code == LSHIFT_EXPR || code == LROTATE_EXPR);
char log[MAX_BITS_PER_WORD];
};
-static void synth_mult PARAMS ((struct algorithm *,
- unsigned HOST_WIDE_INT,
- int));
-static unsigned HOST_WIDE_INT choose_multiplier PARAMS ((unsigned HOST_WIDE_INT,
- int, int,
- unsigned HOST_WIDE_INT *,
- int *, int *));
-static unsigned HOST_WIDE_INT invert_mod2n PARAMS ((unsigned HOST_WIDE_INT,
- int));
+static void synth_mult (struct algorithm *, unsigned HOST_WIDE_INT, int);
+static unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT, int,
+ int, unsigned HOST_WIDE_INT *,
+ int *, int *);
+static unsigned HOST_WIDE_INT invert_mod2n (unsigned HOST_WIDE_INT, int);
/* Compute and return the best algorithm for multiplying by T.
The algorithm must cost less than cost_limit
If retval.cost >= COST_LIMIT, no algorithm was found and all
other field of the returned struct are undefined. */
static void
-synth_mult (alg_out, t, cost_limit)
- struct algorithm *alg_out;
- unsigned HOST_WIDE_INT t;
- int cost_limit;
+synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t,
+ int cost_limit)
{
int m;
struct algorithm *alg_in, *best_alg;
/* We'll be needing a couple extra algorithm structures now. */
- alg_in = (struct algorithm *)alloca (sizeof (struct algorithm));
- best_alg = (struct algorithm *)alloca (sizeof (struct algorithm));
+ alg_in = alloca (sizeof (struct algorithm));
+ best_alg = alloca (sizeof (struct algorithm));
/* If we have a group of zero bits at the low-order part of T, try
multiplying by the remaining bits and then doing a shift. */
you should swap the two operands if OP0 would be constant. */
rtx
-expand_mult (mode, op0, op1, target, unsignedp)
- enum machine_mode mode;
- rtx op0, op1, target;
- int unsignedp;
+expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
+ int unsignedp)
{
rtx const_op1 = op1;
insn = get_last_insn ();
set_unique_reg_note (insn,
- REG_EQUAL,
+ REG_EQUAL,
gen_rtx_MULT (nmode, tem,
- GEN_INT (val_so_far)));
+ GEN_INT (val_so_far)));
}
if (variant == negate_variant)
}
}
+ if (GET_CODE (op0) == CONST_DOUBLE)
+ {
+ rtx temp = op0;
+ op0 = op1;
+ op1 = temp;
+ }
+
+ /* Expand x*2.0 as x+x. */
+ if (GET_CODE (op1) == CONST_DOUBLE
+ && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ REAL_VALUE_TYPE d;
+ REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
+
+ if (REAL_VALUES_EQUAL (d, dconst2))
+ {
+ op0 = force_reg (GET_MODE (op0), op0);
+ return expand_binop (mode, add_optab, op0, op0,
+ target, unsignedp, OPTAB_LIB_WIDEN);
+ }
+ }
+
/* This used to use umul_optab if unsigned, but for non-widening multiply
there is no difference between signed and unsigned. */
op0 = expand_binop (mode,
/* Return the smallest n such that 2**n >= X. */
int
-ceil_log2 (x)
- unsigned HOST_WIDE_INT x;
+ceil_log2 (unsigned HOST_WIDE_INT x)
{
return floor_log2 (x - 1) + 1;
}
static
unsigned HOST_WIDE_INT
-choose_multiplier (d, n, precision, multiplier_ptr, post_shift_ptr, lgup_ptr)
- unsigned HOST_WIDE_INT d;
- int n;
- int precision;
- unsigned HOST_WIDE_INT *multiplier_ptr;
- int *post_shift_ptr;
- int *lgup_ptr;
+choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision,
+ unsigned HOST_WIDE_INT *multiplier_ptr,
+ int *post_shift_ptr, int *lgup_ptr)
{
HOST_WIDE_INT mhigh_hi, mlow_hi;
unsigned HOST_WIDE_INT mhigh_lo, mlow_lo;
abort ();
if (mhigh_hi > 1 || mlow_hi > 1)
abort ();
- /* assert that mlow < mhigh. */
+ /* Assert that mlow < mhigh. */
if (! (mlow_hi < mhigh_hi || (mlow_hi == mhigh_hi && mlow_lo < mhigh_lo)))
abort ();
/* If precision == N, then mlow, mhigh exceed 2^N
(but they do not exceed 2^(N+1)). */
- /* Reduce to lowest terms */
+ /* Reduce to lowest terms. */
for (post_shift = lgup; post_shift > 0; post_shift--)
{
unsigned HOST_WIDE_INT ml_lo = (mlow_hi << (HOST_BITS_PER_WIDE_INT - 1)) | (mlow_lo >> 1);
congruent to 1 (mod 2**N). */
static unsigned HOST_WIDE_INT
-invert_mod2n (x, n)
- unsigned HOST_WIDE_INT x;
- int n;
+invert_mod2n (unsigned HOST_WIDE_INT x, int n)
{
/* Solve x*y == 1 (mod 2^n), where x is odd. Return y. */
MODE is the mode of operation. */
rtx
-expand_mult_highpart_adjust (mode, adj_operand, op0, op1, target, unsignedp)
- enum machine_mode mode;
- rtx adj_operand, op0, op1, target;
- int unsignedp;
+expand_mult_highpart_adjust (enum machine_mode mode, rtx adj_operand, rtx op0,
+ rtx op1, rtx target, int unsignedp)
{
rtx tem;
enum rtx_code adj_code = unsignedp ? PLUS : MINUS;
MAX_COST is the total allowed cost for the expanded RTL. */
rtx
-expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
- enum machine_mode mode;
- rtx op0, target;
- unsigned HOST_WIDE_INT cnst1;
- int unsignedp;
- int max_cost;
+expand_mult_highpart (enum machine_mode mode, rtx op0,
+ unsigned HOST_WIDE_INT cnst1, rtx target,
+ int unsignedp, int max_cost)
{
enum machine_mode wider_mode = GET_MODE_WIDER_MODE (mode);
optab mul_highpart_optab;
the result is exact for inputs up to 0x1fffffff.
The input range can be reduced by using cross-sum rules.
For odd divisors >= 3, the following table gives right shift counts
- so that if an number is shifted by an integer multiple of the given
+ so that if a number is shifted by an integer multiple of the given
amount, the remainder stays the same:
2, 4, 3, 6, 10, 12, 4, 8, 18, 6, 11, 20, 18, 0, 5, 10, 12, 0, 12, 20,
14, 12, 23, 21, 8, 0, 20, 18, 0, 0, 6, 12, 0, 22, 0, 18, 20, 30, 0, 0,
#define EXACT_POWER_OF_2_OR_ZERO_P(x) (((x) & ((x) - 1)) == 0)
rtx
-expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
- int rem_flag;
- enum tree_code code;
- enum machine_mode mode;
- rtx op0, op1, target;
- int unsignedp;
+expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
+ rtx op0, rtx op1, rtx target, int unsignedp)
{
enum machine_mode compute_mode;
rtx tquotient;
int size;
rtx insn, set;
optab optab1, optab2;
- int op1_is_constant, op1_is_pow2;
+ int op1_is_constant, op1_is_pow2 = 0;
int max_cost, extra_cost;
static HOST_WIDE_INT last_div_const = 0;
+ static HOST_WIDE_INT ext_op1;
op1_is_constant = GET_CODE (op1) == CONST_INT;
- op1_is_pow2 = (op1_is_constant
- && ((EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
- || (! unsignedp && EXACT_POWER_OF_2_OR_ZERO_P (-INTVAL (op1))))));
+ if (op1_is_constant)
+ {
+ ext_op1 = INTVAL (op1);
+ if (unsignedp)
+ ext_op1 &= GET_MODE_MASK (mode);
+ op1_is_pow2 = ((EXACT_POWER_OF_2_OR_ZERO_P (ext_op1)
+ || (! unsignedp && EXACT_POWER_OF_2_OR_ZERO_P (-ext_op1))));
+ }
/*
This is the structure of expand_divmod:
not straightforward to generalize this. Maybe we should make an array
of possible modes in init_expmed? Save this for GCC 2.7. */
- optab1 = (op1_is_pow2 ? (unsignedp ? lshr_optab : ashr_optab)
+ optab1 = ((op1_is_pow2 && op1 != const0_rtx)
+ ? (unsignedp ? lshr_optab : ashr_optab)
: (unsignedp ? udiv_optab : sdiv_optab));
- optab2 = (op1_is_pow2 ? optab1 : (unsignedp ? udivmod_optab : sdivmod_optab));
+ optab2 = ((op1_is_pow2 && op1 != const0_rtx)
+ ? optab1
+ : (unsignedp ? udivmod_optab : sdivmod_optab));
for (compute_mode = mode; compute_mode != VOIDmode;
compute_mode = GET_MODE_WIDER_MODE (compute_mode))
unsigned HOST_WIDE_INT mh, ml;
int pre_shift, post_shift;
int dummy;
- unsigned HOST_WIDE_INT d = INTVAL (op1);
+ unsigned HOST_WIDE_INT d = (INTVAL (op1)
+ & GET_MODE_MASK (compute_mode));
if (EXACT_POWER_OF_2_OR_ZERO_P (d))
{
&& (set = single_set (insn)) != 0
&& SET_DEST (set) == quotient)
set_unique_reg_note (insn,
- REG_EQUAL,
+ REG_EQUAL,
gen_rtx_UDIV (compute_mode, op0, op1));
}
else /* TRUNC_DIV, signed */
&& abs_d < ((unsigned HOST_WIDE_INT) 1
<< (HOST_BITS_PER_WIDE_INT - 1)))
set_unique_reg_note (insn,
- REG_EQUAL,
+ REG_EQUAL,
gen_rtx_DIV (compute_mode,
op0,
GEN_INT
&& (set = single_set (insn)) != 0
&& SET_DEST (set) == quotient)
set_unique_reg_note (insn,
- REG_EQUAL,
+ REG_EQUAL,
gen_rtx_DIV (compute_mode, op0, op1));
}
break;
build_int_2 (pre_shift, 0), NULL_RTX, unsignedp);
quotient = expand_mult (compute_mode, t1,
gen_int_mode (ml, compute_mode),
- NULL_RTX, 0);
+ NULL_RTX, 1);
insn = get_last_insn ();
set_unique_reg_note (insn,
- REG_EQUAL,
+ REG_EQUAL,
gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
compute_mode,
op0, op1));
{
/* Try to produce the remainder without producing the quotient.
If we seem to have a divmod pattern that does not require widening,
- don't try widening here. We should really have an WIDEN argument
+ don't try widening here. We should really have a WIDEN argument
to expand_twoval_binop, since what we'd really like to do here is
1) try a mod insn in compute_mode
2) try a divmod insn in compute_mode
generated by loop.c. */
tree
-make_tree (type, x)
- tree type;
- rtx x;
+make_tree (tree type, rtx x)
{
tree t;
MODE is the machine mode for the computation.
X and MULT must have mode MODE. ADD may have a different mode.
So can X (defaults to same as MODE).
- UNSIGNEDP is non-zero to do unsigned multiplication. */
+ UNSIGNEDP is nonzero to do unsigned multiplication. */
bool
-const_mult_add_overflow_p (x, mult, add, mode, unsignedp)
- rtx x, mult, add;
- enum machine_mode mode;
- int unsignedp;
+const_mult_add_overflow_p (rtx x, rtx mult, rtx add, enum machine_mode mode, int unsignedp)
{
tree type, mult_type, add_type, result;
MODE is the machine mode for the computation.
X and MULT must have mode MODE. ADD may have a different mode.
So can X (defaults to same as MODE).
- UNSIGNEDP is non-zero to do unsigned multiplication.
+ UNSIGNEDP is nonzero to do unsigned multiplication.
This may emit insns. */
rtx
-expand_mult_add (x, target, mult, add, mode, unsignedp)
- rtx x, target, mult, add;
- enum machine_mode mode;
- int unsignedp;
+expand_mult_add (rtx x, rtx target, rtx mult, rtx add, enum machine_mode mode,
+ int unsignedp)
{
tree type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
tree add_type = (GET_MODE (add) == VOIDmode
If TARGET is 0, a pseudo-register or constant is returned. */
rtx
-expand_and (mode, op0, op1, target)
- enum machine_mode mode;
- rtx op0, op1, target;
+expand_and (enum machine_mode mode, rtx op0, rtx op1, rtx target)
{
rtx tem = 0;
"raw" out of the scc insn. */
rtx
-emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
- rtx target;
- enum rtx_code code;
- rtx op0, op1;
- enum machine_mode mode;
- int unsignedp;
- int normalizep;
+emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
+ enum machine_mode mode, int unsignedp, int normalizep)
{
rtx subtarget;
enum insn_code icode;
{
if (code == EQ || code == NE)
{
+ rtx op00, op01, op0both;
+
/* Do a logical OR of the two words and compare the result. */
- rtx op0h = gen_highpart (word_mode, op0);
- rtx op0l = gen_lowpart (word_mode, op0);
- rtx op0both = expand_binop (word_mode, ior_optab, op0h, op0l,
- NULL_RTX, unsignedp, OPTAB_DIRECT);
+ op00 = simplify_gen_subreg (word_mode, op0, mode, 0);
+ op01 = simplify_gen_subreg (word_mode, op0, mode, UNITS_PER_WORD);
+ op0both = expand_binop (word_mode, ior_optab, op00, op01,
+ NULL_RTX, unsignedp, OPTAB_DIRECT);
if (op0both != 0)
return emit_store_flag (target, code, op0both, op1, word_mode,
unsignedp, normalizep);
}
else if (code == LT || code == GE)
- /* If testing the sign bit, can just test on high word. */
- return emit_store_flag (target, code, gen_highpart (word_mode, op0),
- op1, word_mode, unsignedp, normalizep);
+ {
+ rtx op0h;
+
+ /* If testing the sign bit, can just test on high word. */
+ op0h = simplify_gen_subreg (word_mode, op0, mode,
+ subreg_highpart_offset (word_mode, mode));
+ return emit_store_flag (target, code, op0h, op1, word_mode,
+ unsignedp, normalizep);
+ }
}
/* From now on, we won't change CODE, so set ICODE now. */
&& (normalizep || STORE_FLAG_VALUE == 1
|| (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
- == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))))
+ == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))))
{
subtarget = target;
if (code == EQ || code == NE)
{
/* For EQ or NE, one way to do the comparison is to apply an operation
- that converts the operand into a positive number if it is non-zero
+ that converts the operand into a positive number if it is nonzero
or zero if it was originally zero. Then, for EQ, we subtract 1 and
for NE we negate. This puts the result in the sign bit. Then we
normalize with a shift, if needed.
/* Like emit_store_flag, but always succeeds. */
rtx
-emit_store_flag_force (target, code, op0, op1, mode, unsignedp, normalizep)
- rtx target;
- enum rtx_code code;
- rtx op0, op1;
- enum machine_mode mode;
- int unsignedp;
- int normalizep;
+emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
+ enum machine_mode mode, int unsignedp, int normalizep)
{
rtx tem, label;
be handled if needed). */
static void
-do_cmp_and_jump (arg1, arg2, op, mode, label)
- rtx arg1, arg2, label;
- enum rtx_code op;
- enum machine_mode mode;
+do_cmp_and_jump (rtx arg1, rtx arg2, enum rtx_code op, enum machine_mode mode,
+ rtx label)
{
/* If this mode is an integer too wide to compare properly,
compare word by word. Rely on cse to optimize constant cases. */