diff options
author | Zack Weinberg <zack@gcc.gnu.org> | 2004-01-16 01:27:38 +0000 |
---|---|---|
committer | Zack Weinberg <zack@gcc.gnu.org> | 2004-01-16 01:27:38 +0000 |
commit | f57fc998eeab27e8292de128b37c94ffa37d8409 (patch) | |
tree | 8c8acf6e85b0ef4b2cdeb4d1ce751bdf47265a9a /gcc | |
parent | 16a9a2803f9e25933a2ca2bc28590464b1f42c9f (diff) | |
download | gcc-f57fc998eeab27e8292de128b37c94ffa37d8409.zip gcc-f57fc998eeab27e8292de128b37c94ffa37d8409.tar.gz gcc-f57fc998eeab27e8292de128b37c94ffa37d8409.tar.bz2 |
ia64.md (*movti_internal): C output template extracted to ia64.c.
* config/ia64/ia64.md (*movti_internal): C output template
extracted to ia64.c.
(*movti_internal_reg): Delete.
(reload_inti, reload_outti): Use the correct mode on operand 2
in the first place, don't fix it up in the output template.
(movtf, reload_ointf, reload_outtf): New expanders.
(*movtf_internal): New define_insn_and_split.
* config/ia64/ia64.c (ia64_split_timode): Rename to ia64_split_tmode;
make static; do not hand TFmode CONST_DOUBLEs to split_double.
(ia64_split_tmode_move): New function, body mostly pulled
from ia64.md:*movti_internal.
(ia64_function_arg_words): New function, extracted common
logic from ia64_function_arg et seq.
(ia64_function_arg_offset): Likewise. Handle correctly the
case of a scalar quantity 16 bytes wide with only 8-byte alignment.
(ia64_function_arg, ia64_function_arg_partial_nregs)
(ia64_function_arg_advance): Use ia64_function_arg_words and
ia64_function_arg_offset.
(ia64_function_value): TCmode does not go in float regs.
(ia64_secondary_reload_class): Also handle TFmode.
* config/ia64/ia64-protos.h: Remove prototype for
ia64_split_timode; add prototype for ia64_split_tmode_move.
From-SVN: r75956
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 39 | ||||
-rw-r--r-- | gcc/config/ia64/ia64-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 175 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.md | 132 |
4 files changed, 211 insertions, 137 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2c95abb..4a2e9aa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2004-01-15 Zack Weinberg <zack@codesourcery.com> + + * config/ia64/ia64.md (*movti_internal): C output template + extracted to ia64.c. + (*movti_internal_reg): Delete. + (reload_inti, reload_outti): Use the correct mode on operand 2 + in the first place, don't fix it up in the output template. + (movtf, reload_ointf, reload_outtf): New expanders. + (*movtf_internal): New define_insn_and_split. + * config/ia64/ia64.c (ia64_split_timode): Rename to ia64_split_tmode; + make static; do not hand TFmode CONST_DOUBLEs to split_double. + (ia64_split_tmode_move): New function, body mostly pulled + from ia64.md:*movti_internal. + (ia64_function_arg_words): New function, extracted common + logic from ia64_function_arg et seq. + (ia64_function_arg_offset): Likewise. Handle correctly the + case of a scalar quantity 16 bytes wide with only 8-byte alignment. + (ia64_function_arg, ia64_function_arg_partial_nregs) + (ia64_function_arg_advance): Use ia64_function_arg_words and + ia64_function_arg_offset. + (ia64_function_value): TCmode does not go in float regs. + (ia64_secondary_reload_class): Also handle TFmode. + * config/ia64/ia64-protos.h: Remove prototype for + ia64_split_timode; add prototype for ia64_split_tmode_move. + 2004-01-15 Kelley Cook <kcook@gcc.gnu.org> * Makefile.in (MAINT): Make it an immediate assignment. @@ -224,7 +249,7 @@ 2004-01-14 Richard Earnshaw <rearnsha@arm.com> - * regrename.c (find_oldest_value_reg): If the replacement uses + * regrename.c (find_oldest_value_reg): If the replacement uses multiple hard registers, check that all of them are in CLASS. 2004-01-14 Jan Hubicka <jh@suse.cz> @@ -301,14 +326,14 @@ 2004-01-13 Bernardo Innocenti <bernie@develer.com> * config/m68k/netbsd-elf.h (REGISTER_NAMES): Add missing "argptr" - pseudo-register. + pseudo-register. 2004-01-13 Devang Patel <dpatel@apple.com PR debug/7078 - * dbxout.c (dbxout_symbol_name): Emit mangled names for + * dbxout.c (dbxout_symbol_name): Emit mangled names for NAMESPACE_DECL memebers. - + 2004-01-13 Andrew Pinski <pinskia@physics.uc.edu> PR c++/12709 @@ -318,7 +343,7 @@ 2004-01-13 Vladimir Makarov <vmakarov@redhat.com> * rtl.def: Add comment about new option in automata_option. - + * genautomata.c (PROGRESS_OPTION): New macro. (progress_flag): New global variable. (gen_automata_option): Process `progress'. @@ -329,14 +354,14 @@ (initiate_automaton_gen): Process command line flag `-progress'. * doc/md.texi: Describe the new option. - + 2004-01-13 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz> * cfg.c (dump_bb): Dump entry edges. 2004-01-13 Richard Earnshaw <rearnsha@arm.com> - * arm.c (thumb_legitimate_address_p): Only allow constant pool + * arm.c (thumb_legitimate_address_p): Only allow constant pool references from SImode. * arm.md (thumb_movhi_insn): Don't allow minipool references. diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index 01d6115..c6920fa 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -80,7 +80,7 @@ extern int ia64_move_ok (rtx, rtx); extern int addp4_optimize_ok (rtx, rtx); extern void ia64_emit_cond_move (rtx, rtx, rtx); extern int ia64_depz_field_mask (rtx, rtx); -extern rtx ia64_split_timode (rtx[], rtx, rtx); +extern void ia64_split_tmode_move (rtx[]); extern rtx spill_xfmode_operand (rtx, int); extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode); extern void ia64_expand_call (rtx, rtx, rtx, int); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 67df9cb..a0af1b4 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -1361,10 +1361,11 @@ ia64_emit_cond_move (rtx op0, rtx op1, rtx cond) PATTERN (insn)); } -/* Split a post-reload TImode reference into two DImode components. */ +/* Split a post-reload TImode or TFmode reference into two DImode + components. */ -rtx -ia64_split_timode (rtx out[2], rtx in, rtx scratch) +static rtx +ia64_split_tmode (rtx out[2], rtx in, rtx scratch) { switch (GET_CODE (in)) { @@ -1417,7 +1418,32 @@ ia64_split_timode (rtx out[2], rtx in, rtx scratch) case CONST_INT: case CONST_DOUBLE: - split_double (in, &out[0], &out[1]); + if (GET_MODE (in) != TFmode) + split_double (in, &out[0], &out[1]); + else + /* split_double does not understand how to split a TFmode + quantity into a pair of DImode constants. */ + { + REAL_VALUE_TYPE r; + unsigned HOST_WIDE_INT p[2]; + long l[4]; /* TFmode is 128 bits */ + + REAL_VALUE_FROM_CONST_DOUBLE (r, in); + real_to_target (l, &r, TFmode); + + if (FLOAT_WORDS_BIG_ENDIAN) + { + p[0] = (((unsigned HOST_WIDE_INT) l[0]) << 32) + l[1]; + p[1] = (((unsigned HOST_WIDE_INT) l[2]) << 32) + l[3]; + } + else + { + p[0] = (((unsigned HOST_WIDE_INT) l[3]) << 32) + l[2]; + p[1] = (((unsigned HOST_WIDE_INT) l[1]) << 32) + l[0]; + } + out[0] = GEN_INT (p[0]); + out[1] = GEN_INT (p[1]); + } return NULL_RTX; default: @@ -1425,6 +1451,46 @@ ia64_split_timode (rtx out[2], rtx in, rtx scratch) } } +/* Split a TImode or TFmode move instruction after reload. + This is used by *movtf_internal and *movti_internal. */ +void +ia64_split_tmode_move (rtx operands[]) +{ + rtx adj1, adj2, in[2], out[2], insn; + int first; + + adj1 = ia64_split_tmode (in, operands[1], operands[2]); + adj2 = ia64_split_tmode (out, operands[0], operands[2]); + + first = 0; + if (reg_overlap_mentioned_p (out[0], in[1])) + { + if (reg_overlap_mentioned_p (out[1], in[0])) + abort (); + first = 1; + } + + if (adj1 && adj2) + abort (); + if (adj1) + emit_insn (adj1); + if (adj2) + emit_insn (adj2); + insn = emit_insn (gen_rtx_SET (VOIDmode, out[first], in[first])); + if (GET_CODE (out[first]) == MEM + && GET_CODE (XEXP (out[first], 0)) == POST_MODIFY) + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, + XEXP (XEXP (out[first], 0), 0), + REG_NOTES (insn)); + insn = emit_insn (gen_rtx_SET (VOIDmode, out[!first], in[!first])); + if (GET_CODE (out[!first]) == MEM + && GET_CODE (XEXP (out[!first], 0)) == POST_MODIFY) + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, + XEXP (XEXP (out[!first], 0), 0), + REG_NOTES (insn)); + +} + /* ??? Fixing GR->FR XFmode moves during reload is hard. You need to go through memory plus an extra GR scratch register. Except that you can either get the first from SECONDARY_MEMORY_NEEDED or the second from @@ -3407,9 +3473,50 @@ hfa_element_mode (tree type, int nested) return VOIDmode; } +/* Return the number of words required to hold a quantity of TYPE and MODE + when passed as an argument. */ +static int +ia64_function_arg_words (tree type, enum machine_mode mode) +{ + int words; + + if (mode == BLKmode) + words = int_size_in_bytes (type); + else + words = GET_MODE_SIZE (mode); + + return (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD; /* round up */ +} + +/* Return the number of registers that should be skipped so the current + argument (described by TYPE and WORDS) will be properly aligned. + + Integer and float arguments larger than 8 bytes start at the next + even boundary. Aggregates larger than 8 bytes start at the next + even boundary if the aggregate has 16 byte alignment. Note that + in the 32-bit ABI, TImode and TFmode have only 8-byte alignment + but are still to be aligned in registers. + + ??? The ABI does not specify how to handle aggregates with + alignment from 9 to 15 bytes, or greater than 16. We handle them + all as if they had 16 byte alignment. Such aggregates can occur + only if gcc extensions are used. */ +static int +ia64_function_arg_offset (CUMULATIVE_ARGS *cum, tree type, int words) +{ + if ((cum->words & 1) == 0) + return 0; + + if (type + && TREE_CODE (type) != INTEGER_TYPE + && TREE_CODE (type) != REAL_TYPE) + return TYPE_ALIGN (type) > 8 * BITS_PER_UNIT; + else + return words > 1; +} + /* Return rtx for register where argument is passed, or zero if it is passed on the stack. */ - /* ??? 128-bit quad-precision floats are always passed in general registers. */ @@ -3418,25 +3525,10 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named, int incoming) { int basereg = (incoming ? GR_ARG_FIRST : AR_ARG_FIRST); - int words = (((mode == BLKmode ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1) - / UNITS_PER_WORD); - int offset = 0; + int words = ia64_function_arg_words (type, mode); + int offset = ia64_function_arg_offset (cum, type, words); enum machine_mode hfa_mode = VOIDmode; - /* Integer and float arguments larger than 8 bytes start at the next even - boundary. Aggregates larger than 8 bytes start at the next even boundary - if the aggregate has 16 byte alignment. Net effect is that types with - alignment greater than 8 start at the next even boundary. */ - /* ??? The ABI does not specify how to handle aggregates with alignment from - 9 to 15 bytes, or greater than 16. We handle them all as if they had - 16 byte alignment. Such aggregates can occur only if gcc extensions are - used. */ - if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT) - : (words > 1)) - && (cum->words & 1)) - offset = 1; - /* If all argument slots are used, then it must go on the stack. */ if (cum->words + offset >= MAX_ARGUMENT_SLOTS) return 0; @@ -3590,17 +3682,8 @@ int ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED) { - int words = (((mode == BLKmode ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1) - / UNITS_PER_WORD); - int offset = 0; - - /* Arguments with alignment larger than 8 bytes start at the next even - boundary. */ - if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT) - : (words > 1)) - && (cum->words & 1)) - offset = 1; + int words = ia64_function_arg_words (type, mode); + int offset = ia64_function_arg_offset (cum, type, words); /* If all argument slots are used, then it must go on the stack. */ if (cum->words + offset >= MAX_ARGUMENT_SLOTS) @@ -3624,23 +3707,14 @@ void ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named) { - int words = (((mode == BLKmode ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1) - / UNITS_PER_WORD); - int offset = 0; + int words = ia64_function_arg_words (type, mode); + int offset = ia64_function_arg_offset (cum, type, words); enum machine_mode hfa_mode = VOIDmode; /* If all arg slots are already full, then there is nothing to do. */ if (cum->words >= MAX_ARGUMENT_SLOTS) return; - /* Arguments with alignment larger than 8 bytes start at the next even - boundary. */ - if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT) - : (words > 1)) - && (cum->words & 1)) - offset = 1; - cum->words += words + offset; /* Check for and handle homogeneous FP aggregates. */ @@ -3750,9 +3824,12 @@ ia64_va_arg (tree valist, tree type) return gen_rtx_MEM (ptr_mode, addr); } - /* Arguments with alignment larger than 8 bytes start at the next even - boundary. */ - if (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT) + /* Aggregate arguments with alignment larger than 8 bytes start at + the next even boundary. Integer and floating point arguments + do so if they are larger than 8 bytes, whether or not they are + also aligned larger than 8 bytes. */ + if ((TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == INTEGER_TYPE) + ? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT) { t = build (PLUS_EXPR, TREE_TYPE (valist), valist, build_int_2 (2 * UNITS_PER_WORD - 1, 0)); @@ -3839,7 +3916,7 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED) else return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc)); } - else if (FLOAT_TYPE_P (valtype) && mode != TFmode) + else if (FLOAT_TYPE_P (valtype) && mode != TFmode && mode != TCmode) return gen_rtx_REG (mode, FR_ARG_FIRST); else { @@ -4380,7 +4457,7 @@ ia64_secondary_reload_class (enum reg_class class, case GR_REGS: /* Since we have no offsettable memory addresses, we need a temporary to hold the address of the second word. */ - if (mode == TImode) + if (mode == TImode || mode == TFmode) return GR_REGS; break; diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index 01e4d73..169569a 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -606,70 +606,7 @@ "reload_completed" [(const_int 0)] { - rtx adj1, adj2, in[2], out[2], insn; - int first; - - adj1 = ia64_split_timode (in, operands[1], operands[2]); - adj2 = ia64_split_timode (out, operands[0], operands[2]); - - first = 0; - if (reg_overlap_mentioned_p (out[0], in[1])) - { - if (reg_overlap_mentioned_p (out[1], in[0])) - abort (); - first = 1; - } - - if (adj1 && adj2) - abort (); - if (adj1) - emit_insn (adj1); - if (adj2) - emit_insn (adj2); - insn = emit_insn (gen_rtx_SET (VOIDmode, out[first], in[first])); - if (GET_CODE (out[first]) == MEM - && GET_CODE (XEXP (out[first], 0)) == POST_MODIFY) - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, - XEXP (XEXP (out[first], 0), 0), - REG_NOTES (insn)); - insn = emit_insn (gen_rtx_SET (VOIDmode, out[!first], in[!first])); - if (GET_CODE (out[!first]) == MEM - && GET_CODE (XEXP (out[!first], 0)) == POST_MODIFY) - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, - XEXP (XEXP (out[!first], 0), 0), - REG_NOTES (insn)); - DONE; -} - [(set_attr "itanium_class" "unknown") - (set_attr "predicable" "no")]) - -;; ??? SSA creates these. Can't allow memories since we don't have -;; the scratch register. Fortunately combine will know how to add -;; the clobber and scratch. -(define_insn_and_split "*movti_internal_reg" - [(set (match_operand:TI 0 "register_operand" "=r") - (match_operand:TI 1 "nonmemory_operand" "ri"))] - "" - "#" - "reload_completed" - [(const_int 0)] -{ - rtx in[2], out[2]; - int first; - - ia64_split_timode (in, operands[1], NULL_RTX); - ia64_split_timode (out, operands[0], NULL_RTX); - - first = 0; - if (reg_overlap_mentioned_p (out[0], in[1])) - { - if (reg_overlap_mentioned_p (out[1], in[0])) - abort (); - first = 1; - } - - emit_insn (gen_rtx_SET (VOIDmode, out[first], in[first])); - emit_insn (gen_rtx_SET (VOIDmode, out[!first], in[!first])); + ia64_split_tmode_move (operands); DONE; } [(set_attr "itanium_class" "unknown") @@ -677,27 +614,17 @@ (define_expand "reload_inti" [(parallel [(set (match_operand:TI 0 "register_operand" "=r") - (match_operand:TI 1 "" "m")) - (clobber (match_operand:TI 2 "register_operand" "=&r"))])] + (match_operand:TI 1 "memory_operand" "m")) + (clobber (match_operand:DI 2 "register_operand" "=&r"))])] "" -{ - unsigned int s_regno = REGNO (operands[2]); - if (s_regno == REGNO (operands[0])) - s_regno += 1; - operands[2] = gen_rtx_REG (DImode, s_regno); -}) + "") (define_expand "reload_outti" - [(parallel [(set (match_operand:TI 0 "" "=m") + [(parallel [(set (match_operand:TI 0 "memory_operand" "=m") (match_operand:TI 1 "register_operand" "r")) - (clobber (match_operand:TI 2 "register_operand" "=&r"))])] + (clobber (match_operand:DI 2 "register_operand" "=&r"))])] "" -{ - unsigned int s_regno = REGNO (operands[2]); - if (s_regno == REGNO (operands[1])) - s_regno += 1; - operands[2] = gen_rtx_REG (DImode, s_regno); -}) + "") ;; Floating Point Moves ;; @@ -835,6 +762,51 @@ ldfe %0 = %1%P1 stfe %0 = %F1%P0" [(set_attr "itanium_class" "fmisc,fld,stf")]) + +;; Better code generation via insns that deal with TFmode register pairs +;; directly. +;; With no offsettable memory references, we've got to have a scratch +;; around to play with the second word. +(define_expand "movtf" + [(parallel [(set (match_operand:TF 0 "general_operand" "") + (match_operand:TF 1 "general_operand" "")) + (clobber (match_scratch:DI 2 ""))])] + "" +{ + rtx op1 = ia64_expand_move (operands[0], operands[1]); + if (!op1) + DONE; + operands[1] = op1; +}) + +(define_insn_and_split "*movtf_internal" + [(set (match_operand:TF 0 "nonimmediate_operand" "=r,r,m") + (match_operand:TF 1 "general_operand" "ri,m,r")) + (clobber (match_scratch:DI 2 "=X,&r,&r"))] + "ia64_move_ok (operands[0], operands[1])" + "#" + "reload_completed" + [(const_int 0)] +{ + ia64_split_tmode_move (operands); + DONE; +} + [(set_attr "itanium_class" "unknown") + (set_attr "predicable" "no")]) + +(define_expand "reload_intf" + [(parallel [(set (match_operand:TF 0 "register_operand" "=r") + (match_operand:TF 1 "memory_operand" "m")) + (clobber (match_operand:DI 2 "register_operand" "=&r"))])] + "" + "") + +(define_expand "reload_outtf" + [(parallel [(set (match_operand:TF 0 "memory_operand" "=m") + (match_operand:TF 1 "register_operand" "r")) + (clobber (match_operand:DI 2 "register_operand" "=&r"))])] + "" + "") ;; :::::::::::::::::::: ;; :: |