]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
split ssa-ranger into stmt-ranger and cfg related stuff move get_tree_range and have...
authorAndrew Macleod <amacleod@gcc.gnu.org>
Wed, 4 Sep 2019 11:42:20 +0000 (11:42 +0000)
committerAndrew Macleod <amacleod@gcc.gnu.org>
Wed, 4 Sep 2019 11:42:20 +0000 (11:42 +0000)
split ssa-ranger into stmt-ranger and cfg related stuff
move get_tree_range and have it return a ranger rather than a bool
remove range_of_expr for edges, just use range_on_edge

From-SVN: r275371

gcc/grange.cc
gcc/grange.h
gcc/ssa-range-cache.cc
gcc/ssa-range-gori.cc
gcc/ssa-range-gori.h
gcc/ssa-range.cc
gcc/ssa-range.h

index f700170b16eca790798a0997373aca79ff1fbbc1..65c1f897000eb7d60c4472297568fd90abe39e8f 100644 (file)
@@ -58,8 +58,56 @@ along with GCC; see the file COPYING3.  If not see
 // A table is indexed by tree-code which provides any neccessary code
 // for implementing the IL specific work. It is modelled after the range op
 // table where a class is implemented for a given tree code, and
-// auto-registered intohe table for use when it is encountered.
+// auto-registered into the table for use when it is encountered.
 
+// This function returns a range for tree node EXPR in R.  Return
+// false if ranges are not supported.
+
+irange
+get_tree_range (tree expr)
+{
+  tree type;
+  if (TYPE_P (expr))
+    type = expr;
+  else
+    type = TREE_TYPE (expr);
+
+  gcc_checking_assert (irange::supports_type_p (type));
+
+  switch (TREE_CODE (expr))
+    {
+      case INTEGER_CST:
+       // If we encounter an overflow, simply punt and drop to varying
+       // since we have no idea how it will be used.
+        if (!TREE_OVERFLOW_P (expr))
+         return irange (expr, expr);
+       break;
+
+      case SSA_NAME:
+        if (irange::supports_ssa_p (expr) && SSA_NAME_RANGE_INFO (expr)
+           && !POINTER_TYPE_P (type))
+         {
+           // Return a range from an SSA_NAME's available range.  
+           wide_int min, max;
+           enum value_range_kind kind = get_range_info (expr, &min, &max);
+           return irange (kind, type, min, max);
+         }
+       break;
+
+      case ADDR_EXPR:
+        {
+         // handle &var which can show up in phi arguments
+         bool ov;
+         if (tree_single_nonzero_warnv_p (expr, &ov))
+            return range_nonzero (type);
+         break;
+       }
+
+      default:
+        break;
+    }
+  return irange (type);
+}
 
 static gimple *
 calc_single_range (irange &r, gswitch *sw, edge e)
index a83db7c4e897b72f50a54116a798d8ad245ff492..fa115bec10c8553e05278957e7777d999b3f5e8e 100644 (file)
@@ -27,6 +27,15 @@ along with GCC; see the file COPYING3.  If not see
 extern gimple_stmt_iterator gsi_outgoing_range_stmt (basic_block bb);
 extern gimple *gimple_outgoing_range_stmt_p (basic_block bb);
 extern gimple *gimple_outgoing_edge_range_p (irange &r, edge e);
+extern irange get_tree_range (tree expr);
+
+static inline tree
+valid_range_ssa_p (tree exp)
+{
+  if (exp && TREE_CODE (exp) == SSA_NAME && irange::supports_ssa_p (exp))
+    return exp;
+  return NULL_TREE;
+}
 
 // Gimple statement which supports range_op operations.
 // This can map to gimple assign or cond statements, so quick access to the
index c7e364bbc8b1f163881dc2b5269fb42ce158cbe4..53af02bf03989c336cd56a735aa94fb4b7b5306c 100644 (file)
@@ -578,7 +578,7 @@ gori_cache::edge_range (irange &r, edge e, tree name)
        {
          // Try to pick up any known value first. 
          if (!m_globals.get_global_range (r, name))
-           r = range_from_ssa (name);
+           r = get_tree_range (name);
        }
     }
   else
index 334f349d3fab565d4c707734847ee9330eb576c8..8540fbab0e81b82fe7e14f183055a67a255fd6d5 100644 (file)
@@ -472,90 +472,17 @@ gori_map::dump(FILE *f)
     }
 }
 
-// Return a range from an SSA_NAME's available range.  If there is no
-// available range, build a range for its entire domain.
-
-irange
-range_from_ssa (tree ssa)
-{
-  tree type = TREE_TYPE (ssa);
-  gcc_checking_assert (irange::supports_type_p (type));
-  if (!SSA_NAME_RANGE_INFO (ssa) || POINTER_TYPE_P (type))
-    return irange (type);
-  wide_int min, max;
-  enum value_range_kind kind = get_range_info (ssa, &min, &max);
-  return irange (kind, type, min, max);
-}
-
-// This function returns a range for tree node EXPR in R.  Return
-// false if ranges are not supported.
-
-bool
-get_tree_range (irange &r, tree expr)
-{
-  tree type;
-  switch (TREE_CODE (expr))
-    {
-      case INTEGER_CST:
-        if (!TREE_OVERFLOW_P (expr))
-         r = irange (expr, expr);
-       else
-         // If we encounter an overflow, simply punt and drop to varying
-         // since we hvae no idea how it will be used.
-         r.set_varying (TREE_TYPE (expr));
-       return true;
-
-      case SSA_NAME:
-        if (irange::supports_ssa_p (expr))
-         {
-           r = range_from_ssa (expr);
-           return true;
-         }
-       break;
-
-      case ADDR_EXPR:
-        {
-         // handle &var which can show up in phi arguments
-         bool ov;
-         type = TREE_TYPE (expr);
-         if (irange::supports_type_p (type))
-           {
-             if (tree_single_nonzero_warnv_p (expr, &ov))
-               r = range_nonzero (type);
-             else
-               r.set_varying (type);
-             return true;
-           }
-         break;
-       }
-
-      default:
-       if (TYPE_P (expr))
-         type = expr;
-       else
-         type = TREE_TYPE (expr);
-       if (irange::supports_type_p (type))
-         {
-           // Set to range for this type.
-           r.set_varying (type);
-           return true;
-         }
-       break;
-    }
-  return false;
-}
-
 // Same but perform substitution of NAME with RANGE_OF_NAME if expr
 // happens to match it.
 
-static bool
-get_tree_range (irange &r, tree expr, tree name, irange *range_of_name)
+static irange
+get_tree_range (tree expr, tree name, irange *range_of_name)
 {
   if (expr != name || !range_of_name)
-    return get_tree_range (r, expr);
+    return get_tree_range (expr);
 
-  r = *range_of_name;
-  return true;
+  gcc_checking_assert (range_of_name != NULL);
+  return *range_of_name;
 }
 
 // Calculate the range for NAME if the lhs of statement S has the range LHS.
@@ -579,31 +506,32 @@ compute_operand_range_on_stmt (irange &r, grange_op *s, const irange &lhs,
          // The second parameter to a unary operation is the range for the type
          // of operand1, but if it can be reduced further, the results will
          // be better.  Start with what we know of the range of OP1.
-         if (get_tree_range (op1_range, op1, name, name_range))
-           return s->calc_op1_irange (r, lhs, op1_range);
-         else
-           return s->calc_op1_irange (r, lhs);
+         op1_range = get_tree_range (op1, name, name_range);
+         return s->calc_op1_irange (r, lhs, op1_range);
        }
       // If we need the second operand, get a value and evaluate.
-      if (get_tree_range (op2_range, op2, name, name_range))
-       if (s->calc_op1_irange (r, lhs, op2_range))
-         {
-           // If op1 also has a range, intersect the 2 ranges.
-           if (name_range)
-             r.intersect (*name_range);
-           return true;
-         }
+      op2_range = get_tree_range (op2, name, name_range);
+      if (s->calc_op1_irange (r, lhs, op2_range))
+       {
+         // If op1 also has a range, intersect the 2 ranges.
+         if (name_range)
+           r.intersect (*name_range);
+         return true;
+       }
       return false;
     }
 
-  if (op2 == name && get_tree_range (op1_range, op1, name, name_range))
-    if (s->calc_op2_irange (r, lhs, op1_range))
-      {
-       // If op2 also has a range, intersect the 2 ranges.
-       if (name_range)
-         r.intersect (*name_range);
-       return true;
-      }
+  if (op2 == name)
+    {
+      op1_range = get_tree_range (op1, name, name_range);
+      if (s->calc_op2_irange (r, lhs, op1_range))
+       {
+         // If op2 also has a range, intersect the 2 ranges.
+         if (name_range)
+           r.intersect (*name_range);
+         return true;
+       }
+    }
   return false;
 }
 
@@ -624,7 +552,7 @@ compute_operand_range_on_stmt (irange &r, gimple *s, const irange &lhs,
     {
       if (gimple_switch_index (as_a<gswitch *>(s)) == name)
         {
-         gcc_assert (get_tree_range (r, name, name, name_range));
+         r = get_tree_range (name, name, name_range);
          r.intersect (lhs);
          return true;
        }
@@ -933,7 +861,7 @@ gori_compute::compute_logical_operands (irange &r, grange_op *s,
   else
     {
       // Otherwise just get the value for name in operand 1 position
-      gcc_assert (get_tree_range (op1_true, name, name, name_range));
+      op1_true = get_tree_range (name, name, name_range);
       op1_false = op1_true;
     }
 
@@ -950,7 +878,7 @@ gori_compute::compute_logical_operands (irange &r, grange_op *s,
       else
        {
          // Otherwise just get the value for name in operand 2 position
-         gcc_assert (get_tree_range (op2_true, name, name, name_range));
+         op2_true = get_tree_range (name, name, name_range);
          op2_false = op2_true; 
        }
     }
@@ -978,8 +906,7 @@ gori_compute::compute_operand1_range (irange &r, grange_op *s,
   tree op2 = s->operand2 ();
 
   // Determine a known range for operand1 ().
-  if (!get_tree_range (op1_range, op1, name, name_range))
-    return false;
+  op1_range = get_tree_range (op1, name, name_range);
 
   // Now calcuated the operand and put that result in r.
   if (!op2)
@@ -992,8 +919,7 @@ gori_compute::compute_operand1_range (irange &r, grange_op *s,
     }
   else
     {
-      if (!get_tree_range (op2_range, op2, name, name_range))
-       return false;
+      op2_range = get_tree_range (op2, name, name_range);
       if (!s->calc_op1_irange (r, lhs, op2_range))
        return false;
     }
@@ -1022,16 +948,14 @@ gori_compute::compute_operand2_range (irange &r, grange_op *s,
   tree op2 = s->operand2 ();
 
   // Get a range for op1.
-  if (!get_tree_range (op1_range, op1, name, name_range))
-    return false;
+  op1_range = get_tree_range (op1, name, name_range);
 
   // calculate the range for op2 based on lhs and op1.
   if (!s->calc_op2_irange (op2_range, lhs, op1_range))
     return false;
 
   // Also pick up what is known about op2's range at this point
-  if (!get_tree_range (r, op2, name, name_range))
-    return false;
+  r = get_tree_range (op2, name, name_range);
 
   // And intersect it with the calculated result.
   op2_range.intersect (r);
@@ -1166,7 +1090,7 @@ bool
 gori_compute::range_from_import (irange &r, tree name, irange &import_range)
 {
   irange r1, r2;
-  bool res;
+  bool res = true;
   tree import = terminal_name (name);
 
   gcc_checking_assert
@@ -1199,15 +1123,12 @@ gori_compute::range_from_import (irange &r, tree name, irange &import_range)
   if (valid_range_ssa_p (op1))
     {
       if (op1 == import)
-        {
-         res = true;
-         r1 = import_range;
-       }
+       r1 = import_range;
       else
        res = range_from_import (r1, op1, import_range);
     }
   else
-    res = get_tree_range (r1, op1);
+    r1 = get_tree_range (op1);
 
   if (!res)
     return false;
@@ -1218,15 +1139,12 @@ gori_compute::range_from_import (irange &r, tree name, irange &import_range)
   if (valid_range_ssa_p (op2))
     {
       if (op2 == import)
-        {
-         res = true;
-         r2 = import_range;
-       }
+       r2 = import_range;
       else
        res = range_from_import (r2, op2, import_range);
     }
   else
-    res = get_tree_range (r2, op2);
+    r2 = get_tree_range (op2);
 
   if (res)
     return s->fold (r, r1, r2);
index 91978b4ae2ed450b504e790651eda7f22ae59c85..715d58977c554e3952673cd950fd2e47178bab23 100644 (file)
@@ -186,15 +186,4 @@ private:
   irange m_bool_one;            /* Boolean true cached.  */
 };
 
-bool get_tree_range (irange &r, tree expr);
-irange range_from_ssa (tree ssa);
-
-static inline tree
-valid_range_ssa_p (tree exp)
-{
-  if (exp && TREE_CODE (exp) == SSA_NAME && irange::supports_ssa_p (exp))
-    return exp;
-  return NULL_TREE;
-}
-
 #endif // GCC_SSA_RANGE_GORI_H
index 7137194202e077a5b7514782d0b4fc569fced3d8..a498329824f8aaaa854c2cada9d4fdee09ae6a5b 100644 (file)
@@ -55,13 +55,13 @@ along with GCC; see the file COPYING3.  If not see
 
 // Initialize a ranger.
 
-ssa_ranger::ssa_ranger ()
+stmt_ranger::stmt_ranger ()
 {
 }
 
 // Destruct a ranger.
 
-ssa_ranger::~ssa_ranger ()
+stmt_ranger::~stmt_ranger ()
 {
 }
 
@@ -70,76 +70,19 @@ ssa_ranger::~ssa_ranger ()
 // Return false if ranges are not supported.
 
 bool
-ssa_ranger::range_of_expr (irange &r, tree expr, gimple *s ATTRIBUTE_UNUSED)
-{
-  return get_tree_range (r, expr);
-}
-
-// Determine a range for OP on edge E, returning the result in R.
-
-bool
-ssa_ranger::range_of_expr (irange&r, tree op, edge e)
-{
-  if (!irange::supports_p (op))
-     return false;
-  if (valid_range_ssa_p (op))
-    {
-      range_on_edge (r, e, op);
-      return true;
-    }
-  // If it is not an SSA_NAME, just get the basic range.
-  return get_tree_range (r, op);
-}
-
-// Calculate a range on edge E and return it in R.  Try to evaluate a range
-// for NAME on this edge.  Return FALSE if this is either not a control edge
-// or NAME is not defined by this edge.
-
-bool
-ssa_ranger::outgoing_edge_range_p (irange &r, edge e, tree name,
-                                   irange *name_range)
-{
-  irange lhs;
-
-  gcc_checking_assert (valid_range_ssa_p (name));
-  // Determine if there is an outgoing edge.
-  gimple *s = gimple_outgoing_edge_range_p (lhs, e);
-
-  // If there is no outgoing stmt, there is no range produced.
-  if (!s)
-    return false;
-
-  // Otherwise use the outgoing edge as a LHS and try to calculate a range.
-  return compute_operand_range_on_stmt (r, s, lhs, name, name_range);
-}
-
-// Calculate a range for NAME on edge E and return it in R.  
-// if NAME is a PHI node at the dest of E, get the argument result.
-// Return false if no range can be determined.
-
-void
-ssa_ranger::range_on_edge (irange &r, edge e, tree name)
+stmt_ranger::range_of_expr (irange &r, tree expr, gimple *s ATTRIBUTE_UNUSED)
 {
-  irange edge_range;
-  gcc_checking_assert (valid_range_ssa_p (name));
-
-  range_on_exit (r, e->src, name);
-  gcc_checking_assert  (r.undefined_p ()
-                       || types_compatible_p (r.type(), TREE_TYPE (name)));
-
-  // Check to see if NAME is defined on edge e.
-  if (outgoing_edge_range_p (edge_range, e, name, &r))
-    r = edge_range;
+  r = get_tree_range (expr);
+  return true;
 }
 
-
 // Calculate a range for statement S and return it in R. If NAME is provided it
 // represents the SSA_NAME on the LHS of the statement. It is only required
 // if there is more than one lhs/output.  If a range cannot
 // be calculated, return false.
 
 bool
-ssa_ranger::range_of_stmt (irange &r, gimple *s, tree name)
+stmt_ranger::range_of_stmt (irange &r, gimple *s, tree name)
 {
   bool res = false;
   // If name is specified, make sure it a LHS of S.
@@ -165,7 +108,7 @@ ssa_ranger::range_of_stmt (irange &r, gimple *s, tree name)
          return true;
        }
       // We don't understand the stmt, so return the global range.
-      r = range_from_ssa (name);
+      r = get_tree_range (name);
       return true;
     }
   if (res)
@@ -184,7 +127,7 @@ ssa_ranger::range_of_stmt (irange &r, gimple *s, tree name)
 // up. If a range cannot be calculated on this statement, return false.
 
 bool
-ssa_ranger::range_of_stmt_with_range (irange &r, gimple *s, tree name,
+stmt_ranger::range_of_stmt_with_range (irange &r, gimple *s, tree name,
                                       const irange &name_range)
 {
   if (is_a<grange_op *> (s))
@@ -199,65 +142,13 @@ ssa_ranger::range_of_stmt_with_range (irange &r, gimple *s, tree name,
   return false;
 }
 
-// Return the range for NAME on entry to basic block BB in R.  
-// Return false if no range can be calculated.
-// Calculation is performed by unioning all the ranges on incoming edges.
-
-void
-ssa_ranger::range_on_entry (irange &r, basic_block bb, tree name)
-{
-  edge_iterator ei;
-  edge e;
-  tree type = TREE_TYPE (name);
-  irange pred_range;
-
-  gcc_checking_assert (irange::supports_type_p (type));
-
-  // Start with an empty range.
-  r.set_undefined ();
-
-  gcc_checking_assert (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun));
-
-  // Visit each predecessor to resolve them.
-  FOR_EACH_EDGE (e, ei, bb->preds)
-    {
-      range_on_edge (pred_range, e, name);
-      r.union_ (pred_range);
-      // If varying is reach, stop processing.
-      if (r.varying_p ())
-        break;
-    }
-}
-
-
-// Calculate the range for NAME at the end of block BB and return it in R.
-// Return false if no range can be calculated.
-
-void
-ssa_ranger::range_on_exit (irange &r, basic_block bb, tree name)
-{
-  // on-exit from the exit block?
-  gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
-
-  gimple *s = last_stmt (bb);
-  // If there is no statement in the block and this isnt the entry block,
-  // go get the range_on_entry for this block.
-  // For the entry block, a NULL stmt will return the global value for NAME.
-  if (!s && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun))
-    range_on_entry (r, bb, name);
-  else
-    gcc_assert (range_of_expr (r, name, s));
-  gcc_checking_assert (r.undefined_p ()
-                      || types_compatible_p (r.type(), TREE_TYPE (name)));
-}
-
 // Calculate a range for range_op statement S given RANGE1 and RANGE2 and 
 // return it in R.  If a range cannot be calculated, return false.  
 // If valid is false, then one or more of the ranges are invalid, and
 // return false.
 
 inline bool
-ssa_ranger::range_of_range_op_core (irange &r, grange_op *s, bool valid,
+stmt_ranger::range_of_range_op_core (irange &r, grange_op *s, bool valid,
                                     irange &range1, irange &range2)
 {
   if (valid)
@@ -278,7 +169,7 @@ ssa_ranger::range_of_range_op_core (irange &r, grange_op *s, bool valid,
 // cannot be calculated, return false.  
 
 bool
-ssa_ranger::range_of_range_op (irange &r, grange_op *s)
+stmt_ranger::range_of_range_op (irange &r, grange_op *s)
 {
   irange range1, range2;
   bool res = true;
@@ -302,7 +193,7 @@ ssa_ranger::range_of_range_op (irange &r, grange_op *s)
 // cannot be calculated, return false.  
 
 bool
-ssa_ranger::range_of_range_op (irange &r, grange_op *s, tree name,
+stmt_ranger::range_of_range_op (irange &r, grange_op *s, tree name,
                              const irange &name_range)
 {
   irange range1, range2;
@@ -335,7 +226,7 @@ ssa_ranger::range_of_range_op (irange &r, grange_op *s, tree name,
 // cannot be calculated, return false.  
 
 bool
-ssa_ranger::range_of_range_op (irange &r, grange_op *s, gimple *eval_from)
+stmt_ranger::range_of_range_op (irange &r, grange_op *s, gimple *eval_from)
 {
   irange range1, range2;
   bool res = true;
@@ -355,30 +246,6 @@ ssa_ranger::range_of_range_op (irange &r, grange_op *s, gimple *eval_from)
 }
 
 
-// Calculate a range for range_op statement S and return it in R.  Evaluate
-// the statement as if it were on edge EVAL_ON.  If a range cannot be
-// calculated, return false.  
-
-bool
-ssa_ranger::range_of_range_op (irange &r, grange_op *s, edge eval_on)
-{
-  irange range1, range2;
-  bool res = true;
-  gcc_checking_assert (irange::supports_type_p (gimple_expr_type (s)));
-
-  tree op1 = s->operand1 ();
-  tree op2 = s->operand2 ();
-
-  // Calculate a range for operand 1.
-  res = range_of_expr (range1, op1, eval_on);
-
-  // Calculate a result for op2 if it is needed.
-  if (res && op2)
-    res = range_of_expr (range2, op2, eval_on);
-
-  return range_of_range_op_core (r, s, res, range1, range2);
-}
-
 // Calculate a range for phi statement S and return it in R. 
 // If NAME is non-null, replace any occurences of NAME in arguments with
 // NAME_RANGE.
@@ -388,7 +255,7 @@ ssa_ranger::range_of_range_op (irange &r, grange_op *s, edge eval_on)
 // If a range cannot be calculated, return false.  
 
 bool
-ssa_ranger::range_of_phi (irange &r, gphi *phi, tree name,
+stmt_ranger::range_of_phi (irange &r, gphi *phi, tree name,
                           const irange *name_range, gimple *eval_from,
                           edge on_edge)
 {
@@ -412,10 +279,7 @@ ssa_ranger::range_of_phi (irange &r, gphi *phi, tree name,
       if (name == arg)
         arg_range = *name_range;
       else if (valid_range_ssa_p (arg) && !eval_from)
-      // Try to find a range from the edge.  If that fails, return varying.
-       range_on_edge (arg_range, e, arg);
-      else
-       gcc_assert (range_of_expr (arg_range, arg, eval_from));
+      gcc_assert (range_of_expr (arg_range, arg, eval_from));
 
       r.union_ (arg_range);
       // Once the value reaches varying, stop looking.
@@ -435,7 +299,7 @@ ssa_ranger::range_of_phi (irange &r, gphi *phi, tree name,
 // If a range cannot be calculated, return false.  
 
 bool
-ssa_ranger::range_of_call (irange &r, gcall *call, tree name ATTRIBUTE_UNUSED,
+stmt_ranger::range_of_call (irange &r, gcall *call, tree name ATTRIBUTE_UNUSED,
                            const irange *name_range ATTRIBUTE_UNUSED,
                            gimple *eval_from ATTRIBUTE_UNUSED,
                            edge on_edge ATTRIBUTE_UNUSED)
@@ -453,12 +317,18 @@ ssa_ranger::range_of_call (irange &r, gcall *call, tree name ATTRIBUTE_UNUSED,
   return true;
 }
 
-// Calculate a range for COND_EXPR statement S and return it in R.  Evaluate 
-// the stateemnt as if it occured on edge ON_EDGE.
-// If a range cannot be calculated, return false. 
+
+
+// Calculate a range for COND_EXPR statement S and return it in R.  
+// If NAME is non-null, replace any occurences of NAME in arguments with
+// NAME_RANGE.
+// If EVAL_FOM is non-null, evaluate the COND_EXPR as if it occured right 
+// before EVAL_FROM.
+// If a range cannot be calculated, return false.  
 
 bool
-ssa_ranger::range_of_cond_expr  (irange &r, gassign *s, edge on_edge)
+stmt_ranger::range_of_cond_expr  (irange &r, gassign *s, tree name,
+                                 const irange *name_range, gimple *eval_from)
 {
   irange cond_range, range1, range2;
   tree cond = gimple_assign_rhs1 (s);
@@ -471,9 +341,23 @@ ssa_ranger::range_of_cond_expr  (irange &r, gassign *s, edge on_edge)
   if (!irange::supports_type_p (TREE_TYPE (op1)))
     return false;
 
-  gcc_assert (range_of_expr (cond_range, cond, on_edge));
-  gcc_assert (range_of_expr (range1, op1, on_edge));
-  gcc_assert (range_of_expr (range2, op2, on_edge));
+  if (!eval_from)
+    eval_from = s;
+
+  if (name == cond)
+    cond_range = *name_range;
+  else
+    gcc_assert (range_of_expr (cond_range, cond, eval_from));
+
+  if (name == op1)
+    range1 = *name_range;
+  else
+    gcc_assert (range_of_expr (range1, op1, eval_from));
+
+  if (name == op2)
+    range2 = *name_range;
+  else
+    gcc_assert (range_of_expr (range2, op2, eval_from));
 
   if (cond_range.singleton_p ())
     {
@@ -488,16 +372,188 @@ ssa_ranger::range_of_cond_expr  (irange &r, gassign *s, edge on_edge)
   return true;
 }
 
-// Calculate a range for COND_EXPR statement S and return it in R.  
-// If NAME is non-null, replace any occurences of NAME in arguments with
-// NAME_RANGE.
-// If EVAL_FOM is non-null, evaluate the COND_EXPR as if it occured right 
-// before EVAL_FROM.
-// If a range cannot be calculated, return false.  
+
+// Initialize a CFG ranger.
+
+ssa_ranger::ssa_ranger ()
+{
+}
+
+// Destruct a ranger.
+
+ssa_ranger::~ssa_ranger ()
+{
+}
+
+
+// Calculate a range on edge E and return it in R.  Try to evaluate a range
+// for NAME on this edge.  Return FALSE if this is either not a control edge
+// or NAME is not defined by this edge.
 
 bool
-ssa_ranger::range_of_cond_expr  (irange &r, gassign *s, tree name,
-                                 const irange *name_range, gimple *eval_from)
+ssa_ranger::outgoing_edge_range_p (irange &r, edge e, tree name,
+                                   irange *name_range)
+{
+  irange lhs;
+
+  gcc_checking_assert (valid_range_ssa_p (name));
+  // Determine if there is an outgoing edge.
+  gimple *s = gimple_outgoing_edge_range_p (lhs, e);
+
+  // If there is no outgoing stmt, there is no range produced.
+  if (!s)
+    return false;
+
+  // Otherwise use the outgoing edge as a LHS and try to calculate a range.
+  return compute_operand_range_on_stmt (r, s, lhs, name, name_range);
+}
+
+// Calculate a range for NAME on edge E and return it in R.  
+// if NAME is a PHI node at the dest of E, get the argument result.
+// Return false if no range can be determined.
+
+void
+ssa_ranger::range_on_edge (irange &r, edge e, tree name)
+{
+  irange edge_range;
+  gcc_checking_assert (irange::supports_p (name));
+  
+  if (!valid_range_ssa_p (name))
+    {
+      r = get_tree_range (name);
+      return;
+    }
+  range_on_exit (r, e->src, name);
+  gcc_checking_assert  (r.undefined_p ()
+                       || types_compatible_p (r.type(), TREE_TYPE (name)));
+
+  // Check to see if NAME is defined on edge e.
+  if (outgoing_edge_range_p (edge_range, e, name, &r))
+    r = edge_range;
+}
+
+
+// Return the range for NAME on entry to basic block BB in R.  
+// Return false if no range can be calculated.
+// Calculation is performed by unioning all the ranges on incoming edges.
+
+void
+ssa_ranger::range_on_entry (irange &r, basic_block bb, tree name)
+{
+  edge_iterator ei;
+  edge e;
+  tree type = TREE_TYPE (name);
+  irange pred_range;
+
+  gcc_checking_assert (irange::supports_type_p (type));
+
+  // Start with an empty range.
+  r.set_undefined ();
+
+  gcc_checking_assert (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun));
+
+  // Visit each predecessor to resolve them.
+  FOR_EACH_EDGE (e, ei, bb->preds)
+    {
+      range_on_edge (pred_range, e, name);
+      r.union_ (pred_range);
+      // If varying is reach, stop processing.
+      if (r.varying_p ())
+        break;
+    }
+}
+
+
+// Calculate the range for NAME at the end of block BB and return it in R.
+// Return false if no range can be calculated.
+
+void
+ssa_ranger::range_on_exit (irange &r, basic_block bb, tree name)
+{
+  // on-exit from the exit block?
+  gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
+
+  gimple *s = last_stmt (bb);
+  // If there is no statement in the block and this isnt the entry block,
+  // go get the range_on_entry for this block.
+  // For the entry block, a NULL stmt will return the global value for NAME.
+  if (!s && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun))
+    range_on_entry (r, bb, name);
+  else
+    gcc_assert (range_of_expr (r, name, s));
+  gcc_checking_assert (r.undefined_p ()
+                      || types_compatible_p (r.type(), TREE_TYPE (name)));
+}
+
+// Calculate a range for range_op statement S and return it in R.  Evaluate
+// the statement as if it were on edge EVAL_ON.  If a range cannot be
+// calculated, return false.  
+
+bool
+ssa_ranger::range_of_range_op (irange &r, grange_op *s, edge eval_on)
+{
+  irange range1, range2;
+  bool res = true;
+  gcc_checking_assert (irange::supports_type_p (gimple_expr_type (s)));
+
+  tree op1 = s->operand1 ();
+  tree op2 = s->operand2 ();
+
+  // Calculate a range for operand 1.
+  range_on_edge (range1, eval_on, op1);
+
+  // Calculate a result for op2 if it is needed.
+  if (op2)
+    range_on_edge (range2, eval_on, op2);
+
+  return range_of_range_op_core (r, s, res, range1, range2);
+}
+
+bool
+ssa_ranger::range_of_phi (irange &r, gphi *phi, tree name,
+                          const irange *name_range, gimple *eval_from,
+                          edge on_edge)
+{
+  tree phi_def = gimple_phi_result (phi);
+  tree type = TREE_TYPE (phi_def);
+  irange phi_range;
+  unsigned x;
+
+  if (!irange::supports_type_p (type))
+    return false;
+
+  // And start with an empty range, unioning in each argument's range.
+  r.set_undefined ();
+  for (x = 0; x < gimple_phi_num_args (phi); x++)
+    {
+      irange arg_range;
+      tree arg = gimple_phi_arg_def (phi, x);
+      edge e = gimple_phi_arg_edge (phi, x);
+      if (on_edge && e != on_edge)
+        continue;
+      if (name == arg)
+        arg_range = *name_range;
+      else if (valid_range_ssa_p (arg) && !eval_from)
+      // Try to find a range from the edge.  If that fails, return varying.
+       range_on_edge (arg_range, e, arg);
+      else
+       gcc_assert (range_of_expr (arg_range, arg, eval_from));
+
+      r.union_ (arg_range);
+      // Once the value reaches varying, stop looking.
+      if (r.varying_p ())
+       break;
+    }
+
+  return true;
+}
+
+// Calculate a range for COND_EXPR statement S and return it in R.  Evaluate 
+// the stateemnt as if it occured on edge ON_EDGE.
+// If a range cannot be calculated, return false. 
+
+bool
+ssa_ranger::range_of_cond_expr  (irange &r, gassign *s, edge on_edge)
 {
   irange cond_range, range1, range2;
   tree cond = gimple_assign_rhs1 (s);
@@ -510,23 +566,9 @@ ssa_ranger::range_of_cond_expr  (irange &r, gassign *s, tree name,
   if (!irange::supports_type_p (TREE_TYPE (op1)))
     return false;
 
-  if (!eval_from)
-    eval_from = s;
-
-  if (name == cond)
-    cond_range = *name_range;
-  else
-    gcc_assert (range_of_expr (cond_range, cond, eval_from));
-
-  if (name == op1)
-    range1 = *name_range;
-  else
-    gcc_assert (range_of_expr (range1, op1, eval_from));
-
-  if (name == op2)
-    range2 = *name_range;
-  else
-    gcc_assert (range_of_expr (range2, op2, eval_from));
+  range_on_edge (cond_range, on_edge, cond);
+  range_on_edge (range1, on_edge, op1);
+  range_on_edge (range2, on_edge, op2);
 
   if (cond_range.singleton_p ())
     {
@@ -596,8 +638,7 @@ global_ranger::range_of_stmt (irange &r, gimple *s, tree name)
     return true;
  
   // Avoid infinite recursion by initializing global cache
-  irange tmp;
-  tmp = range_from_ssa (name);
+  irange tmp = get_tree_range (name);
   m_gori.m_globals.set_global_range (name, tmp);
 
   gcc_assert (ssa_ranger::range_of_stmt (r, s, name));
@@ -608,14 +649,6 @@ global_ranger::range_of_stmt (irange &r, gimple *s, tree name)
   return true;
 }
 
-// Return the range of expr OP on edge E in R.  
-
-bool
-global_ranger::range_of_expr (irange &r, tree op, edge e)
-{
-  return ssa_ranger::range_of_expr (r, op, e);
-}
-
 // Determine a range for OP on stmt S, returning the result in R.
 // If OP is not defined in BB, find the range on entry to this block.
 
@@ -697,7 +730,8 @@ global_ranger::export_global_ranges ()
          !r.varying_p())
        {
          // Make sure the new range is a subset of the old range.
-         irange old_range = range_from_ssa (name);
+         irange old_range;
+         old_range = get_tree_range (name);
          old_range.intersect (r);
          /* Disable this while we fix tree-ssa/pr61743-2.c.  */
          //gcc_checking_assert (old_range == r);
@@ -996,26 +1030,6 @@ trace_ranger::range_of_expr (irange &r, tree expr, gimple *s)
   return trailer (idx, "range_of_expr", res, expr, r);
 }
 
-// Tracing version of edge range_of_expr.  Call it with printing wrappers.
-
-bool
-trace_ranger::range_of_expr (irange &r, tree expr, edge e)
-{
-  bool res;
-  unsigned idx = ++trace_count;
-  if (dumping (idx))
-    {
-      fprintf (dump_file, "range_of_expr (");
-      print_generic_expr (dump_file, expr, TDF_SLIM);
-      fprintf (dump_file, ") on edge %d->%d\n", e->src->index, e->dest->index);
-      indent += bump;
-    }
-
-  res =  super::range_of_expr (r, expr, e);
-
-  return trailer (idx, "range_of_expr", res, expr, r);
-}
-
 // Tracing version of range_on_edge.  Call it with printing wrappers.
 
 void
index 8a3ea8c6054c4a37375556f54e76f0998b30175a..38a15a7fc92f65c3156691ae5df593a1653ebc26 100644 (file)
@@ -41,25 +41,17 @@ along with GCC; see the file COPYING3.  If not see
 // outgoing_edge_range_p will only return a range if the edge specified 
 // defines a range for the specified name.  Otherwise false is returned.
 //
-
-class ssa_ranger
+//
+class stmt_ranger
 {
   public:
-  ssa_ranger ();
-  ~ssa_ranger ();
+  stmt_ranger ();
+  ~stmt_ranger ();
 
   virtual bool range_of_expr (irange &r, tree expr, gimple *s = NULL);
-  virtual bool range_of_expr (irange &r, tree expr, edge e);
   virtual bool range_of_stmt (irange &r, gimple *s, tree name = NULL_TREE);
   virtual bool range_of_stmt_with_range (irange &r, gimple *s, tree name,
                                         const irange &name_range);
-  virtual void range_on_edge (irange &r, edge e, tree name);
-  virtual void range_on_entry (irange &r, basic_block bb, tree name);
-  virtual void range_on_exit (irange &r, basic_block bb, tree name);
-
-  virtual bool outgoing_edge_range_p (irange &r, edge e, tree name,
-                                     irange *name_range = NULL);
-  
 protected:
   // Calculate a range for a kind of gimple statement .
   bool range_of_range_op_core (irange &r, grange_op *s, bool valid,
@@ -68,7 +60,6 @@ protected:
   bool range_of_range_op  (irange &r, grange_op *s, tree name,
                           const irange &name_range);
   bool range_of_range_op  (irange &r, grange_op *s, gimple *eval_from);
-  bool range_of_range_op  (irange &r, grange_op *s, edge on_edge);
 
   virtual bool range_of_phi (irange &r, gphi *phi, tree name = NULL_TREE,
                             const irange *name_range = NULL,
@@ -78,12 +69,31 @@ protected:
                      const irange *name_range = NULL,
                      gimple *eval_from = NULL, edge on_edge = NULL);
 
-  bool range_of_cond_expr (irange &r, gassign* call, edge on_edge);
   bool range_of_cond_expr (irange &r, gassign* call, tree name = NULL_TREE,
                           const irange *name_range = NULL,
                           gimple *eval_from = NULL);
 };
 
+class ssa_ranger : public stmt_ranger
+{
+  public:
+  ssa_ranger ();
+  ~ssa_ranger ();
+  virtual void range_on_edge (irange &r, edge e, tree name);
+  virtual void range_on_entry (irange &r, basic_block bb, tree name);
+  virtual void range_on_exit (irange &r, basic_block bb, tree name);
+
+  virtual bool outgoing_edge_range_p (irange &r, edge e, tree name,
+                                     irange *name_range = NULL);
+  
+protected:
+  bool range_of_cond_expr (irange &r, gassign* call, edge on_edge);
+  bool range_of_range_op  (irange &r, grange_op *s, edge on_edge);
+  virtual bool range_of_phi (irange &r, gphi *phi, tree name = NULL_TREE,
+                            const irange *name_range = NULL,
+                            gimple *eval_from = NULL, edge on_edge = NULL);
+};
+
 // This class utilizes the gori summary to query the range
 // of SSA_NAMEs across multiple basic blocks and edges.  It builds a cache
 // of range on entry to blocks.  All work is done on-demand so it is relatively
@@ -117,7 +127,6 @@ public:
   ~global_ranger ();
 
   virtual bool range_of_expr (irange &r, tree op, gimple *s = NULL);
-  virtual bool range_of_expr (irange &r, tree expr, edge e);
   virtual bool range_of_stmt (irange &r, gimple *s, tree name = NULL_TREE);
   virtual void range_on_entry (irange &r, basic_block bb, tree name);
 
@@ -159,7 +168,6 @@ public:
   trace_ranger();
 
   virtual bool range_of_expr (irange &r, tree expr, gimple *s = NULL);
-  virtual bool range_of_expr (irange &r, tree expr, edge e);
   virtual bool range_of_stmt (irange &r, gimple *s, tree name = NULL_TREE);
   virtual void range_on_edge (irange &r, edge e, tree name);
   virtual void range_on_entry (irange &r, basic_block bb, tree name);