]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ia64.md (*movti_internal): C output template extracted to ia64.c.
authorZack Weinberg <zack@gcc.gnu.org>
Fri, 16 Jan 2004 01:27:38 +0000 (01:27 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Fri, 16 Jan 2004 01:27:38 +0000 (01:27 +0000)
* 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

gcc/ChangeLog
gcc/config/ia64/ia64-protos.h
gcc/config/ia64/ia64.c
gcc/config/ia64/ia64.md

index 2c95abb857f4aabe043e48ca0e776b498c7b69ec..4a2e9aaea12480437774f08137cfe13d4a81ff62 100644 (file)
@@ -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.
 
 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>
 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
 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'.
        (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.
 
index 01d6115a0a699c636d95355bf0c893344767fe1b..c6920fabf4d811a777fa2a0eeb60b4dea8c30195 100644 (file)
@@ -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);
index 67df9cb2b90a9c40a984dcaae3e592d98e171046..a0af1b4b505c46b6c9366f9b1170e8353abfc50e 100644 (file)
@@ -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;
 
index 01e4d73839e7e59b61a17d578e49f35aa48ab808..169569ac980c72930a502451cec7ae2df0a465fe 100644 (file)
   "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")
 
 (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
 ;;
    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"))])]
+  ""
+  "")
 \f
 ;; ::::::::::::::::::::
 ;; ::