Flow fixes for cond_exec on ia64
authorBernd Schmidt <bernds@redhat.co.uk>
Tue, 19 Dec 2000 16:52:23 +0000 (16:52 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Tue, 19 Dec 2000 16:52:23 +0000 (16:52 +0000)
From-SVN: r38380

gcc/ChangeLog
gcc/flow.c

index 08b5a2d6e68f0a3ccac8c3e262ec76e24032539b..a5d3171b5c9c086e780fa43c994595631e4e296e 100644 (file)
@@ -1,3 +1,16 @@
+2000-12-19  Bernd Schmidt  <bernds@redhat.co.uk>
+
+       * flow.c (ior_reg_cond, nand_reg_cond, not_reg_cond): Rewrite
+       to use different representation.  All callers changed.
+       (and_reg_cond): Renamed from nand_reg_cond; caller changed.
+       (init_propagate_block_info): Don't test flags to determine
+       whether to compute conditional lifetimes.
+       Adjust code for new representation of conditional lifetimes.
+       (mark_regno_cond_dead): Similar adjustment.
+       (free_reg_cond_life_info): Similar adjustment.
+       (elim_reg_cond): New function.
+       (flush_reg_cond_1): Use it.
+
 2000-12-19  Catherine Moore  <clm@redhat.com>
 
        * reload1.c (reload_combine): Take multi-hard-regs into account
index 50c9a1e1e02da78c0d36e6f1125a398a5def8f6b..725f63fc8215e489e082ba30072991c18670eba2 100644 (file)
@@ -392,9 +392,10 @@ static void free_reg_cond_life_info        PARAMS ((splay_tree_value));
 static int flush_reg_cond_reg_1                PARAMS ((splay_tree_node, void *));
 static void flush_reg_cond_reg         PARAMS ((struct propagate_block_info *,
                                                 int));
-static rtx ior_reg_cond                        PARAMS ((rtx, rtx));
+static rtx elim_reg_cond               PARAMS ((rtx, unsigned int));
+static rtx ior_reg_cond                        PARAMS ((rtx, rtx, int));
 static rtx not_reg_cond                        PARAMS ((rtx));
-static rtx nand_reg_cond               PARAMS ((rtx, rtx));
+static rtx and_reg_cond                        PARAMS ((rtx, rtx, int));
 #endif
 #ifdef AUTO_INC_DEC
 static void attempt_auto_inc           PARAMS ((struct propagate_block_info *,
@@ -3894,8 +3895,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
   /* If this block ends in a conditional branch, for each register live
      from one side of the branch and not the other, record the register
      as conditionally dead.  */
-  if ((flags & (PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE))
-      && GET_CODE (bb->end) == JUMP_INSN
+  if (GET_CODE (bb->end) == JUMP_INSN
       && any_condjump_p (bb->end))
     {
       regset_head diff_head;
@@ -3969,7 +3969,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
                 cond = cond_false;
               else
                 cond = cond_true;
-              rcli->condition = alloc_EXPR_LIST (0, cond, NULL_RTX);
+              rcli->condition = cond;
 
               splay_tree_insert (pbi->reg_cond_dead, i,
                                  (splay_tree_value) rcli);
@@ -4898,7 +4898,7 @@ mark_regno_cond_dead (pbi, regno, cond)
             Record the current condition as the condition under
             which it is dead.  */
          rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
-         rcli->condition = alloc_EXPR_LIST (0, cond, NULL_RTX);
+         rcli->condition = cond;
          splay_tree_insert (pbi->reg_cond_dead, regno,
                             (splay_tree_value) rcli);
 
@@ -4913,7 +4913,7 @@ mark_regno_cond_dead (pbi, regno, cond)
             Add the new condition to the old.  */
          rcli = (struct reg_cond_life_info *) node->value;
          ncond = rcli->condition;
-         ncond = ior_reg_cond (ncond, cond);
+         ncond = ior_reg_cond (ncond, cond, 1);
 
          /* If the register is now unconditionally dead,
             remove the entry in the splay_tree.  */
@@ -4941,7 +4941,6 @@ free_reg_cond_life_info (value)
      splay_tree_value value;
 {
   struct reg_cond_life_info *rcli = (struct reg_cond_life_info *) value;
-  free_EXPR_LIST_list (&rcli->condition);
   free (rcli);
 }
 
@@ -4955,36 +4954,26 @@ flush_reg_cond_reg_1 (node, data)
   struct reg_cond_life_info *rcli;
   int *xdata = (int *) data;
   unsigned int regno = xdata[0];
-  rtx c, *prev;
 
   /* Don't need to search if last flushed value was farther on in
      the in-order traversal.  */
   if (xdata[1] >= (int) node->key)
     return 0;
-
+  
   /* Splice out portions of the expression that refer to regno.  */
   rcli = (struct reg_cond_life_info *) node->value;
-  c = *(prev = &rcli->condition);
-  while (c)
-    {
-      if (regno == REGNO (XEXP (XEXP (c, 0), 0)))
-       {
-         rtx next = XEXP (c, 1);
-         free_EXPR_LIST_node (c);
-         c = *prev = next;
-       }
-      else
-       c = *(prev = &XEXP (c, 1));
-    }
+  rcli->condition = elim_reg_cond (rcli->condition, regno);
 
-  /* If the entire condition is now NULL, signal the node to be removed.  */
-  if (! rcli->condition)
+  /* If the entire condition is now false, signal the node to be removed.  */
+  if (rcli->condition == const0_rtx)
     {
       xdata[1] = node->key;
       return -1;
     }
-  else
-    return 0;
+  else if (rcli->condition == const1_rtx)
+    abort ();
+
+  return 0;
 }
 
 /* Flush all (sub) expressions referring to REGNO from REG_COND_LIVE.  */
@@ -5005,47 +4994,90 @@ flush_reg_cond_reg (pbi, regno)
   CLEAR_REGNO_REG_SET (pbi->reg_cond_reg, regno);
 }
 
-/* Logical arithmetic on predicate conditions.  IOR, NOT and NAND.
-   We actually use EXPR_LIST to chain the sub-expressions together
-   instead of IOR because it's easier to manipulate and we have
-   the lists.c functions to reuse nodes.
-
-   Return a new rtl expression as appropriate.  */
+/* Logical arithmetic on predicate conditions.  IOR, NOT and AND.
+   For ior/and, the ADD flag determines whether we want to add the new
+   condition X to the old one unconditionally.  If it is zero, we will
+   only return a new expression if X allows us to simplify part of
+   OLD, otherwise we return OLD unchanged to the caller.
+   If ADD is nonzero, we will return a new condition in all cases.  The
+   toplevel caller of one of these functions should always pass 1 for
+   ADD.  */
 
 static rtx
-ior_reg_cond (old, x)
+ior_reg_cond (old, x, add)
      rtx old, x;
+     int add;
 {
-  enum rtx_code x_code;
-  rtx x_reg;
-  rtx c;
-
-  /* We expect these conditions to be of the form (eq reg 0).  */
-  x_code = GET_CODE (x);
-  if (GET_RTX_CLASS (x_code) != '<'
-      || GET_CODE (x_reg = XEXP (x, 0)) != REG
-      || XEXP (x, 1) != const0_rtx)
-    abort ();
+  rtx op0, op1;
 
-  /* Search the expression for an existing sub-expression of X_REG.  */
-  for (c = old; c; c = XEXP (c, 1))
+  switch (GET_CODE (old))
     {
-      rtx y = XEXP (c, 0);
-      if (REGNO (XEXP (y, 0)) == REGNO (x_reg))
+    case IOR:
+      op0 = ior_reg_cond (XEXP (old, 0), x, 0);
+      op1 = ior_reg_cond (XEXP (old, 1), x, 0);
+      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
        {
-         /* If we find X already present in OLD, we need do nothing.  */
-         if (GET_CODE (y) == x_code)
-           return old;
-
-         /* If we find X being a compliment of a condition in OLD,
-            then the entire condition is true.  */
-         if (GET_CODE (y) == reverse_condition (x_code))
+         if (op0 == const0_rtx)
+           return op1;
+         if (op1 == const0_rtx)
+           return op0;
+         if (op0 == const1_rtx || op1 == const1_rtx)
            return const1_rtx;
+         if (op0 == XEXP (old, 0))
+           op0 = gen_rtx_IOR (0, op0, x);
+         else
+           op1 = gen_rtx_IOR (0, op1, x);
+         return gen_rtx_IOR (0, op0, op1);
        }
-    }
+      if (! add)
+       return old;
+      return gen_rtx_IOR (0, old, x);
+
+    case AND:
+      op0 = ior_reg_cond (XEXP (old, 0), x, 0);
+      op1 = ior_reg_cond (XEXP (old, 1), x, 0);
+      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+       {
+         if (op0 == const1_rtx)
+           return op1;
+         if (op1 == const1_rtx)
+           return op0;
+         if (op0 == const0_rtx || op1 == const0_rtx)
+           return const0_rtx;
+         if (op0 == XEXP (old, 0))
+           op0 = gen_rtx_IOR (0, op0, x);
+         else
+           op1 = gen_rtx_IOR (0, op1, x);
+         return gen_rtx_AND (0, op0, op1);
+       }
+      if (! add)
+       return old;
+      return gen_rtx_IOR (0, old, x);
+
+    case NOT:
+      op0 = and_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
+      if (op0 != XEXP (old, 0))
+       return not_reg_cond (op0);
+      if (! add)
+       return old;
+      return gen_rtx_IOR (0, old, x);
+
+    case EQ:
+    case NE:
+      if ((GET_CODE (x) == EQ || GET_CODE (x) == NE)
+         && GET_CODE (x) != GET_CODE (old)
+         && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
+       return const1_rtx;
+      if (GET_CODE (x) == GET_CODE (old)
+         && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
+       return old;
+      if (! add)
+       return old;
+      return gen_rtx_IOR (0, old, x);
 
-  /* Otherwise just add to the chain.  */
-  return alloc_EXPR_LIST (0, x, old);
+    default:
+      abort ();
+    }
 }
 
 static rtx
@@ -5053,63 +5085,160 @@ not_reg_cond (x)
      rtx x;
 {
   enum rtx_code x_code;
-  rtx x_reg;
 
-  /* We expect these conditions to be of the form (eq reg 0).  */
+  if (x == const0_rtx)
+    return const1_rtx;
+  else if (x == const1_rtx)
+    return const0_rtx;
   x_code = GET_CODE (x);
-  if (GET_RTX_CLASS (x_code) != '<'
-      || GET_CODE (x_reg = XEXP (x, 0)) != REG
-      || XEXP (x, 1) != const0_rtx)
-    abort ();
+  if (x_code == NOT)
+    return XEXP (x, 0);
+  if (GET_RTX_CLASS (x_code) == '<'
+      && GET_CODE (XEXP (x, 0)) == REG)
+    {
+      if (XEXP (x, 1) != const0_rtx)
+       abort ();
 
-  return alloc_EXPR_LIST (0, gen_rtx_fmt_ee (reverse_condition (x_code),
-                                            VOIDmode, x_reg, const0_rtx),
-                         NULL_RTX);
+      return gen_rtx_fmt_ee (reverse_condition (x_code),
+                            VOIDmode, XEXP (x, 0), const0_rtx);
+    }
+  return gen_rtx_NOT (0, x);
 }
 
 static rtx
-nand_reg_cond (old, x)
+and_reg_cond (old, x, add)
      rtx old, x;
+     int add;
 {
-  enum rtx_code x_code;
-  rtx x_reg;
-  rtx c, *prev;
-
-  /* We expect these conditions to be of the form (eq reg 0).  */
-  x_code = GET_CODE (x);
-  if (GET_RTX_CLASS (x_code) != '<'
-      || GET_CODE (x_reg = XEXP (x, 0)) != REG
-      || XEXP (x, 1) != const0_rtx)
-    abort ();
+  rtx op0, op1;
 
-  /* Search the expression for an existing sub-expression of X_REG.  */
-
-  for (c = *(prev = &old); c; c = *(prev = &XEXP (c, 1)))
+  switch (GET_CODE (old))
     {
-      rtx y = XEXP (c, 0);
-      if (REGNO (XEXP (y, 0)) == REGNO (x_reg))
+    case IOR:
+      op0 = and_reg_cond (XEXP (old, 0), x, 0);
+      op1 = and_reg_cond (XEXP (old, 1), x, 0);
+      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
        {
-         /* If we find X already present in OLD, then we need to
-            splice it out.  */
-         if (GET_CODE (y) == x_code)
-           {
-             *prev = XEXP (c, 1);
-             free_EXPR_LIST_node (c);
-             return old ? old : const0_rtx;
-           }
-
-         /* If we find X being a compliment of a condition in OLD,
-            then we need do nothing.  */
-         if (GET_CODE (y) == reverse_condition (x_code))
-           return old;
+         if (op0 == const0_rtx)
+           return op1;
+         if (op1 == const0_rtx)
+           return op0;
+         if (op0 == const1_rtx || op1 == const1_rtx)
+           return const1_rtx;
+         if (op0 == XEXP (old, 0))
+           op0 = gen_rtx_AND (0, op0, x);
+         else
+           op1 = gen_rtx_AND (0, op1, x);
+         return gen_rtx_IOR (0, op0, op1);
        }
+      if (! add)
+       return old;
+      return gen_rtx_AND (0, old, x);
+
+    case AND:
+      op0 = and_reg_cond (XEXP (old, 0), x, 0);
+      op1 = and_reg_cond (XEXP (old, 1), x, 0);
+      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+       {
+         if (op0 == const1_rtx)
+           return op1;
+         if (op1 == const1_rtx)
+           return op0;
+         if (op0 == const0_rtx || op1 == const0_rtx)
+           return const0_rtx;
+         if (op0 == XEXP (old, 0))
+           op0 = gen_rtx_AND (0, op0, x);
+         else
+           op1 = gen_rtx_AND (0, op1, x);
+         return gen_rtx_AND (0, op0, op1);
+       }
+      if (! add)
+       return old;
+      return gen_rtx_AND (0, old, x);
+
+    case NOT:
+      op0 = ior_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
+      if (op0 != XEXP (old, 0))
+       return not_reg_cond (op0);
+      if (! add)
+       return old;
+      return gen_rtx_AND (0, old, x);
+
+    case EQ:
+    case NE:
+      if ((GET_CODE (x) == EQ || GET_CODE (x) == NE)
+         && GET_CODE (x) != GET_CODE (old)
+         && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
+       return const0_rtx;
+      if (GET_CODE (x) == GET_CODE (old)
+         && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
+       return old;
+      if (! add)
+       return old;
+      return gen_rtx_AND (0, old, x);
+
+    default:
+      abort ();
     }
+}
+
+/* Given a condition X, remove references to reg REGNO and return the
+   new condition.  The removal will be done so that all conditions
+   involving REGNO are considered to evaluate to false.  This function
+   is used when the value of REGNO changes.  */
 
-  /* Otherwise, by implication, the register in question is now live for
-     the inverse of the condition X.  */
-  return alloc_EXPR_LIST (0, gen_rtx_fmt_ee (reverse_condition (x_code),
-                                            VOIDmode, x_reg, const0_rtx),
-                         old);
+static rtx
+elim_reg_cond (x, regno)
+     rtx x;
+     unsigned int regno;
+{
+  rtx op0, op1;
+  switch (GET_CODE (x))
+    {
+    case AND:
+      op0 = elim_reg_cond (XEXP (x, 0), regno);
+      op1 = elim_reg_cond (XEXP (x, 1), regno);
+      if (op0 == const0_rtx || op1 == const0_rtx)
+       return const0_rtx;
+      if (op0 == const1_rtx)
+       return op1;
+      if (op1 == const1_rtx)
+       return op0;
+      if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
+       return x;
+      return gen_rtx_AND (0, op0, op1);
+
+    case IOR:
+      op0 = elim_reg_cond (XEXP (x, 0), regno);
+      op1 = elim_reg_cond (XEXP (x, 1), regno);
+      if (op0 == const1_rtx || op1 == const1_rtx)
+       return const1_rtx;
+      if (op0 == const0_rtx)
+       return op1;
+      if (op1 == const0_rtx)
+       return op0;
+      if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
+       return x;
+      return gen_rtx_IOR (0, op0, op1);
+
+    case NOT:
+      op0 = elim_reg_cond (XEXP (x, 0), regno);
+      if (op0 == const0_rtx)
+       return const1_rtx;
+      if (op0 == const1_rtx)
+       return const0_rtx;
+      if (op0 != XEXP (x, 0))
+       return not_reg_cond (op0);
+      return x;
+
+    case EQ:
+    case NE:
+      if (REGNO (XEXP (x, 0)) == regno)
+       return const0_rtx;
+      return x;
+    default:
+      abort ();
+    }
 }
 #endif /* HAVE_conditional_execution */
 \f
@@ -5513,7 +5642,7 @@ mark_used_reg (pbi, reg, cond, insn)
                 Subtract the new life cond from the old death cond.  */
              rcli = (struct reg_cond_life_info *) node->value;
              ncond = rcli->condition;
-             ncond = nand_reg_cond (ncond, cond);
+             ncond = and_reg_cond (ncond, not_reg_cond (cond), 1);
 
              /* If the register is now unconditionally live, remove the
                 entry in the splay_tree.  */