diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1996-03-11 06:49:32 -0500 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1996-03-11 06:49:32 -0500 |
commit | d7cd794fdf7abd1d9e93482a8074220a1e133c8b (patch) | |
tree | 5817b710fa1df498d731a3b5bd42aa1b9dfdac73 /gcc | |
parent | 2ae508e5e3d7756fb7bf74015337f82869f16a77 (diff) | |
download | gcc-d7cd794fdf7abd1d9e93482a8074220a1e133c8b.zip gcc-d7cd794fdf7abd1d9e93482a8074220a1e133c8b.tar.gz gcc-d7cd794fdf7abd1d9e93482a8074220a1e133c8b.tar.bz2 |
(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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/combine.c | 67 |
1 files changed, 31 insertions, 36 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index 3b7ecb6..7023119 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -5068,7 +5068,8 @@ make_extraction (mode, inner, pos, pos_rtx, len, ignore the POS lowest bits, etc. */ enum machine_mode is_mode = GET_MODE (inner); 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 extraction_mode = word_mode; enum machine_mode tmode = mode_for_size (len, MODE_INT, 1); @@ -5208,12 +5209,12 @@ make_extraction (mode, inner, pos, pos_rtx, len, || (pos_rtx != 0 && len != 1))) 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. */ #ifdef HAVE_insv 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]; extraction_mode = insn_operand_mode[(int) CODE_FOR_insv][3]; } @@ -5222,7 +5223,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, #ifdef HAVE_extzv 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]; extraction_mode = insn_operand_mode[(int) CODE_FOR_extzv][0]; } @@ -5231,7 +5232,7 @@ make_extraction (mode, inner, pos, pos_rtx, len, #ifdef HAVE_extv 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]; extraction_mode = insn_operand_mode[(int) CODE_FOR_extv][0]; } @@ -5247,13 +5248,15 @@ make_extraction (mode, inner, pos, pos_rtx, len, && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (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 - cannot, the desired mode is EXTRACTION_MODE. */ - if (GET_CODE (inner) != MEM - || (inner_mode != wanted_mem_mode - && (mode_dependent_address_p (XEXP (inner, 0)) - || MEM_VOLATILE_P (inner)))) - wanted_mem_mode = extraction_mode; + /* If this is not from memory, the desired mode is wanted_inner_reg_mode; + if we have to change the mode of memory and cannot, the desired mode is + EXTRACTION_MODE. */ + if (GET_CODE (inner) != MEM) + wanted_inner_mode = wanted_inner_reg_mode; + else if (inner_mode != wanted_inner_mode + && (mode_dependent_address_p (XEXP (inner, 0)) + || MEM_VOLATILE_P (inner))) + wanted_inner_mode = extraction_mode; orig_pos = pos; @@ -5262,14 +5265,11 @@ make_extraction (mode, inner, pos, pos_rtx, len, /* If position is constant, compute new position. Otherwise, build subtraction. */ if (pos_rtx == 0) - pos = (MAX (GET_MODE_BITSIZE (is_mode), - GET_MODE_BITSIZE (wanted_mem_mode)) - - len - pos); + pos = GET_MODE_BITSIZE (wanted_inner_mode) - len - pos; else pos_rtx = gen_rtx_combine (MINUS, GET_MODE (pos_rtx), - GEN_INT (MAX (GET_MODE_BITSIZE (is_mode), - GET_MODE_BITSIZE (wanted_mem_mode)) + GEN_INT (GET_MODE_BITSIZE (wanted_inner_mode) - len), pos_rtx); } @@ -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 extract, try to adjust the byte to point to the byte containing the value. */ - if (wanted_mem_mode != VOIDmode - && GET_MODE_SIZE (wanted_mem_mode) < GET_MODE_SIZE (is_mode) + if (wanted_inner_mode != VOIDmode + && GET_MODE_SIZE (wanted_inner_mode) < GET_MODE_SIZE (is_mode) && ((GET_CODE (inner) == MEM - && (inner_mode == wanted_mem_mode + && (inner_mode == wanted_inner_mode || (! mode_dependent_address_p (XEXP (inner, 0)) && ! MEM_VOLATILE_P (inner)))))) { @@ -5301,18 +5301,18 @@ make_extraction (mode, inner, pos, pos_rtx, len, if (pos_rtx == 0) { 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 && ! spans_byte - && is_mode != wanted_mem_mode) + && is_mode != wanted_inner_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)); RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (inner); MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (inner); @@ -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. */ 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 ? GET_MODE_MASK (extraction_mode) : (((HOST_WIDE_INT) 1 << len) - 1) << orig_pos, @@ -9156,24 +9156,19 @@ simplify_comparison (code, pop0, pop1) /* 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 with zero, we can convert this into an equality comparison - between the position and the location of the single bit. We can't - 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. */ + between the position and the location of the single bit. */ if (GET_CODE (XEXP (op0, 0)) == CONST_INT && XEXP (op0, 1) == const1_rtx && equality_comparison_p && const_op == 0 - && (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0 - && (! BITS_BIG_ENDIAN -#ifdef HAVE_extzv - || HAVE_extzv -#endif - )) + && (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0) { -#ifdef HAVE_extzv if (BITS_BIG_ENDIAN) +#ifdef HAVE_extzv i = (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][1]) - 1 - i); +#else + i = BITS_PER_WORD - 1 - i; #endif op0 = XEXP (op0, 2); |