Index: gcc/gcc/rtlanal.c |
diff --git a/gcc/gcc/rtlanal.c b/gcc/gcc/rtlanal.c |
index e6cec483b82c8aae05d1a98b3af98407b3c1f385..0e3b77bc0c9f1fbf7df79ddc86ffcb9d139ceabb 100644 |
--- a/gcc/gcc/rtlanal.c |
+++ b/gcc/gcc/rtlanal.c |
@@ -39,18 +39,6 @@ along with GCC; see the file COPYING3. If not see |
#include "df.h" |
#include "tree.h" |
-/* Information about a subreg of a hard register. */ |
-struct subreg_info |
-{ |
- /* Offset of first hard register involved in the subreg. */ |
- int offset; |
- /* Number of hard registers involved in the subreg. */ |
- int nregs; |
- /* Whether this subreg can be represented as a hard reg with the new |
- mode. */ |
- bool representable_p; |
-}; |
- |
/* Forward declarations */ |
static void set_of_1 (rtx, const_rtx, void *); |
static bool covers_regno_p (const_rtx, unsigned int); |
@@ -58,9 +46,6 @@ static bool covers_regno_no_parallel_p (const_rtx, unsigned int); |
static int rtx_referenced_p_1 (rtx *, void *); |
static int computed_jump_p_1 (const_rtx); |
static void parms_set (rtx, const_rtx, void *); |
-static void subreg_get_info (unsigned int, enum machine_mode, |
- unsigned int, enum machine_mode, |
- struct subreg_info *); |
static unsigned HOST_WIDE_INT cached_nonzero_bits (const_rtx, enum machine_mode, |
const_rtx, enum machine_mode, |
@@ -308,7 +293,7 @@ rtx_addr_can_trap_p_1 (const_rtx x, HOST_WIDE_INT offset, HOST_WIDE_INT size, |
decl = SYMBOL_REF_DECL (x); |
/* Else check that the access is in bounds. TODO: restructure |
- expr_size/lhd_expr_size/int_expr_size and just use the latter. */ |
+ expr_size/tree_expr_size/int_expr_size and just use the latter. */ |
if (!decl) |
decl_size = -1; |
else if (DECL_P (decl) && DECL_SIZE_UNIT (decl)) |
@@ -356,7 +341,7 @@ rtx_addr_can_trap_p_1 (const_rtx x, HOST_WIDE_INT offset, HOST_WIDE_INT size, |
/* - or it is an address that can't trap plus a constant integer, |
with the proper remainder modulo the mode size if we are |
considering unaligned memory references. */ |
- if (GET_CODE (XEXP (x, 1)) == CONST_INT |
+ if (CONST_INT_P (XEXP (x, 1)) |
&& !rtx_addr_can_trap_p_1 (XEXP (x, 0), offset + INTVAL (XEXP (x, 1)), |
size, mode, unaligned_mems)) |
return 0; |
@@ -423,7 +408,7 @@ nonzero_address_p (const_rtx x) |
return nonzero_address_p (XEXP (x, 0)); |
case PLUS: |
- if (GET_CODE (XEXP (x, 1)) == CONST_INT) |
+ if (CONST_INT_P (XEXP (x, 1))) |
return nonzero_address_p (XEXP (x, 0)); |
/* Handle PIC references. */ |
else if (XEXP (x, 0) == pic_offset_table_rtx |
@@ -435,7 +420,7 @@ nonzero_address_p (const_rtx x) |
/* Similar to the above; allow positive offsets. Further, since |
auto-inc is only allowed in memories, the register must be a |
pointer. */ |
- if (GET_CODE (XEXP (x, 1)) == CONST_INT |
+ if (CONST_INT_P (XEXP (x, 1)) |
&& INTVAL (XEXP (x, 1)) > 0) |
return true; |
return nonzero_address_p (XEXP (x, 0)); |
@@ -510,10 +495,10 @@ get_integer_term (const_rtx x) |
x = XEXP (x, 0); |
if (GET_CODE (x) == MINUS |
- && GET_CODE (XEXP (x, 1)) == CONST_INT) |
+ && CONST_INT_P (XEXP (x, 1))) |
return - INTVAL (XEXP (x, 1)); |
if (GET_CODE (x) == PLUS |
- && GET_CODE (XEXP (x, 1)) == CONST_INT) |
+ && CONST_INT_P (XEXP (x, 1))) |
return INTVAL (XEXP (x, 1)); |
return 0; |
} |
@@ -529,10 +514,10 @@ get_related_value (const_rtx x) |
return 0; |
x = XEXP (x, 0); |
if (GET_CODE (x) == PLUS |
- && GET_CODE (XEXP (x, 1)) == CONST_INT) |
+ && CONST_INT_P (XEXP (x, 1))) |
return XEXP (x, 0); |
else if (GET_CODE (x) == MINUS |
- && GET_CODE (XEXP (x, 1)) == CONST_INT) |
+ && CONST_INT_P (XEXP (x, 1))) |
return XEXP (x, 0); |
return 0; |
} |
@@ -581,7 +566,7 @@ split_const (rtx x, rtx *base_out, rtx *offset_out) |
if (GET_CODE (x) == CONST) |
{ |
x = XEXP (x, 0); |
- if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT) |
+ if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))) |
{ |
*base_out = XEXP (x, 0); |
*offset_out = XEXP (x, 1); |
@@ -626,7 +611,7 @@ count_occurrences (const_rtx x, const_rtx find, int count_dest) |
if (XEXP (x, 1)) |
count += count_occurrences (XEXP (x, 1), find, count_dest); |
return count; |
- |
+ |
case MEM: |
if (MEM_P (find) && rtx_equal_p (x, find)) |
return 1; |
@@ -756,7 +741,7 @@ reg_used_between_p (const_rtx reg, const_rtx from_insn, const_rtx to_insn) |
return 0; |
for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn)) |
- if (INSN_P (insn) |
+ if (NONDEBUG_INSN_P (insn) |
&& (reg_overlap_mentioned_p (reg, PATTERN (insn)) |
|| (CALL_P (insn) && find_reg_fusage (insn, USE, reg)))) |
return 1; |
@@ -1880,10 +1865,11 @@ find_regno_fusage (const_rtx insn, enum rtx_code code, unsigned int regno) |
} |
-/* Add register note with kind KIND and datum DATUM to INSN. */ |
+/* Allocate a register note with kind KIND and datum DATUM. LIST is |
+ stored as the pointer to the next register note. */ |
-void |
-add_reg_note (rtx insn, enum reg_note kind, rtx datum) |
+rtx |
+alloc_reg_note (enum reg_note kind, rtx datum, rtx list) |
{ |
rtx note; |
@@ -1896,16 +1882,24 @@ add_reg_note (rtx insn, enum reg_note kind, rtx datum) |
/* These types of register notes use an INSN_LIST rather than an |
EXPR_LIST, so that copying is done right and dumps look |
better. */ |
- note = alloc_INSN_LIST (datum, REG_NOTES (insn)); |
+ note = alloc_INSN_LIST (datum, list); |
PUT_REG_NOTE_KIND (note, kind); |
break; |
default: |
- note = alloc_EXPR_LIST (kind, datum, REG_NOTES (insn)); |
+ note = alloc_EXPR_LIST (kind, datum, list); |
break; |
} |
- REG_NOTES (insn) = note; |
+ return note; |
+} |
+ |
+/* Add register note with kind KIND and datum DATUM to INSN. */ |
+ |
+void |
+add_reg_note (rtx insn, enum reg_note kind, rtx datum) |
+{ |
+ REG_NOTES (insn) = alloc_reg_note (kind, datum, REG_NOTES (insn)); |
} |
/* Remove register note NOTE from the REG_NOTES of INSN. */ |
@@ -2154,6 +2148,7 @@ side_effects_p (const_rtx x) |
case SCRATCH: |
case ADDR_VEC: |
case ADDR_DIFF_VEC: |
+ case VAR_LOCATION: |
return 0; |
case CLOBBER: |
@@ -2257,6 +2252,11 @@ may_trap_p_1 (const_rtx x, unsigned flags) |
/* Memory ref can trap unless it's a static var or a stack slot. */ |
case MEM: |
+ /* Recognize specific pattern of stack checking probes. */ |
+ if (flag_stack_check |
+ && MEM_VOLATILE_P (x) |
+ && XEXP (x, 0) == stack_pointer_rtx) |
+ return 1; |
if (/* MEM_NOTRAP_P only relates to the actual position of the memory |
reference; moving it out of context such as when moving code |
when optimizing, might cause its address to become invalid. */ |
@@ -2501,7 +2501,7 @@ replace_rtx (rtx x, rtx from, rtx to) |
{ |
rtx new_rtx = replace_rtx (SUBREG_REG (x), from, to); |
- if (GET_CODE (new_rtx) == CONST_INT) |
+ if (CONST_INT_P (new_rtx)) |
{ |
x = simplify_subreg (GET_MODE (x), new_rtx, |
GET_MODE (SUBREG_REG (x)), |
@@ -2517,7 +2517,7 @@ replace_rtx (rtx x, rtx from, rtx to) |
{ |
rtx new_rtx = replace_rtx (XEXP (x, 0), from, to); |
- if (GET_CODE (new_rtx) == CONST_INT) |
+ if (CONST_INT_P (new_rtx)) |
{ |
x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x), |
new_rtx, GET_MODE (XEXP (x, 0))); |
@@ -2647,9 +2647,7 @@ tablejump_p (const_rtx insn, rtx *labelp, rtx *tablep) |
if (JUMP_P (insn) |
&& (label = JUMP_LABEL (insn)) != NULL_RTX |
&& (table = next_active_insn (label)) != NULL_RTX |
- && JUMP_P (table) |
- && (GET_CODE (PATTERN (table)) == ADDR_VEC |
- || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC)) |
+ && JUMP_TABLE_DATA_P (table)) |
{ |
if (labelp) |
*labelp = label; |
@@ -2780,11 +2778,11 @@ for_each_rtx_1 (rtx exp, int n, rtx_function f, void *data) |
else if (result != 0) |
/* Stop the traversal. */ |
return result; |
- |
+ |
if (*x == NULL_RTX) |
/* There are no sub-expressions. */ |
continue; |
- |
+ |
i = non_rtx_starting_operands[GET_CODE (*x)]; |
if (i >= 0) |
{ |
@@ -2809,11 +2807,11 @@ for_each_rtx_1 (rtx exp, int n, rtx_function f, void *data) |
else if (result != 0) |
/* Stop the traversal. */ |
return result; |
- |
+ |
if (*x == NULL_RTX) |
/* There are no sub-expressions. */ |
continue; |
- |
+ |
i = non_rtx_starting_operands[GET_CODE (*x)]; |
if (i >= 0) |
{ |
@@ -2913,7 +2911,7 @@ int |
commutative_operand_precedence (rtx op) |
{ |
enum rtx_code code = GET_CODE (op); |
- |
+ |
/* Constants always come the second operand. Prefer "nice" constants. */ |
if (code == CONST_INT) |
return -8; |
@@ -2960,7 +2958,7 @@ commutative_operand_precedence (rtx op) |
operand. In particular, (plus (minus (reg) (reg)) (neg (reg))) |
is canonical, although it will usually be further simplified. */ |
return 2; |
- |
+ |
case RTX_UNARY: |
/* Then prefer NEG and NOT. */ |
if (code == NEG || code == NOT) |
@@ -3090,7 +3088,7 @@ subreg_lsb (const_rtx x) |
offset - The byte offset. |
ymode - The mode of a top level SUBREG (or what may become one). |
info - Pointer to structure to fill in. */ |
-static void |
+void |
subreg_get_info (unsigned int xregno, enum machine_mode xmode, |
unsigned int offset, enum machine_mode ymode, |
struct subreg_info *info) |
@@ -3129,10 +3127,10 @@ subreg_get_info (unsigned int xregno, enum machine_mode xmode, |
picking a different register class, or doing it in memory if |
necessary.) An example of a value with holes is XCmode on 32-bit |
x86 with -m128bit-long-double; it's represented in 6 32-bit registers, |
- 3 for each part, but in memory it's two 128-bit parts. |
+ 3 for each part, but in memory it's two 128-bit parts. |
Padding is assumed to be at the end (not necessarily the 'high part') |
of each unit. */ |
- if ((offset / GET_MODE_SIZE (xmode_unit) + 1 |
+ if ((offset / GET_MODE_SIZE (xmode_unit) + 1 |
< GET_MODE_NUNITS (xmode)) |
&& (offset / GET_MODE_SIZE (xmode_unit) |
!= ((offset + GET_MODE_SIZE (ymode) - 1) |
@@ -3144,7 +3142,7 @@ subreg_get_info (unsigned int xregno, enum machine_mode xmode, |
} |
else |
nregs_xmode = hard_regno_nregs[xregno][xmode]; |
- |
+ |
nregs_ymode = hard_regno_nregs[xregno][ymode]; |
/* Paradoxical subregs are otherwise valid. */ |
@@ -3530,7 +3528,7 @@ label_is_jump_target_p (const_rtx label, const_rtx jump_insn) |
/* Return an estimate of the cost of computing rtx X. |
One use is in cse, to decide which expression to keep in the hash table. |
Another is in rtl generation, to pick the cheapest way to multiply. |
- Other uses like the latter are expected in the future. |
+ Other uses like the latter are expected in the future. |
SPEED parameter specify whether costs optimized for speed or size should |
be returned. */ |
@@ -3604,19 +3602,19 @@ rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED, bool speed) |
} |
/* Return cost of address expression X. |
- Expect that X is properly formed address reference. |
+ Expect that X is properly formed address reference. |
SPEED parameter specify whether costs optimized for speed or size should |
be returned. */ |
int |
-address_cost (rtx x, enum machine_mode mode, bool speed) |
+address_cost (rtx x, enum machine_mode mode, addr_space_t as, bool speed) |
{ |
/* 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. */ |
- if (!memory_address_p (mode, x)) |
+ if (!memory_address_addr_space_p (mode, x, as)) |
return 1000; |
return targetm.address_cost (x, speed); |
@@ -3755,7 +3753,11 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
#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 |
+ /* As we do not know which address space the pointer is refering to, |
+ we can do this only if the target does not support different pointer |
+ or address modes depending on the address space. */ |
+ if (target_default_pointer_address_modes_p () |
+ && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode |
&& REG_POINTER (x)) |
nonzero &= GET_MODE_MASK (ptr_mode); |
#endif |
@@ -3827,8 +3829,8 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
/* 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. */ |
- /* Mind that MODE is the mode the caller wants to look at this |
- operation in, and not the actual operation mode. We can wind |
+ /* Mind that MODE is the mode the caller wants to look at this |
+ operation in, and not the actual operation mode. We can wind |
up with (subreg:DI (gt:V4HI x y)), and we don't have anything |
that describes the results of a vector compare. */ |
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT |
@@ -3992,7 +3994,11 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
/* 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 |
+ /* As we do not know which address space the pointer is refering to, |
+ we can do this only if the target does not support different pointer |
+ or address modes depending on the address space. */ |
+ if (target_default_pointer_address_modes_p () |
+ && 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); |
@@ -4001,7 +4007,7 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
break; |
case ZERO_EXTRACT: |
- if (GET_CODE (XEXP (x, 1)) == CONST_INT |
+ if (CONST_INT_P (XEXP (x, 1)) |
&& INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT) |
nonzero &= ((HOST_WIDE_INT) 1 << INTVAL (XEXP (x, 1))) - 1; |
break; |
@@ -4059,7 +4065,7 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
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 |
+ if (CONST_INT_P (XEXP (x, 1)) |
&& INTVAL (XEXP (x, 1)) >= 0 |
&& INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT |
&& INTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (GET_MODE (x))) |
@@ -4266,8 +4272,12 @@ num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
#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)) |
+ /* As we do not know which address space the pointer is refering to, |
+ we can do this only if the target does not support different pointer |
+ or address modes depending on the address space. */ |
+ if (target_default_pointer_address_modes_p () |
+ && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode |
+ && mode == Pmode && REG_POINTER (x)) |
return GET_MODE_BITSIZE (Pmode) - GET_MODE_BITSIZE (ptr_mode) + 1; |
#endif |
@@ -4354,7 +4364,7 @@ num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
break; |
case SIGN_EXTRACT: |
- if (GET_CODE (XEXP (x, 1)) == CONST_INT) |
+ if (CONST_INT_P (XEXP (x, 1))) |
return MAX (1, (int) bitwidth - INTVAL (XEXP (x, 1))); |
break; |
@@ -4378,7 +4388,7 @@ num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
/* 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 |
+ if (CONST_INT_P (XEXP (x, 1)) |
&& INTVAL (XEXP (x, 1)) >= 0 |
&& INTVAL (XEXP (x, 1)) < (int) bitwidth) |
{ |
@@ -4424,7 +4434,7 @@ num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
if (code == AND |
&& num1 > 1 |
&& bitwidth <= HOST_BITS_PER_WIDE_INT |
- && GET_CODE (XEXP (x, 1)) == CONST_INT |
+ && CONST_INT_P (XEXP (x, 1)) |
&& !(INTVAL (XEXP (x, 1)) & ((HOST_WIDE_INT) 1 << (bitwidth - 1)))) |
return num1; |
@@ -4432,7 +4442,7 @@ num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
if (code == IOR |
&& num1 > 1 |
&& bitwidth <= HOST_BITS_PER_WIDE_INT |
- && GET_CODE (XEXP (x, 1)) == CONST_INT |
+ && CONST_INT_P (XEXP (x, 1)) |
&& (INTVAL (XEXP (x, 1)) & ((HOST_WIDE_INT) 1 << (bitwidth - 1)))) |
return num1; |
@@ -4463,7 +4473,11 @@ num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
/* 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 |
+ /* As we do not know which address space the pointer is refering to, |
+ we can do this only if the target does not support different pointer |
+ or address modes depending on the address space. */ |
+ if (target_default_pointer_address_modes_p () |
+ && ! 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) |
@@ -4550,7 +4564,7 @@ num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
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 |
+ if (CONST_INT_P (XEXP (x, 1)) |
&& INTVAL (XEXP (x, 1)) > 0 |
&& INTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (GET_MODE (x))) |
num0 = MIN ((int) bitwidth, num0 + INTVAL (XEXP (x, 1))); |
@@ -4559,7 +4573,7 @@ num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x, |
case ASHIFT: |
/* Left shifts destroy copies. */ |
- if (GET_CODE (XEXP (x, 1)) != CONST_INT |
+ if (!CONST_INT_P (XEXP (x, 1)) |
|| INTVAL (XEXP (x, 1)) < 0 |
|| INTVAL (XEXP (x, 1)) >= (int) bitwidth |
|| INTVAL (XEXP (x, 1)) >= GET_MODE_BITSIZE (GET_MODE (x))) |
@@ -4664,7 +4678,7 @@ insn_rtx_cost (rtx pat, bool speed) |
If WANT_REG is nonzero, we wish the condition to be relative to that |
register, if possible. Therefore, do not canonicalize the condition |
- further. If ALLOW_CC_MODE is nonzero, allow the condition returned |
+ further. If ALLOW_CC_MODE is nonzero, allow the condition returned |
to be a compare to a CC mode register. |
If VALID_AT_INSN_P, the condition must be valid at both *EARLIEST |
@@ -4741,7 +4755,11 @@ canonicalize_condition (rtx insn, rtx cond, int reverse, rtx *earliest, |
stop if it isn't a single set or if it has a REG_INC note because |
we don't want to bother dealing with it. */ |
- if ((prev = prev_nonnote_insn (prev)) == 0 |
+ do |
+ prev = prev_nonnote_insn (prev); |
+ while (prev && DEBUG_INSN_P (prev)); |
+ |
+ if (prev == 0 |
|| !NONJUMP_INSN_P (prev) |
|| FIND_REG_INC_NOTE (prev, NULL_RTX) |
/* In cfglayout mode, there do not have to be labels at the |
@@ -4871,7 +4889,7 @@ canonicalize_condition (rtx insn, rtx cond, int reverse, rtx *earliest, |
overflow. */ |
if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_CC |
- && GET_CODE (op1) == CONST_INT |
+ && CONST_INT_P (op1) |
&& GET_MODE (op0) != VOIDmode |
&& GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT) |
{ |
@@ -5048,4 +5066,20 @@ constant_pool_constant_p (rtx x) |
x = avoid_constant_pool_reference (x); |
return GET_CODE (x) == CONST_DOUBLE; |
} |
+ |
+/* If M is a bitmask that selects a field of low-order bits within an item but |
+ not the entire word, return the length of the field. Return -1 otherwise. |
+ M is used in machine mode MODE. */ |
+int |
+low_bitmask_len (enum machine_mode mode, unsigned HOST_WIDE_INT m) |
+{ |
+ if (mode != VOIDmode) |
+ { |
+ if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT) |
+ return -1; |
+ m &= GET_MODE_MASK (mode); |
+ } |
+ |
+ return exact_log2 (m + 1); |
+} |