diff options
author | Jeffrey A Law <law@cygnus.com> | 1998-09-15 22:47:10 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1998-09-15 16:47:10 -0600 |
commit | 0d8e55d8cd9fd8b867fb44005a8ee9435f1406ae (patch) | |
tree | ed903d8c350727df2bf1f53c6551d8a874814869 | |
parent | 54d65918774e3854206d61c82dbb39d2241eb603 (diff) | |
download | gcc-0d8e55d8cd9fd8b867fb44005a8ee9435f1406ae.zip gcc-0d8e55d8cd9fd8b867fb44005a8ee9435f1406ae.tar.gz gcc-0d8e55d8cd9fd8b867fb44005a8ee9435f1406ae.tar.bz2 |
combine.c (make_extraction): If no mode is specified for an operand of insv...
* combine.c (make_extraction): If no mode is specified for
an operand of insv, extv, or extzv, default it to word_mode.
(simplify_comparison): Similarly.
* expmed.c (store_bit_field): Similarly.
(extract_bit_field): Similarly.
* function.c (fixup_var_regs_1): Similarly.
* recog.c (validate_replace_rtx_1): Similarly.
* mips.md (extv, extzv, insv expanders): Default modes for most
operands. Handle TARGET_64BIT.
(movdi_uld, movdi_usd): New patterns.
From-SVN: r22439
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/combine.c | 46 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 178 | ||||
-rw-r--r-- | gcc/expmed.c | 78 | ||||
-rw-r--r-- | gcc/function.c | 19 | ||||
-rw-r--r-- | gcc/recog.c | 12 |
6 files changed, 273 insertions, 71 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d791d77..a4f4e38 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ Tue Sep 15 22:59:52 1998 Jeffrey A Law (law@cygnus.com) + * combine.c (make_extraction): If no mode is specified for + an operand of insv, extv, or extzv, default it to word_mode. + (simplify_comparison): Similarly. + * expmed.c (store_bit_field): Similarly. + (extract_bit_field): Similarly. + * function.c (fixup_var_regs_1): Similarly. + * recog.c (validate_replace_rtx_1): Similarly. + * mips.md (extv, extzv, insv expanders): Default modes for most + operands. Handle TARGET_64BIT. + (movdi_uld, movdi_usd): New patterns. + * pa.c (emit_move_sequence): Do not replace a pseudo with its equivalent memory location unless we have been provided a scratch register. Similarly do not call find_replacement unless a diff --git a/gcc/combine.c b/gcc/combine.c index 8f0ea65..024cb51 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -5605,27 +5605,45 @@ make_extraction (mode, inner, pos, pos_rtx, len, #ifdef HAVE_insv if (in_dest) { - 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]; + wanted_inner_reg_mode + = (insn_operand_mode[(int) CODE_FOR_insv][0] == VOIDmode + ? word_mode + : insn_operand_mode[(int) CODE_FOR_insv][0]); + pos_mode = (insn_operand_mode[(int) CODE_FOR_insv][2] == VOIDmode + ? word_mode : insn_operand_mode[(int) CODE_FOR_insv][2]); + extraction_mode = (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode + ? word_mode + : insn_operand_mode[(int) CODE_FOR_insv][3]); } #endif #ifdef HAVE_extzv if (! in_dest && unsignedp) { - 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]; + wanted_inner_reg_mode + = (insn_operand_mode[(int) CODE_FOR_extzv][1] == VOIDmode + ? word_mode + : insn_operand_mode[(int) CODE_FOR_extzv][1]); + pos_mode = (insn_operand_mode[(int) CODE_FOR_extzv][3] == VOIDmode + ? word_mode : insn_operand_mode[(int) CODE_FOR_extzv][3]); + extraction_mode = (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode + ? word_mode + : insn_operand_mode[(int) CODE_FOR_extzv][0]); } #endif #ifdef HAVE_extv if (! in_dest && ! unsignedp) { - 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]; + wanted_inner_reg_mode + = (insn_operand_mode[(int) CODE_FOR_extv][1] == VOIDmode + ? word_mode + : insn_operand_mode[(int) CODE_FOR_extv][1]); + pos_mode = (insn_operand_mode[(int) CODE_FOR_extv][3] == VOIDmode + ? word_mode : insn_operand_mode[(int) CODE_FOR_extv][3]); + extraction_mode = (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode + ? word_mode + : insn_operand_mode[(int) CODE_FOR_extv][0]); } #endif @@ -9762,12 +9780,16 @@ simplify_comparison (code, pop0, pop1) && (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0) { if (BITS_BIG_ENDIAN) + { #ifdef HAVE_extzv - i = (GET_MODE_BITSIZE - (insn_operand_mode[(int) CODE_FOR_extzv][1]) - 1 - i); + mode = insn_operand_mode[(int) CODE_FOR_extzv][1]; + if (mode == VOIDmode) + mode = word_mode; + i = (GET_MODE_BITSIZE (mode) - 1 - i); #else - i = BITS_PER_WORD - 1 - i; + i = BITS_PER_WORD - 1 - i; #endif + } op0 = XEXP (op0, 2); op1 = GEN_INT (i); diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 4172c41..17bd10f 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -4224,24 +4224,30 @@ move\\t%0,%z4\\n\\ ;; Bit field extract patterns which use lwl/lwr. -;; ??? There should be DImode variants for 64 bit code, but the current -;; bitfield scheme can't handle that. We would need to add new optabs -;; in order to make that work. - ;; ??? There could be HImode variants for the ulh/ulhu/ush macros. ;; It isn't clear whether this will give better code. +;; Only specify the mode operand 1, the rest are assumed to be word_mode. (define_expand "extv" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extract:SI (match_operand:QI 1 "memory_operand" "") - (match_operand:SI 2 "immediate_operand" "") - (match_operand:SI 3 "immediate_operand" "")))] + [(set (match_operand 0 "register_operand" "") + (sign_extract (match_operand:QI 1 "memory_operand" "") + (match_operand 2 "immediate_operand" "") + (match_operand 3 "immediate_operand" "")))] "!TARGET_MIPS16" " { - /* If this isn't a 32 bit field, and it doesn't start on a byte boundary - then fail. */ - if (INTVAL (operands[2]) != 32 || (INTVAL (operands[3]) % 8) != 0) + /* If the field does not start on a byte boundary, then fail. */ + if (INTVAL (operands[3]) % 8 != 0) + FAIL; + + /* MIPS I and MIPS II can only handle a 32bit field. */ + if (!TARGET_64BIT && INTVAL (operands[2]) != 32) + FAIL; + + /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */ + if (TARGET_64BIT + && INTVAL (operands[2]) != 64 + && INTVAL (operands[2]) != 32) FAIL; /* This can happen for a 64 bit target, when extracting a value from @@ -4253,22 +4259,43 @@ move\\t%0,%z4\\n\\ /* Change the mode to BLKmode for aliasing purposes. */ operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0)); - /* Otherwise, emit a lwl/lwr pair to load the value. */ - emit_insn (gen_movsi_ulw (operands[0], operands[1])); + /* Otherwise, emit a l[wd]l/l[wd]r pair to load the value. */ + if (INTVAL (operands[2]) == 64) + emit_insn (gen_movdi_uld (operands[0], operands[1])); + else + { + if (TARGET_64BIT) + { + operands[0] = gen_lowpart (SImode, operands[0]); + if (operands[0] == NULL_RTX) + FAIL; + } + emit_insn (gen_movsi_ulw (operands[0], operands[1])); + } DONE; }") +;; Only specify the mode operand 1, the rest are assumed to be word_mode. (define_expand "extzv" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extract:SI (match_operand:QI 1 "memory_operand" "") - (match_operand:SI 2 "immediate_operand" "") - (match_operand:SI 3 "immediate_operand" "")))] + [(set (match_operand 0 "register_operand" "") + (zero_extract (match_operand:QI 1 "memory_operand" "") + (match_operand 2 "immediate_operand" "") + (match_operand 3 "immediate_operand" "")))] "!TARGET_MIPS16" " { - /* If this isn't a 32 bit field, and it doesn't start on a byte boundary - then fail. */ - if (INTVAL (operands[2]) != 32 || (INTVAL (operands[3]) % 8) != 0) + /* If the field does not start on a byte boundary, then fail. */ + if (INTVAL (operands[3]) % 8 != 0) + FAIL; + + /* MIPS I and MIPS II can only handle a 32bit field. */ + if (!TARGET_64BIT && INTVAL (operands[2]) != 32) + FAIL; + + /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */ + if (TARGET_64BIT + && INTVAL (operands[2]) != 64 + && INTVAL (operands[2]) != 32) FAIL; /* This can happen for a 64 bit target, when extracting a value from @@ -4281,21 +4308,42 @@ move\\t%0,%z4\\n\\ operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0)); /* Otherwise, emit a lwl/lwr pair to load the value. */ - emit_insn (gen_movsi_ulw (operands[0], operands[1])); + if (INTVAL (operands[2]) == 64) + emit_insn (gen_movdi_uld (operands[0], operands[1])); + else + { + if (TARGET_64BIT) + { + operands[0] = gen_lowpart (SImode, operands[0]); + if (operands[0] == NULL_RTX) + FAIL; + } + emit_insn (gen_movsi_ulw (operands[0], operands[1])); + } DONE; }") +;; Only specify the mode operands 0, the rest are assumed to be word_mode. (define_expand "insv" - [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "") - (match_operand:SI 1 "immediate_operand" "") - (match_operand:SI 2 "immediate_operand" "")) - (match_operand:SI 3 "register_operand" ""))] + [(set (zero_extract (match_operand:QI 0 "memory_operand" "") + (match_operand 1 "immediate_operand" "") + (match_operand 2 "immediate_operand" "")) + (match_operand 3 "register_operand" ""))] "!TARGET_MIPS16" " { - /* If this isn't a 32 bit field, and it doesn't start on a byte boundary - then fail. */ - if (INTVAL (operands[1]) != 32 || (INTVAL (operands[2]) % 8) != 0) + /* If the field does not start on a byte boundary, then fail. */ + if (INTVAL (operands[2]) % 8 != 0) + FAIL; + + /* MIPS I and MIPS II can only handle a 32bit field. */ + if (!TARGET_64BIT && INTVAL (operands[1]) != 32) + FAIL; + + /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */ + if (TARGET_64BIT + && INTVAL (operands[1]) != 64 + && INTVAL (operands[1]) != 32) FAIL; /* This can happen for a 64 bit target, when storing into a 32 bit union @@ -4307,8 +4355,19 @@ move\\t%0,%z4\\n\\ /* Change the mode to BLKmode for aliasing purposes. */ operands[0] = change_address (operands[0], BLKmode, XEXP (operands[0], 0)); - /* Otherwise, emit a swl/swr pair to load the value. */ - emit_insn (gen_movsi_usw (operands[0], operands[3])); + /* Otherwise, emit a s[wd]l/s[wd]r pair to load the value. */ + if (INTVAL (operands[1]) == 64) + emit_insn (gen_movdi_usd (operands[0], operands[3])); + else + { + if (TARGET_64BIT) + { + operands[3] = gen_lowpart (SImode, operands[3]); + if (operands[3] == NULL_RTX) + FAIL; + } + emit_insn (gen_movsi_usw (operands[0], operands[3])); + } DONE; }") @@ -4369,6 +4428,65 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "SI") (set_attr "length" "2,4")]) +;; Bit field extract patterns which use ldl/ldr. + +;; unaligned double word moves generated by the bit field patterns + +(define_insn "movdi_uld" + [(set (match_operand:DI 0 "register_operand" "=&d,&d") + (unspec:DI [(match_operand:BLK 1 "general_operand" "R,o")] 0))] + "" + "* +{ + rtx offset = const0_rtx; + rtx addr = XEXP (operands[1], 0); + rtx mem_addr = eliminate_constant_term (addr, &offset); + char *ret; + + if (TARGET_STATS) + mips_count_memory_refs (operands[1], 2); + + /* The stack/frame pointers are always aligned, so we can convert + to the faster lw if we are referencing an aligned stack location. */ + + if ((INTVAL (offset) & 7) == 0 + && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) + ret = \"ld\\t%0,%1\"; + else + ret = \"uld\\t%0,%1\"; + + return mips_fill_delay_slot (ret, DELAY_LOAD, operands, insn); +}" + [(set_attr "type" "load,load") + (set_attr "mode" "SI") + (set_attr "length" "2,4")]) + +(define_insn "movdi_usd" + [(set (match_operand:BLK 0 "memory_operand" "=R,o") + (unspec:BLK [(match_operand:DI 1 "reg_or_0_operand" "dJ,dJ")] 1))] + "" + "* +{ + rtx offset = const0_rtx; + rtx addr = XEXP (operands[0], 0); + rtx mem_addr = eliminate_constant_term (addr, &offset); + + if (TARGET_STATS) + mips_count_memory_refs (operands[0], 2); + + /* The stack/frame pointers are always aligned, so we can convert + to the faster sw if we are referencing an aligned stack location. */ + + if ((INTVAL (offset) & 7) == 0 + && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) + return \"sd\\t%1,%0\"; + + return \"usd\\t%z1,%0\"; +}" + [(set_attr "type" "store") + (set_attr "mode" "SI") + (set_attr "length" "2,4")]) + ;; These two patterns support loading addresses with two instructions instead ;; of using the macro instruction la. diff --git a/gcc/expmed.c b/gcc/expmed.c index c6efd62..730d904 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -211,10 +211,10 @@ negate_rtx (mode, x) /* ??? Note that there are two different ideas here for how to determine the size to count bits within, for a register. One is BITS_PER_WORD, and the other is the size of operand 3 - of the insv pattern. (The latter assumes that an n-bit machine - will be able to insert bit fields up to n bits wide.) - It isn't certain that either of these is right. - extract_bit_field has the same quandary. */ + of the insv pattern. + + If operand 3 of the insv pattern is VOIDmode, then we will use BITS_PER_WORD + else, we use the mode of operand 3. */ rtx store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size) @@ -230,6 +230,14 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size) register int offset = bitnum / unit; register int bitpos = bitnum % unit; register rtx op0 = str_rtx; +#ifdef HAVE_insv + int insv_bitsize; + + if (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode) + insv_bitsize = GET_MODE_BITSIZE (word_mode); + else + insv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]); +#endif if (GET_CODE (str_rtx) == MEM && ! MEM_IN_STRUCT_P (str_rtx)) abort (); @@ -400,21 +408,22 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size) && GET_MODE (value) != BLKmode && !(bitsize == 1 && GET_CODE (value) == CONST_INT) /* Ensure insv's size is wide enough for this field. */ - && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]) - >= bitsize) + && (insv_bitsize >= bitsize) && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG) - && (bitsize + bitpos - > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3])))) + && (bitsize + bitpos > insv_bitsize))) { int xbitpos = bitpos; rtx value1; rtx xop0 = op0; rtx last = get_last_insn (); rtx pat; - enum machine_mode maxmode - = insn_operand_mode[(int) CODE_FOR_insv][3]; - + enum machine_mode maxmode; int save_volatile_ok = volatile_ok; + + maxmode = insn_operand_mode[(int) CODE_FOR_insv][3]; + if (maxmode == VOIDmode) + maxmode = word_mode; + volatile_ok = 1; /* If this machine's insv can only insert into a register, copy OP0 @@ -894,6 +903,27 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, register rtx op0 = str_rtx; rtx spec_target = target; rtx spec_target_subreg = 0; +#ifdef HAVE_extv + int extv_bitsize; +#endif +#ifdef HAVE_extzv + int extzv_bitsize; +#endif + +#ifdef HAVE_extv + if (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode) + extv_bitsize = GET_MODE_BITSIZE (word_mode); + else + extv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]); +#endif + +#ifdef HAVE_extzv + if (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode) + extzv_bitsize = GET_MODE_BITSIZE (word_mode); + else + extzv_bitsize + = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]); +#endif /* Discount the part of the structure before the desired byte. We need to know how many bytes are safe to reference after it. */ @@ -1073,11 +1103,9 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, { #ifdef HAVE_extzv if (HAVE_extzv - && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]) - >= bitsize) + && (extzv_bitsize >= bitsize) && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG) - && (bitsize + bitpos - > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0])))) + && (bitsize + bitpos > extzv_bitsize))) { int xbitpos = bitpos, xoffset = offset; rtx bitsize_rtx, bitpos_rtx; @@ -1087,8 +1115,11 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, rtx xspec_target = spec_target; rtx xspec_target_subreg = spec_target_subreg; rtx pat; - enum machine_mode maxmode - = insn_operand_mode[(int) CODE_FOR_extzv][0]; + enum machine_mode maxmode; + + maxmode = insn_operand_mode[(int) CODE_FOR_extzv][0]; + if (maxmode == VOIDmode) + maxmode = word_mode; if (GET_CODE (xop0) == MEM) { @@ -1213,11 +1244,9 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, { #ifdef HAVE_extv if (HAVE_extv - && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]) - >= bitsize) + && (extv_bitsize >= bitsize) && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG) - && (bitsize + bitpos - > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0])))) + && (bitsize + bitpos > extv_bitsize))) { int xbitpos = bitpos, xoffset = offset; rtx bitsize_rtx, bitpos_rtx; @@ -1226,8 +1255,11 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, rtx xspec_target = spec_target; rtx xspec_target_subreg = spec_target_subreg; rtx pat; - enum machine_mode maxmode - = insn_operand_mode[(int) CODE_FOR_extv][0]; + enum machine_mode maxmode; + + maxmode = insn_operand_mode[(int) CODE_FOR_extv][0]; + if (maxmode == VOIDmode) + maxmode = word_mode; if (GET_CODE (xop0) == MEM) { diff --git a/gcc/function.c b/gcc/function.c index a5f8f05..c75648d 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -1975,11 +1975,19 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements) #ifdef HAVE_extzv if (GET_CODE (x) == ZERO_EXTRACT) - wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1]; + { + wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1]; + if (wanted_mode == VOIDmode) + wanted_mode = word_mode; + } #endif #ifdef HAVE_extv if (GET_CODE (x) == SIGN_EXTRACT) - wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1]; + { + wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1]; + if (wanted_mode == VOIDmode) + wanted_mode = word_mode; + } #endif /* If we have a narrower mode, we can do something. */ if (wanted_mode != VOIDmode @@ -2168,11 +2176,14 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements) && ! mode_dependent_address_p (XEXP (tem, 0)) && ! MEM_VOLATILE_P (tem)) { - enum machine_mode wanted_mode - = insn_operand_mode[(int) CODE_FOR_insv][0]; + enum machine_mode wanted_mode; enum machine_mode is_mode = GET_MODE (tem); HOST_WIDE_INT pos = INTVAL (XEXP (outerdest, 2)); + wanted_mode = insn_operand_mode[(int) CODE_FOR_insv][0]; + if (wanted_mode == VOIDmode) + wanted_mode = word_mode; + /* If we have a narrower mode, we can do something. */ if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode)) { diff --git a/gcc/recog.c b/gcc/recog.c index d472df0..9f6a1ea 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -484,11 +484,19 @@ validate_replace_rtx_1 (loc, from, to, object) #ifdef HAVE_extzv if (code == ZERO_EXTRACT) - wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1]; + { + wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1]; + if (wanted_mode == VOIDmode) + wanted_mode = word_mode; + } #endif #ifdef HAVE_extv if (code == SIGN_EXTRACT) - wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1]; + { + wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1]; + if (wanted_mode == VOIDmode) + wanted_mode = word_mode; + } #endif /* If we have a narrower mode, we can do something. */ |