remove unused files
[platform/upstream/gcc48.git] / gcc / ira-lives.c
index f639e12..31635dd 100644 (file)
@@ -1,6 +1,5 @@
 /* IRA processing allocno lives to build allocno live ranges.
-   Copyright (C) 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2006-2013 Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
 This file is part of GCC.
@@ -192,7 +191,7 @@ inc_register_pressure (enum reg_class pclass, int n)
        continue;
       curr_reg_pressure[cl] += n;
       if (high_pressure_start_point[cl] < 0
-         && (curr_reg_pressure[cl] > ira_available_class_regs[cl]))
+         && (curr_reg_pressure[cl] > ira_class_hard_regs_num[cl]))
        high_pressure_start_point[cl] = curr_point;
       if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl])
        curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl];
@@ -221,7 +220,7 @@ dec_register_pressure (enum reg_class pclass, int nregs)
       curr_reg_pressure[cl] -= nregs;
       ira_assert (curr_reg_pressure[cl] >= 0);
       if (high_pressure_start_point[cl] >= 0
-         && curr_reg_pressure[cl] <= ira_available_class_regs[cl])
+         && curr_reg_pressure[cl] <= ira_class_hard_regs_num[cl])
        set_p = true;
     }
   if (set_p)
@@ -235,12 +234,30 @@ dec_register_pressure (enum reg_class pclass, int nregs)
          if (! ira_reg_pressure_class_p[cl])
            continue;
          if (high_pressure_start_point[cl] >= 0
-             && curr_reg_pressure[cl] <= ira_available_class_regs[cl])
+             && curr_reg_pressure[cl] <= ira_class_hard_regs_num[cl])
            high_pressure_start_point[cl] = -1;
        }
     }
 }
 
+/* Determine from the objects_live bitmap whether REGNO is currently live,
+   and occupies only one object.  Return false if we have no information.  */
+static bool
+pseudo_regno_single_word_and_live_p (int regno)
+{
+  ira_allocno_t a = ira_curr_regno_allocno_map[regno];
+  ira_object_t obj;
+
+  if (a == NULL)
+    return false;
+  if (ALLOCNO_NUM_OBJECTS (a) > 1)
+    return false;
+
+  obj = ALLOCNO_OBJECT (a, 0);
+
+  return sparseset_bit_p (objects_live, OBJECT_CONFLICT_ID (obj));
+}
+
 /* Mark the pseudo register REGNO as live.  Update all information about
    live ranges and register pressure.  */
 static void
@@ -510,7 +527,7 @@ mark_ref_dead (df_ref def)
 
 /* If REG is a pseudo or a subreg of it, and the class of its allocno
    intersects CL, make a conflict with pseudo DREG.  ORIG_DREG is the
-   rtx actually accessed, it may be indentical to DREG or a subreg of it.
+   rtx actually accessed, it may be identical to DREG or a subreg of it.
    Advance the current program point before making the conflict if
    ADVANCE_P.  Return TRUE if we will need to advance the current
    program point.  */
@@ -544,7 +561,7 @@ make_pseudo_conflict (rtx reg, enum reg_class cl, rtx dreg, rtx orig_dreg,
 
 /* Check and make if necessary conflicts for pseudo DREG of class
    DEF_CL of the current insn with input operand USE of class USE_CL.
-   ORIG_DREG is the rtx actually accessed, it may be indentical to
+   ORIG_DREG is the rtx actually accessed, it may be identical to
    DREG or a subreg of it.  Advance the current program point before
    making the conflict if ADVANCE_P.  Return TRUE if we will need to
    advance the current program point.  */
@@ -761,23 +778,16 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const)
          break;
 
        case 'n':
-         if (CONST_INT_P (op)
-             || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
-             || (equiv_const != NULL_RTX
-                 && (CONST_INT_P (equiv_const)
-                     || (GET_CODE (equiv_const) == CONST_DOUBLE
-                         && GET_MODE (equiv_const) == VOIDmode))))
+         if (CONST_SCALAR_INT_P (op)
+             || (equiv_const != NULL_RTX && CONST_SCALAR_INT_P (equiv_const)))
            return NO_REGS;
          break;
 
        case 's':
-         if ((CONSTANT_P (op) && !CONST_INT_P (op)
-              && (GET_CODE (op) != CONST_DOUBLE || GET_MODE (op) != VOIDmode))
+         if ((CONSTANT_P (op) && !CONST_SCALAR_INT_P (op))
              || (equiv_const != NULL_RTX
                  && CONSTANT_P (equiv_const)
-                 && !CONST_INT_P (equiv_const)
-                 && (GET_CODE (equiv_const) != CONST_DOUBLE
-                     || GET_MODE (equiv_const) != VOIDmode)))
+                 && !CONST_SCALAR_INT_P (equiv_const)))
            return NO_REGS;
          break;
 
@@ -800,11 +810,11 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const)
 
        case 'E':
        case 'F':
-         if (GET_CODE (op) == CONST_DOUBLE
+         if (CONST_DOUBLE_AS_FLOAT_P (op) 
              || (GET_CODE (op) == CONST_VECTOR
                  && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT)
              || (equiv_const != NULL_RTX
-                 && (GET_CODE (equiv_const) == CONST_DOUBLE
+                 && (CONST_DOUBLE_AS_FLOAT_P (equiv_const)
                      || (GET_CODE (equiv_const) == CONST_VECTOR
                          && (GET_MODE_CLASS (GET_MODE (equiv_const))
                              == MODE_VECTOR_FLOAT)))))
@@ -813,10 +823,10 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const)
 
        case 'G':
        case 'H':
-         if ((GET_CODE (op) == CONST_DOUBLE
+         if ((CONST_DOUBLE_AS_FLOAT_P (op) 
               && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, constraints))
              || (equiv_const != NULL_RTX
-                 && GET_CODE (equiv_const) == CONST_DOUBLE
+                 && CONST_DOUBLE_AS_FLOAT_P (equiv_const) 
                  && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (equiv_const,
                                                       c, constraints)))
            return NO_REGS;
@@ -832,9 +842,10 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const)
          next_cl = (c == 'r'
                     ? GENERAL_REGS
                     : REG_CLASS_FROM_CONSTRAINT (c, constraints));
-         if ((cl != NO_REGS && next_cl != cl)
-             || (ira_available_class_regs[next_cl]
-                 > ira_reg_class_max_nregs[next_cl][GET_MODE (op)]))
+         if (cl == NO_REGS
+             ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+             : (ira_class_singleton[cl][GET_MODE (op)]
+                != ira_class_singleton[next_cl][GET_MODE (op)]))
            return NO_REGS;
          cl = next_cl;
          break;
@@ -844,10 +855,10 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const)
          next_cl
            = single_reg_class (recog_data.constraints[c - '0'],
                                recog_data.operand[c - '0'], NULL_RTX);
-         if ((cl != NO_REGS && next_cl != cl)
-             || next_cl == NO_REGS
-             || (ira_available_class_regs[next_cl]
-                 > ira_reg_class_max_nregs[next_cl][GET_MODE (op)]))
+         if (cl == NO_REGS
+             ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+             : (ira_class_singleton[cl][GET_MODE (op)]
+                != ira_class_singleton[next_cl][GET_MODE (op)]))
            return NO_REGS;
          cl = next_cl;
          break;
@@ -922,13 +933,14 @@ ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set)
                  cl = (c == 'r'
                        ? GENERAL_REGS
                        : REG_CLASS_FROM_CONSTRAINT (c, p));
-                 if (cl != NO_REGS
+                 if (cl != NO_REGS)
+                   {
                      /* There is no register pressure problem if all of the
                         regs in this class are fixed.  */
-                     && ira_available_class_regs[cl] != 0
-                     && (ira_available_class_regs[cl]
-                         <= ira_reg_class_max_nregs[cl][mode]))
-                   IOR_HARD_REG_SET (*set, reg_class_contents[cl]);
+                     int regno = ira_class_singleton[cl][mode];
+                     if (regno >= 0)
+                       add_to_hard_reg_set (set, mode, regno);
+                   }
                  break;
                }
        }
@@ -972,8 +984,7 @@ process_single_reg_class_operands (bool in_p, int freq)
 
          operand_a = ira_curr_regno_allocno_map[regno];
          aclass = ALLOCNO_CLASS (operand_a);
-         if (ira_class_subset_p[cl][aclass]
-             && ira_class_hard_regs_num[cl] != 0)
+         if (ira_class_subset_p[cl][aclass])
            {
              /* View the desired allocation of OPERAND as:
 
@@ -987,7 +998,8 @@ process_single_reg_class_operands (bool in_p, int freq)
              HOST_WIDE_INT offset;
 
              xmode = recog_data.operand_mode[i];
-             xregno = ira_class_hard_regs[cl][0];
+             xregno = ira_class_singleton[cl][xmode];
+             gcc_assert (xregno >= 0);
              ymode = ALLOCNO_MODE (operand_a);
              offset = subreg_lowpart_offset (ymode, xmode);
              yregno = simplify_subreg_regno (xregno, xmode, offset, ymode);
@@ -1043,6 +1055,67 @@ bb_has_abnormal_call_pred (basic_block bb)
   return false;
 }
 
+/* Look through the CALL_INSN_FUNCTION_USAGE of a call insn INSN, and see if
+   we find a SET rtx that we can use to deduce that a register can be cheaply
+   caller-saved.  Return such a register, or NULL_RTX if none is found.  */
+static rtx
+find_call_crossed_cheap_reg (rtx insn)
+{
+  rtx cheap_reg = NULL_RTX;
+  rtx exp = CALL_INSN_FUNCTION_USAGE (insn);
+
+  while (exp != NULL)
+    {
+      rtx x = XEXP (exp, 0);
+      if (GET_CODE (x) == SET)
+       {
+         exp = x;
+         break;
+       }
+      exp = XEXP (exp, 1);
+    }
+  if (exp != NULL)
+    {
+      basic_block bb = BLOCK_FOR_INSN (insn);
+      rtx reg = SET_SRC (exp);
+      rtx prev = PREV_INSN (insn);
+      while (prev && !(INSN_P (prev)
+                      && BLOCK_FOR_INSN (prev) != bb))
+       {
+         if (NONDEBUG_INSN_P (prev))
+           {
+             rtx set = single_set (prev);
+
+             if (set && rtx_equal_p (SET_DEST (set), reg))
+               {
+                 rtx src = SET_SRC (set);
+                 if (!REG_P (src) || HARD_REGISTER_P (src)
+                     || !pseudo_regno_single_word_and_live_p (REGNO (src)))
+                   break;
+                 if (!modified_between_p (src, prev, insn))
+                   cheap_reg = src;
+                 break;
+               }
+             if (set && rtx_equal_p (SET_SRC (set), reg))
+               {
+                 rtx dest = SET_DEST (set);
+                 if (!REG_P (dest) || HARD_REGISTER_P (dest)
+                     || !pseudo_regno_single_word_and_live_p (REGNO (dest)))
+                   break;
+                 if (!modified_between_p (dest, prev, insn))
+                   cheap_reg = dest;
+                 break;
+               }
+
+             if (reg_overlap_mentioned_p (reg, PATTERN (prev)))
+               break;
+           }
+         prev = PREV_INSN (prev);
+       }
+    }
+  return cheap_reg;
+}  
+
 /* Process insns of the basic block given by its LOOP_TREE_NODE to
    update allocno live ranges, allocno hard register conflicts,
    intersected calls, and register pressure info for allocnos for the
@@ -1068,7 +1141,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
          high_pressure_start_point[ira_pressure_classes[i]] = -1;
        }
       curr_bb_node = loop_tree_node;
-      reg_live_out = DF_LR_OUT (bb);
+      reg_live_out = df_get_live_out (bb);
       sparseset_clear (objects_live);
       REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out);
       AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset);
@@ -1091,7 +1164,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
                if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl])
                  curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl];
                ira_assert (curr_reg_pressure[cl]
-                           <= ira_available_class_regs[cl]);
+                           <= ira_class_hard_regs_num[cl]);
              }
          }
       EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
@@ -1185,6 +1258,13 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
 
          if (call_p)
            {
+             /* Try to find a SET in the CALL_INSN_FUNCTION_USAGE, and from
+                there, try to find a pseudo that is live across the call but
+                can be cheaply reconstructed from the return value.  */
+             rtx cheap_reg = find_call_crossed_cheap_reg (insn);
+             if (cheap_reg != NULL_RTX)
+               add_reg_note (insn, REG_RETURNED, cheap_reg);
+
              last_call_num++;
              sparseset_clear (allocnos_processed);
              /* The current set of live allocnos are live across the call.  */
@@ -1226,6 +1306,9 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
                  /* Mark it as saved at the next call.  */
                  allocno_saved_at_call[num] = last_call_num + 1;
                  ALLOCNO_CALLS_CROSSED_NUM (a)++;
+                 if (cheap_reg != NULL_RTX
+                     && ALLOCNO_REGNO (a) == (int) REGNO (cheap_reg))
+                   ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a)++;
                }
            }
 
@@ -1368,32 +1451,32 @@ remove_some_program_points_and_update_live_ranges (void)
   int *map;
   ira_object_t obj;
   ira_object_iterator oi;
-  live_range_t r;
+  live_range_t r, prev_r, next_r;
   sbitmap born_or_dead, born, dead;
   sbitmap_iterator sbi;
   bool born_p, dead_p, prev_born_p, prev_dead_p;
   
   born = sbitmap_alloc (ira_max_point);
   dead = sbitmap_alloc (ira_max_point);
-  sbitmap_zero (born);
-  sbitmap_zero (dead);
+  bitmap_clear (born);
+  bitmap_clear (dead);
   FOR_EACH_OBJECT (obj, oi)
     for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
       {
        ira_assert (r->start <= r->finish);
-       SET_BIT (born, r->start);
-       SET_BIT (dead, r->finish);
+       bitmap_set_bit (born, r->start);
+       bitmap_set_bit (dead, r->finish);
       }
 
   born_or_dead = sbitmap_alloc (ira_max_point);
-  sbitmap_a_or_b (born_or_dead, born, dead);
+  bitmap_ior (born_or_dead, born, dead);
   map = (int *) ira_allocate (sizeof (int) * ira_max_point);
   n = -1;
   prev_born_p = prev_dead_p = false;
-  EXECUTE_IF_SET_IN_SBITMAP (born_or_dead, 0, i, sbi)
+  EXECUTE_IF_SET_IN_BITMAP (born_or_dead, 0, i, sbi)
     {
-      born_p = TEST_BIT (born, i);
-      dead_p = TEST_BIT (dead, i);
+      born_p = bitmap_bit_p (born, i);
+      dead_p = bitmap_bit_p (dead, i);
       if ((prev_born_p && ! prev_dead_p && born_p && ! dead_p)
          || (prev_dead_p && ! prev_born_p && dead_p && ! born_p))
        map[i] = n;
@@ -1412,10 +1495,19 @@ remove_some_program_points_and_update_live_ranges (void)
   ira_max_point = n;
 
   FOR_EACH_OBJECT (obj, oi)
-    for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
+    for (r = OBJECT_LIVE_RANGES (obj), prev_r = NULL; r != NULL; r = next_r)
       {
+       next_r = r->next;
        r->start = map[r->start];
        r->finish = map[r->finish];
+       if (prev_r == NULL || prev_r->start > r->finish + 1)
+         {
+           prev_r = r;
+           continue;
+         }
+       prev_r->start = r->start;
+       prev_r->next = next_r;
+       ira_finish_live_range (r);
       }
 
   ira_free (map);