Commit d7cd794f by Richard Kenner

(make_extraction): Use proper mode for INNER in all cases.

(simplify_comparison, case ZERO_EXTRACT): For bits big endian and no extzv,
use BITS_PER_WORD.

From-SVN: r11510
parent 2ae508e5
...@@ -5068,7 +5068,8 @@ make_extraction (mode, inner, pos, pos_rtx, len, ...@@ -5068,7 +5068,8 @@ make_extraction (mode, inner, pos, pos_rtx, len,
ignore the POS lowest bits, etc. */ ignore the POS lowest bits, etc. */
enum machine_mode is_mode = GET_MODE (inner); enum machine_mode is_mode = GET_MODE (inner);
enum machine_mode inner_mode; enum machine_mode inner_mode;
enum machine_mode wanted_mem_mode = byte_mode; enum machine_mode wanted_inner_mode = byte_mode;
enum machine_mode wanted_inner_reg_mode = word_mode;
enum machine_mode pos_mode = word_mode; enum machine_mode pos_mode = word_mode;
enum machine_mode extraction_mode = word_mode; enum machine_mode extraction_mode = word_mode;
enum machine_mode tmode = mode_for_size (len, MODE_INT, 1); enum machine_mode tmode = mode_for_size (len, MODE_INT, 1);
...@@ -5208,12 +5209,12 @@ make_extraction (mode, inner, pos, pos_rtx, len, ...@@ -5208,12 +5209,12 @@ make_extraction (mode, inner, pos, pos_rtx, len,
|| (pos_rtx != 0 && len != 1))) || (pos_rtx != 0 && len != 1)))
return 0; return 0;
/* Get the mode to use should INNER be a MEM, the mode for the position, /* Get the mode to use should INNER not be a MEM, the mode for the position,
and the mode for the result. */ and the mode for the result. */
#ifdef HAVE_insv #ifdef HAVE_insv
if (in_dest) if (in_dest)
{ {
wanted_mem_mode = insn_operand_mode[(int) CODE_FOR_insv][0]; wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_insv][0];
pos_mode = insn_operand_mode[(int) CODE_FOR_insv][2]; pos_mode = insn_operand_mode[(int) CODE_FOR_insv][2];
extraction_mode = insn_operand_mode[(int) CODE_FOR_insv][3]; extraction_mode = insn_operand_mode[(int) CODE_FOR_insv][3];
} }
...@@ -5222,7 +5223,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, ...@@ -5222,7 +5223,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
#ifdef HAVE_extzv #ifdef HAVE_extzv
if (! in_dest && unsignedp) if (! in_dest && unsignedp)
{ {
wanted_mem_mode = insn_operand_mode[(int) CODE_FOR_extzv][1]; wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
pos_mode = insn_operand_mode[(int) CODE_FOR_extzv][3]; pos_mode = insn_operand_mode[(int) CODE_FOR_extzv][3];
extraction_mode = insn_operand_mode[(int) CODE_FOR_extzv][0]; extraction_mode = insn_operand_mode[(int) CODE_FOR_extzv][0];
} }
...@@ -5231,7 +5232,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, ...@@ -5231,7 +5232,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
#ifdef HAVE_extv #ifdef HAVE_extv
if (! in_dest && ! unsignedp) if (! in_dest && ! unsignedp)
{ {
wanted_mem_mode = insn_operand_mode[(int) CODE_FOR_extv][1]; wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
pos_mode = insn_operand_mode[(int) CODE_FOR_extv][3]; pos_mode = insn_operand_mode[(int) CODE_FOR_extv][3];
extraction_mode = insn_operand_mode[(int) CODE_FOR_extv][0]; extraction_mode = insn_operand_mode[(int) CODE_FOR_extv][0];
} }
...@@ -5247,13 +5248,15 @@ make_extraction (mode, inner, pos, pos_rtx, len, ...@@ -5247,13 +5248,15 @@ make_extraction (mode, inner, pos, pos_rtx, len,
&& GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx))) && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx)))
pos_mode = GET_MODE (pos_rtx); pos_mode = GET_MODE (pos_rtx);
/* If this is not from memory or we have to change the mode of memory and /* If this is not from memory, the desired mode is wanted_inner_reg_mode;
cannot, the desired mode is EXTRACTION_MODE. */ if we have to change the mode of memory and cannot, the desired mode is
if (GET_CODE (inner) != MEM EXTRACTION_MODE. */
|| (inner_mode != wanted_mem_mode if (GET_CODE (inner) != MEM)
&& (mode_dependent_address_p (XEXP (inner, 0)) wanted_inner_mode = wanted_inner_reg_mode;
|| MEM_VOLATILE_P (inner)))) else if (inner_mode != wanted_inner_mode
wanted_mem_mode = extraction_mode; && (mode_dependent_address_p (XEXP (inner, 0))
|| MEM_VOLATILE_P (inner)))
wanted_inner_mode = extraction_mode;
orig_pos = pos; orig_pos = pos;
...@@ -5262,14 +5265,11 @@ make_extraction (mode, inner, pos, pos_rtx, len, ...@@ -5262,14 +5265,11 @@ make_extraction (mode, inner, pos, pos_rtx, len,
/* If position is constant, compute new position. Otherwise, /* If position is constant, compute new position. Otherwise,
build subtraction. */ build subtraction. */
if (pos_rtx == 0) if (pos_rtx == 0)
pos = (MAX (GET_MODE_BITSIZE (is_mode), pos = GET_MODE_BITSIZE (wanted_inner_mode) - len - pos;
GET_MODE_BITSIZE (wanted_mem_mode))
- len - pos);
else else
pos_rtx pos_rtx
= gen_rtx_combine (MINUS, GET_MODE (pos_rtx), = gen_rtx_combine (MINUS, GET_MODE (pos_rtx),
GEN_INT (MAX (GET_MODE_BITSIZE (is_mode), GEN_INT (GET_MODE_BITSIZE (wanted_inner_mode)
GET_MODE_BITSIZE (wanted_mem_mode))
- len), - len),
pos_rtx); pos_rtx);
} }
...@@ -5277,10 +5277,10 @@ make_extraction (mode, inner, pos, pos_rtx, len, ...@@ -5277,10 +5277,10 @@ make_extraction (mode, inner, pos, pos_rtx, len,
/* If INNER has a wider mode, make it smaller. If this is a constant /* If INNER has a wider mode, make it smaller. If this is a constant
extract, try to adjust the byte to point to the byte containing extract, try to adjust the byte to point to the byte containing
the value. */ the value. */
if (wanted_mem_mode != VOIDmode if (wanted_inner_mode != VOIDmode
&& GET_MODE_SIZE (wanted_mem_mode) < GET_MODE_SIZE (is_mode) && GET_MODE_SIZE (wanted_inner_mode) < GET_MODE_SIZE (is_mode)
&& ((GET_CODE (inner) == MEM && ((GET_CODE (inner) == MEM
&& (inner_mode == wanted_mem_mode && (inner_mode == wanted_inner_mode
|| (! mode_dependent_address_p (XEXP (inner, 0)) || (! mode_dependent_address_p (XEXP (inner, 0))
&& ! MEM_VOLATILE_P (inner)))))) && ! MEM_VOLATILE_P (inner))))))
{ {
...@@ -5301,18 +5301,18 @@ make_extraction (mode, inner, pos, pos_rtx, len, ...@@ -5301,18 +5301,18 @@ make_extraction (mode, inner, pos, pos_rtx, len,
if (pos_rtx == 0) if (pos_rtx == 0)
{ {
offset += pos / BITS_PER_UNIT; offset += pos / BITS_PER_UNIT;
pos %= GET_MODE_BITSIZE (wanted_mem_mode); pos %= GET_MODE_BITSIZE (wanted_inner_mode);
} }
if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN
&& ! spans_byte && ! spans_byte
&& is_mode != wanted_mem_mode) && is_mode != wanted_inner_mode)
offset = (GET_MODE_SIZE (is_mode) offset = (GET_MODE_SIZE (is_mode)
- GET_MODE_SIZE (wanted_mem_mode) - offset); - GET_MODE_SIZE (wanted_inner_mode) - offset);
if (offset != 0 || inner_mode != wanted_mem_mode) if (offset != 0 || inner_mode != wanted_inner_mode)
{ {
rtx newmem = gen_rtx (MEM, wanted_mem_mode, rtx newmem = gen_rtx (MEM, wanted_inner_mode,
plus_constant (XEXP (inner, 0), offset)); plus_constant (XEXP (inner, 0), offset));
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (inner); RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (inner);
MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (inner); MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (inner);
...@@ -5323,7 +5323,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, ...@@ -5323,7 +5323,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
/* If INNER is not memory, we can always get it into the proper mode. */ /* If INNER is not memory, we can always get it into the proper mode. */
else if (GET_CODE (inner) != MEM) else if (GET_CODE (inner) != MEM)
inner = force_to_mode (inner, extraction_mode, inner = force_to_mode (inner, wanted_inner_mode,
pos_rtx || len + orig_pos >= HOST_BITS_PER_WIDE_INT pos_rtx || len + orig_pos >= HOST_BITS_PER_WIDE_INT
? GET_MODE_MASK (extraction_mode) ? GET_MODE_MASK (extraction_mode)
: (((HOST_WIDE_INT) 1 << len) - 1) << orig_pos, : (((HOST_WIDE_INT) 1 << len) - 1) << orig_pos,
...@@ -9156,24 +9156,19 @@ simplify_comparison (code, pop0, pop1) ...@@ -9156,24 +9156,19 @@ simplify_comparison (code, pop0, pop1)
/* If we are extracting a single bit from a variable position in /* If we are extracting a single bit from a variable position in
a constant that has only a single bit set and are comparing it a constant that has only a single bit set and are comparing it
with zero, we can convert this into an equality comparison with zero, we can convert this into an equality comparison
between the position and the location of the single bit. We can't between the position and the location of the single bit. */
do this if bit endian and we don't have an extzv since we then
can't know what mode to use for the endianness adjustment. */
if (GET_CODE (XEXP (op0, 0)) == CONST_INT if (GET_CODE (XEXP (op0, 0)) == CONST_INT
&& XEXP (op0, 1) == const1_rtx && XEXP (op0, 1) == const1_rtx
&& equality_comparison_p && const_op == 0 && equality_comparison_p && const_op == 0
&& (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0 && (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0)
&& (! BITS_BIG_ENDIAN
#ifdef HAVE_extzv
|| HAVE_extzv
#endif
))
{ {
#ifdef HAVE_extzv
if (BITS_BIG_ENDIAN) if (BITS_BIG_ENDIAN)
#ifdef HAVE_extzv
i = (GET_MODE_BITSIZE i = (GET_MODE_BITSIZE
(insn_operand_mode[(int) CODE_FOR_extzv][1]) - 1 - i); (insn_operand_mode[(int) CODE_FOR_extzv][1]) - 1 - i);
#else
i = BITS_PER_WORD - 1 - i;
#endif #endif
op0 = XEXP (op0, 2); op0 = XEXP (op0, 2);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment