ia64.c (ia64_register_move_cost): Add mode arguemnt.
authorRichard Henderson <rth@redhat.com>
Thu, 23 Aug 2001 07:44:03 +0000 (00:44 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 23 Aug 2001 07:44:03 +0000 (00:44 -0700)
        * config/ia64/ia64.c (ia64_register_move_cost): Add mode arguemnt.
        Reorganize.  Handle ADDL like GR, add GR_AND_BR.  Handle TFmode.
        (ia64_secondary_reload_class): Need GR between AR/BR and anything.
        Need GR between FR and not GR_AND_FR.
        * config/ia64/ia64-protos.h (ia64_register_move_cost): Update.
        * config/ia64/ia64.h (reg_class): Add GR_AND_BR_REGS, move
        AR regs before GR regs.
        (REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update.
        (PREFERRED_RELOAD_CLASS): Tweak for reordered classes.
        (REGISTER_MOVE_COST): Update.
        (MEMORY_MOVE_COST): Add GR_AND_FR_REGS.

From-SVN: r45125

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

index eb088f362dd97f8fa6a7011c8933d67b9aa0aa9d..af192db17a450489e5d2445856586512867cd901 100644 (file)
@@ -1,3 +1,17 @@
+2001-08-23  Richard Henderson  <rth@redhat.com>
+
+       * config/ia64/ia64.c (ia64_register_move_cost): Add mode arguemnt.
+       Reorganize.  Handle ADDL like GR, add GR_AND_BR.  Handle TFmode.
+       (ia64_secondary_reload_class): Need GR between AR/BR and anything.
+       Need GR between FR and not GR_AND_FR.
+       * config/ia64/ia64-protos.h (ia64_register_move_cost): Update.
+       * config/ia64/ia64.h (reg_class): Add GR_AND_BR_REGS, move
+       AR regs before GR regs.
+       (REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update.
+       (PREFERRED_RELOAD_CLASS): Tweak for reordered classes.
+       (REGISTER_MOVE_COST): Update.
+       (MEMORY_MOVE_COST): Add GR_AND_FR_REGS.
+
 2001-08-23  Richard Henderson  <rth@redhat.com>
 
        * regclass.c (init_reg_sets_1): Don't assume cost 2 within
index 03d2952aa227f53a18c58be2b2f98f625546b447..fca7f35551a530159f73140fac65651b8a84e986 100644 (file)
@@ -119,7 +119,8 @@ extern void ia64_asm_output_external PARAMS((FILE *, tree, const char *));
 extern void ia64_encode_section_info PARAMS((tree));
 #endif /* TREE_CODE */
 
-extern int ia64_register_move_cost PARAMS((enum reg_class, enum reg_class));
+extern int ia64_register_move_cost PARAMS((enum machine_mode, enum reg_class,
+                                          enum reg_class));
 extern int ia64_epilogue_uses PARAMS((int));
 extern void emit_safe_across_calls PARAMS((FILE *));
 extern void ia64_init_builtins PARAMS((void));
index 5cba6245ef050a4b75654f7d90a99682deddd1ae..8b56dad350830d19d274f6ae9e621cf6ad4a03cb 100644 (file)
@@ -3551,45 +3551,73 @@ ia64_print_operand (file, x, code)
 }
 \f
 /* Calulate the cost of moving data from a register in class FROM to
-   one in class TO.  */
+   one in class TO, using MODE.  */
 
 int
-ia64_register_move_cost (from, to)
+ia64_register_move_cost (mode, from, to)
+     enum machine_mode mode;
      enum reg_class from, to;
 {
-  int from_hard, to_hard;
-  int from_gr, to_gr;
-  int from_fr, to_fr;
-  int from_pr, to_pr;
-
-  from_hard = (from == BR_REGS || from == AR_M_REGS || from == AR_I_REGS);
-  to_hard = (to == BR_REGS || to == AR_M_REGS || to == AR_I_REGS);
-  from_gr = (from == GENERAL_REGS);
-  to_gr = (to == GENERAL_REGS);
-  from_fr = (from == FR_REGS);
-  to_fr = (to == FR_REGS);
-  from_pr = (from == PR_REGS);
-  to_pr = (to == PR_REGS);
-
-  if (from_hard && to_hard)
-    return 8;
-  else if ((from_hard && !to_gr) || (!from_gr && to_hard))
-    return 6;
+  /* ADDL_REGS is the same as GR_REGS for movement purposes.  */
+  if (to == ADDL_REGS)
+    to = GR_REGS;
+  if (from == ADDL_REGS)
+    from = GR_REGS;
 
-  /* Moving between PR registers takes two insns.  */
-  else if (from_pr && to_pr)
-    return 3;
-  /* Moving between PR and anything but GR is impossible.  */
-  else if ((from_pr && !to_gr) || (!from_gr && to_pr))
-    return 6;
-
-  /* ??? Moving from FR<->GR must be more expensive than 2, so that we get
-     secondary memory reloads for TFmode moves.  Unfortunately, we don't
-     have the mode here, so we can't check that.  */
-  /* Moreover, we have to make this at least as high as MEMORY_MOVE_COST
-     to avoid spectacularly poor register class preferencing for TFmode.  */
-  else if (from_fr != to_fr)
-    return 5;
+  /* All costs are symmetric, so reduce cases by putting the
+     lower number class as the destination.  */
+  if (from < to)
+    {
+      enum reg_class tmp = to;
+      to = from, from = tmp;
+    }
+
+  /* Moving from FR<->GR in TFmode must be more expensive than 2,
+     so that we get secondary memory reloads.  Between FR_REGS,
+     we have to make this at least as expensive as MEMORY_MOVE_COST
+     to avoid spectacularly poor register class preferencing.  */
+  if (mode == TFmode)
+    {
+      if (to != GR_REGS || from != GR_REGS)
+        return MEMORY_MOVE_COST (mode, to, 0);
+      else
+       return 3;
+    }
+
+  switch (to)
+    {
+    case PR_REGS:
+      /* Moving between PR registers takes two insns.  */
+      if (from == PR_REGS)
+       return 3;
+      /* Moving between PR and anything but GR is impossible.  */
+      if (from != GR_REGS)
+       return MEMORY_MOVE_COST (mode, to, 0);
+      break;
+
+    case BR_REGS:
+      /* Moving between BR and anything but GR is impossible.  */
+      if (from != GR_REGS && from != GR_AND_BR_REGS)
+       return MEMORY_MOVE_COST (mode, to, 0);
+      break;
+
+    case AR_I_REGS:
+    case AR_M_REGS:
+      /* Moving between AR and anything but GR is impossible.  */
+      if (from != GR_REGS)
+       return MEMORY_MOVE_COST (mode, to, 0);
+      break;
+
+    case GR_REGS:
+    case FR_REGS:
+    case GR_AND_FR_REGS:
+    case GR_AND_BR_REGS:
+    case ALL_REGS:
+      break;
+
+    default:
+      abort ();
+    }
 
   return 2;
 }
@@ -3613,17 +3641,21 @@ ia64_secondary_reload_class (class, mode, x)
   switch (class)
     {
     case BR_REGS:
-      /* ??? This is required because of a bad gcse/cse/global interaction.
-        We end up with two pseudos with overlapping lifetimes both of which
-        are equiv to the same constant, and both which need to be in BR_REGS.
-        This results in a BR_REGS to BR_REGS copy which doesn't exist.  To
-        reproduce, return NO_REGS here, and compile divdi3 in libgcc2.c.
-        This seems to be a cse bug.  cse_basic_block_end changes depending
-        on the path length, which means the qty_first_reg check in
-        make_regs_eqv can give different answers at different times.  */
-      /* ??? At some point I'll probably need a reload_indi pattern to handle
-        this.  */
-      if (BR_REGNO_P (regno))
+    case AR_M_REGS:
+    case AR_I_REGS:
+      /* ??? BR<->BR register copies can happen due to a bad gcse/cse/global
+        interaction.  We end up with two pseudos with overlapping lifetimes
+        both of which are equiv to the same constant, and both which need
+        to be in BR_REGS.  This seems to be a cse bug.  cse_basic_block_end
+        changes depending on the path length, which means the qty_first_reg
+        check in make_regs_eqv can give different answers at different times.
+        At some point I'll probably need a reload_indi pattern to handle
+        this.
+
+        We can also get GR_AND_FR_REGS to BR_REGS/AR_REGS copies, where we
+        wound up with a FP register from GR_AND_FR_REGS.  Extend that to all
+        non-general registers for good measure.  */
+      if (regno >= 0 && ! GENERAL_REGNO_P (regno))
        return GR_REGS;
 
       /* This is needed if a pseudo used as a call_operand gets spilled to a
@@ -3633,6 +3665,10 @@ ia64_secondary_reload_class (class, mode, x)
       break;
 
     case FR_REGS:
+      /* Need to go through general regsters to get to other class regs.  */
+      if (regno >= 0 && ! (FR_REGNO_P (regno) || GENERAL_REGNO_P (regno)))
+       return GR_REGS;
       /* This can happen when a paradoxical subreg is an operand to the
         muldi3 pattern.  */
       /* ??? This shouldn't be necessary after instruction scheduling is
index ccd6df7fbaadbaf0ffc056997b84ad4520517ce1..737b1e7b597a0bd3d4bf1be293009458d4fb7660 100644 (file)
@@ -907,12 +907,13 @@ enum reg_class
   NO_REGS,
   PR_REGS,
   BR_REGS,
+  AR_M_REGS,
+  AR_I_REGS,
   ADDL_REGS,
   GR_REGS,
   FR_REGS,
+  GR_AND_BR_REGS,
   GR_AND_FR_REGS,
-  AR_M_REGS,
-  AR_I_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
 };
@@ -925,8 +926,9 @@ enum reg_class
 /* An initializer containing the names of the register classes as C string
    constants.  These names are used in writing some of the debugging dumps.  */
 #define REG_CLASS_NAMES \
-{ "NO_REGS", "PR_REGS", "BR_REGS", "ADDL_REGS", "GR_REGS", "FR_REGS", \
-  "GR_AND_FR_REGS", "AR_M_REGS", "AR_I_REGS", "ALL_REGS" }
+{ "NO_REGS", "PR_REGS", "BR_REGS", "AR_M_REGS", "AR_I_REGS", \
+  "ADDL_REGS", "GR_REGS", "FR_REGS", \
+  "GR_AND_BR_REGS", "GR_AND_FR_REGS", "ALL_REGS" }
 
 /* An initializer containing the contents of the register classes, as integers
    which are bit masks.  The Nth integer specifies the contents of class N.
@@ -946,6 +948,14 @@ enum reg_class
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
     0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
     0x00000000, 0x00000000, 0x00FF },                  \
+  /* AR_M_REGS.  */                                    \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
+    0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
+    0x00000000, 0x00000000, 0x0C00 },                  \
+  /* AR_I_REGS.  */                                    \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
+    0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
+    0x00000000, 0x00000000, 0x7000 },                  \
   /* ADDL_REGS.  */                                    \
   { 0x0000000F, 0x00000000, 0x00000000, 0x00000000,    \
     0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
@@ -958,18 +968,14 @@ enum reg_class
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
     0x00000000, 0x00000000, 0x0000 },                  \
+  /* GR_AND_BR_REGS.  */                               \
+  { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
+    0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
+    0x00000000, 0x00000000, 0x03FF },                  \
   /* GR_AND_FR_REGS.  */                               \
   { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
     0x00000000, 0x00000000, 0x0300 },                  \
-  /* AR_M_REGS.  */                                    \
-  { 0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
-    0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
-    0x00000000, 0x00000000, 0x0C00 },                  \
-  /* AR_I_REGS.  */                                    \
-  { 0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
-    0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
-    0x00000000, 0x00000000, 0x7000 },                  \
   /* ALL_REGS.  */                                     \
   { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
@@ -1044,7 +1050,8 @@ enum reg_class
 #define PREFERRED_RELOAD_CLASS(X, CLASS) \
   (CLASS == FR_REGS && GET_CODE (X) == MEM && MEM_VOLATILE_P (X) ? NO_REGS   \
    : CLASS == FR_REGS && GET_CODE (X) == CONST_DOUBLE ? NO_REGS                     \
-   : GET_RTX_CLASS (GET_CODE (X)) != 'o' && CLASS > GR_AND_FR_REGS ? NO_REGS \
+   : GET_RTX_CLASS (GET_CODE (X)) != 'o'                                    \
+     && (CLASS == AR_M_REGS || CLASS == AR_I_REGS) ? NO_REGS                \
    : CLASS)
 
 /* You should define this macro to indicate to the reload phase that it may
@@ -1882,15 +1889,15 @@ do {                                                                    \
 #define ADDRESS_COST(ADDRESS) 0
 
 /* A C expression for the cost of moving data from a register in class FROM to
-   one in class TO.  */
+   one in class TO, using MODE.  */
 
-#define REGISTER_MOVE_COST(MODE, FROM, TO) \
-  ia64_register_move_cost((FROM), (TO))
+#define REGISTER_MOVE_COST  ia64_register_move_cost
 
 /* A C expression for the cost of moving data of mode M between a
    register and memory.  */
 #define MEMORY_MOVE_COST(MODE,CLASS,IN) \
-  ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS ? 4 : 10)
+  ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS \
+   || (CLASS) == GR_AND_FR_REGS ? 4 : 10)
 
 /* A C expression for the cost of a branch instruction.  A value of 1 is the
    default; other values are interpreted relative to that.  Used by the