]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Reduce range_stmt to a single gimple stmt for efficiency
authorAndrew Macleod <amacleod@gcc.gnu.org>
Tue, 10 Apr 2018 22:55:44 +0000 (22:55 +0000)
committerAndrew Macleod <amacleod@gcc.gnu.org>
Tue, 10 Apr 2018 22:55:44 +0000 (22:55 +0000)
From-SVN: r259304

gcc/ssa-range-bb.c
gcc/ssa-range-bb.h
gcc/ssa-range-stmt.c
gcc/ssa-range-stmt.h
gcc/ssa-range.c

index a288037b17088a84aa00d59d4a8ca44277bbb285..bafee0f817b4c220b1b1014080f1347c5ed172bd 100644 (file)
@@ -208,13 +208,14 @@ void
 gori_map::process_stmt (gimple *stmt, bitmap result, basic_block bb)
 {
   range_stmt rn (stmt);
-  tree ssa1 = rn.ssa_operand1 ();
-  tree ssa2 = rn.ssa_operand2 ();
   bitmap b;
 
   if (!rn.valid ())
     return;
 
+  tree ssa1 = rn.ssa_operand1 ();
+  tree ssa2 = rn.ssa_operand2 ();
+
   if (ssa1)
     {
       b = calc_def_chain (ssa1, bb);
@@ -348,125 +349,36 @@ block_ranger::~block_ranger ()
   delete gori;
 }
 
-/* Return TRUE if CODE with operands of type TYPE is a boolean
-   evaluation.  These are important to identify as both sides of a logical
-   binary expression must be evaluated in order to calculate a range.  */
+/* This routine will return what  is globally known about the range for an
+   operand of any kind.  */
 bool
-block_ranger::logical_expr_p (tree_code code, tree type) const
+block_ranger::get_operand_range (irange& r, tree op)
 {
+  /* This check allows unary operations to be handled without having to 
+     make an explicit check for the existence of a second operand.  */
+  if (!op)
+    return false;
 
-  /* Look for boolean and/or condition.  */
-  switch (code)
-    {
-      case TRUTH_AND_EXPR:
-      case TRUTH_OR_EXPR:
-        return true;
-
-      case BIT_AND_EXPR:
-      case BIT_IOR_EXPR:
-        if (types_compatible_p (type, boolean_type_node))
-         return true;
-       break;
-
-      default:
-        break;
-    }
-  return false;
-}
-
-/* Evaluate a binary logical expression given true and false ranges for each
-   of the operands. Base the result on the value in the LHS.  */
-bool
-block_ranger::eval_logical (irange& r, range_stmt &stmt, const irange& lhs,
-                           const irange& op1_true, const irange& op1_false,
-                           const irange& op2_true,
-                           const irange& op2_false) const
-{
-  gcc_checking_assert (logical_expr_p (stmt.get_code (),
-                                      TREE_TYPE (stmt.operand1 ())));
-  /* If the LHS can be TRUE OR FALSE, then both need to be evalauted and
-     combined, otherwise any range restrictions that have been determined
-     leading up to this point would be lost.  */
-  if (!wi::eq_p (lhs.lower_bound(), lhs.upper_bound()))
-    {
-      irange r1;
-      if (eval_logical (r1, stmt, bool_zero, op1_true, op1_false, op2_true,
-                       op2_false) &&
-         eval_logical (r, stmt, bool_one, op1_true, op1_false, op2_true,
-                       op2_false))
-       {
-         r.union_ (r1);
-         return true;
-       }
-      return false;
-
-    }
-
-  /* Now combine based on whether the result is TRUE or FALSE.  */
-  switch (stmt.get_code ())
-    {
-
-      /* A logical operation on two ranges is executed with operand ranges that
-        have been determined for both a TRUE and FALSE result..
-        Assuming x_8 is an unsigned char:
-               b_1 = x_8 < 20
-               b_2 = x_8 > 5
-        if we are looking for the range of x_8, the operand ranges will be:
-        will be: 
-        b_1 TRUE       x_8 = [0, 19]
-        b_1 FALSE      x_8 = [20, 255]
-        b_2 TRUE       x_8 = [6, 255]
-        b_2 FALSE      x_8 = [0,5]. */
-              
-      /*       c_2 = b_1 && b_2
-        The result of an AND operation with a TRUE result is the intersection
-        of the 2 TRUE ranges, [0,19] intersect [6,255]  ->   [6, 19]. */
-      case TRUTH_AND_EXPR:
-      case BIT_AND_EXPR:
-        if (!lhs.zero_p ())
-         r = irange_intersect (op1_true, op2_true);
-       else
-         {
-           /* The FALSE side is the union of the other 3 cases.  */
-           irange ff = irange_intersect (op1_false, op2_false);
-           irange tf = irange_intersect (op1_true, op2_false);
-           irange ft = irange_intersect (op1_false, op2_true);
-           r = irange_union (ff, tf);
-           r.union_ (ft);
-         }
-        break;
-
-      /*       c_2 = b_1 || b_2
-        An OR operation will only take the FALSE path if both operands are
-        false, so [20, 255] intersect [0, 5] is the union: [0,5][20,255].  */
-      case TRUTH_OR_EXPR:
-      case BIT_IOR_EXPR:
-        if (lhs.zero_p ())
-         r = irange_intersect (op1_false, op2_false);
-       else
-         {
-           /* The TRUE side of the OR operation will be the union of the other
-              three combinations.  */
-           irange tt = irange_intersect (op1_true, op2_true);
-           irange tf = irange_intersect (op1_true, op2_false);
-           irange ft = irange_intersect (op1_false, op2_true);
-           r = irange_union (tt, tf);
-           r.union_ (ft);
-         }
-       break;
-
-      default:
-        gcc_unreachable ();
-    }
+  if (TREE_CODE (op) == INTEGER_CST)
+    r.set_range (TREE_TYPE (op), op, op);
+  else
+    if (TREE_CODE (op) == SSA_NAME)
+      r = op;
+    else
+      if (TYPE_P (op))
+       r.set_range_for_type (op);
+      else
+        /* Default to range for the type of the expression.   */
+       r.set_range_for_type (TREE_TYPE (op));
 
   return true;
 }
 
+
 /* Given a logical STMT, calculate true and false for each potential path 
    using NAME and resolve the outcome based on the logical operator.  */
 bool
-block_ranger::process_logical (range_stmt& stmt, irange& r, tree name,
+block_ranger::process_logical (range_stmt stmt, irange& r, tree name,
                       const irange& lhs)
 {
   range_stmt op_stmt;
@@ -521,8 +433,8 @@ block_ranger::process_logical (range_stmt& stmt, irange& r, tree name,
        }
     }
 
-  if (!ret || !eval_logical (r, stmt, lhs, op1_true, op1_false, op2_true,
-                            op2_false))
+  if (!ret || !stmt.fold_logical (r, lhs, op1_true, op1_false, op2_true,
+                                 op2_false))
     r.set_range_for_type (TREE_TYPE (name));
   return true;
 }
@@ -531,14 +443,22 @@ block_ranger::process_logical (range_stmt& stmt, irange& r, tree name,
 /* Given the expression in STMT, return an evaluation in R for NAME.
    Returning false means the name being looked for was NOT resolvable.  */
 bool
-block_ranger::get_range (range_stmt& stmt, irange& r, tree name,
-                        const irange& lhs)
+block_ranger::get_range_from_stmt (range_stmt stmt, irange& r, tree name,
+                                  const irange& lhs)
 {
-  range_stmt op_stmt;
   irange op1_range, op2_range;
   tree op1, op2;
   bool op1_in_chain, op2_in_chain;
 
+  if (!stmt.valid ())
+    return false;
+
+  if (lhs.empty_p ())
+    {
+      r.clear (TREE_TYPE (name));
+      return true;
+    }
+
   op1 = stmt.operand1 ();
   op2 = stmt.operand2 ();
 
@@ -561,7 +481,7 @@ block_ranger::get_range (range_stmt& stmt, irange& r, tree name,
     }
 
   /* Check for boolean cases which require developing ranges and combining.  */
-  if (logical_expr_p (stmt.get_code (), TREE_TYPE (op1)))
+  if (stmt.logical_expr_p ())
     return process_logical (stmt, r, name, lhs);
 
   /* Reaching this point means NAME is not in this stmt, but one of the
@@ -621,29 +541,6 @@ block_ranger::get_range (range_stmt& stmt, irange& r, tree name,
   return get_range_from_stmt (SSA_NAME_DEF_STMT (op2), r, name, op2_range);
 }
  
-/* Given the expression in STMT, return an evaluation in R for NAME. */
-bool
-block_ranger::get_range_from_stmt (gimple *stmt, irange& r, tree name,
-                          const irange& lhs)
-{
-  range_stmt rn;
-  rn = stmt;
-
-  /* If it isnt an expression that is understood, we know nothing.  */
-  if (!rn.valid())
-    return false;
-
-  /* If the lhs has no range, ie , it cannot be executed, then the query
-     has no range either.  */
-  if (lhs.empty_p ())
-    {
-      r.clear (TREE_TYPE (name));
-      return true;
-    }
-  return get_range (rn, r, name, lhs);
-}
-
 void
 block_ranger::dump (FILE *f)
 {
@@ -812,28 +709,45 @@ block_ranger::range_on_stmt (irange& r, tree name, gimple *g)
   if (rn.operand1 () != name && rn.operand2 () != name)
     return false;
 
-  /* So far only understand LHS if its an assignment.  */
-  if (gimple_code (g) != GIMPLE_ASSIGN)
+  /* Only works if there is a LHS.  */
+  if (!gimple_get_lhs (g))
     return false;
 
   if (get_operand_range (lhs, gimple_get_lhs (g)))
-    return get_range (rn, r, name, lhs);
+    return get_range_from_stmt (rn, r, name, lhs);
 
   return false;
 }
 
+
+/* Attempt to evaluate the epression using whatever is globally known about
+   the operands.  If it can be evaluated, TRUE is returned
+   and the range is returned in R.  */
+
 bool
 block_ranger::range_of_def (irange& r, gimple *g)
 {
   range_stmt rn (g);
+  irange r1, r2;
 
   /* If we don't understand the stmt... */
   if (!rn.valid())
     return false;
   
-  return rn.fold (r);
+  tree op1 = rn.operand1 ();
+  tree op2 = rn.operand2 ();
+
+  get_operand_range (r1, op1);
+  if (op2)
+    return rn.fold (r, r1);
+
+  get_operand_range (r2, op2);
+  return rn.fold (r, r1, r2);
 }
 
+/* This method will attempt to evaluate the expression by replacing any
+   occurrence of ssa_name NAME with the range NAME_RANGE. If it can be
+   evaluated, TRUE is returned and the resulting range returned in R.  */
 bool
 block_ranger::range_of_def (irange& r, gimple *g, tree name,
                    const irange& range_of_name)
@@ -844,6 +758,23 @@ block_ranger::range_of_def (irange& r, gimple *g, tree name,
   if (!rn.valid())
     return false;
   
-  return rn.fold (r, name, range_of_name);
+  irange r1, r2;
+  tree op1 = rn.operand1 ();
+  tree op2 = rn.operand2 ();
+
+  if (op1 == name)
+    r1 = range_of_name;
+  else
+    get_operand_range (r1, op1);
+
+  if (!op2)
+    return rn.fold (r, r1);
+
+  if (op2 == name)
+    r2 = range_of_name;
+  else
+    get_operand_range (r2, op2);
+
+  return rn.fold (r, r1, r2);
 }
 
index ce42d432bb22c8cf66606fb5ded4c7872f2f1d6c..e4895566f787f8515eeefec8679a4bd9acca71c4 100644 (file)
@@ -34,15 +34,12 @@ class block_ranger
   class gori_map *gori;        /* Generates Outgoing Range Info.  */
   irange bool_zero;
   irange bool_one;
-  bool logical_expr_p (tree_code code, tree type) const;
-  bool eval_logical (irange& r, range_stmt &stmt, const irange& lhs,
-                    const irange& op1_true, const irange& op1_false,
-                    const irange& op2_true, const irange& op2_false) const;
-  bool process_logical (range_stmt& stmt, irange& r, tree name,
+  bool process_logical (range_stmt stmt, irange& r, tree name,
                        const irange& lhs);
-  bool get_range (range_stmt& stmt, irange& r, tree name, const irange& lhs);
-  bool get_range_from_stmt (gimple *stmt, irange& r, tree name,
+  bool get_range_from_stmt (range_stmt stmt, irange& r, tree name,
                            const irange& lhs);
+protected:
+  bool get_operand_range (irange& r, tree op);
 public:
   block_ranger ();
   ~block_ranger ();
index 4cf6e0fcf8fb901a55fa1833fa5c32e921781b56..3e6eccf29473f95dc5ace5045db0488231616150 100644 (file)
@@ -46,94 +46,156 @@ along with GCC; see the file COPYING3.  If not see
 #include "ssa-range-stmt.h"
 
 
-/* This routine will return what  is globally known about the range for an
-   operand of any kind.  */
-bool
-get_operand_range (irange& r, tree op)
+/* Validate that the statement and all operands of this expression are
+   operable on iranges. If it is valid, set the stmt pointer.  */
+void
+range_stmt::validate_stmt (gimple *s)
 {
-  /* This check allows unary operations to be handled without having to 
-     make an explicit check for the existence of a second operand.  */
-  if (!op)
-    return false;
+  // Check for supported statements
+  switch (gimple_code (s))
+    {
+      case GIMPLE_COND:
+      case GIMPLE_ASSIGN:
+       g = s;
+        break;
 
-  if (TREE_CODE (op) == INTEGER_CST)
-    r.set_range (TREE_TYPE (op), op, op);
-  else
-    if (TREE_CODE (op) == SSA_NAME)
-      r = op;
-    else
-      if (TYPE_P (op))
-       r.set_range_for_type (op);
-      else
-        /* Default to range for the type of the expression.   */
-       r.set_range_for_type (TREE_TYPE (op));
+      default:
+        g = NULL;
+    }
 
-  return true;
+  // Must have a ranger operation handler as well.
+  if (g && handler ())
+    {
+      // Now verify all the operanmds are compatible
+      tree op1 = operand1 ();
+      tree op2 = operand2 ();
+      tree ssa1 = valid_irange_ssa (op1);
+      tree ssa2 = valid_irange_ssa (op2);
+
+      if (ssa1 || (TREE_CODE (op1) == INTEGER_CST && !TREE_OVERFLOW (op1))) 
+       {
+         if (!op2)
+          return;
+         if (ssa2 || (TREE_CODE (op2) == INTEGER_CST && !TREE_OVERFLOW (op2)))
+          return;
+       }
+    }
+  g = NULL;
 }
 
 
-/* Initialize the SSA operands and validate that all operands of this
-   expression are operable on iranges. 
-   Return ERROR_MARK if they are not, otherwise the current tree code.  */
-tree_code
-range_stmt::validate_operands ()
+/* Return TRUE if CODE with operands of type TYPE is a boolean
+   evaluation.  These are important to identify as both sides of a logical
+   binary expression must be evaluated in order to calculate a range.  */
+bool
+range_stmt::logical_expr_p () const
 {
-  ssa1 = valid_irange_ssa (op1);
-  ssa2 = valid_irange_ssa (op2);
-
-  if (ssa1 || (TREE_CODE (op1) == INTEGER_CST && !TREE_OVERFLOW (op1))) 
-   {
-     if (!op2)
-       return code;
-     if (ssa2 || (TREE_CODE (op2) == INTEGER_CST && !TREE_OVERFLOW (op2)))
-       return code;
-   }
-  return ERROR_MARK;
+  /* Look for boolean and/or condition.  */
+  switch (get_code ())
+    {
+      case TRUTH_AND_EXPR:
+      case TRUTH_OR_EXPR:
+        return true;
+
+      case BIT_AND_EXPR:
+      case BIT_IOR_EXPR:
+        if (types_compatible_p (TREE_TYPE (operand1 ()), boolean_type_node))
+         return true;
+       break;
+
+      default:
+        break;
+    }
+  return false;
 }
 
-/* Build a range node from a stmt, if it possible.  */
-void
-range_stmt::from_stmt (gimple *s)
+
+/* Evaluate a binary logical expression given true and false ranges for each
+   of the operands. Base the result on the value in the LHS.  */
+bool
+range_stmt::fold_logical (irange& r, const irange& lhs, const irange& op1_true,
+                         const irange& op1_false, const irange& op2_true,
+                         const irange& op2_false) const
 {
-  switch (gimple_code (s))
+  gcc_checking_assert (logical_expr_p ());
+  /* If the LHS can be TRUE OR FALSE, then both need to be evaluated and
+     combined, otherwise any range restrictions that have been determined
+     leading up to this point would be lost.  */
+  if (!wi::eq_p (lhs.lower_bound(), lhs.upper_bound()))
     {
-      case GIMPLE_COND:
-        {
-         gcond *gc = as_a <gcond *> (s);
-         code  = gimple_cond_code (gc);
-         if (irange_op_handler (code))
-           {
-             lhs = gimple_get_lhs (s);
-             op1 = gimple_cond_lhs (gc);
-             op2 = gimple_cond_rhs (gc);
-             code = validate_operands ();
-             return;
-           }
-         break;
-       }
-      case GIMPLE_ASSIGN:
+      irange r1;
+      irange bool_zero (boolean_type_node, 0, 0);
+      irange bool_one (boolean_type_node, 1, 1);
+      if (fold_logical (r1, bool_zero, op1_true, op1_false, op2_true,
+                       op2_false) &&
+         fold_logical (r, bool_one, op1_true, op1_false, op2_true, op2_false))
        {
-         gassign *ga = as_a <gassign *> (s);
-         code = gimple_assign_rhs_code (ga);
-         if (irange_op_handler (code))
-           {
-             lhs = gimple_get_lhs (s);
-             op1 = gimple_assign_rhs1 (ga);
-             if (get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS)
-               op2 = gimple_assign_rhs2 (ga);
-             else
-               op2 = NULL;
-             code = validate_operands ();
-             return;
-           }
-         break;
+         r.union_ (r1);
+         return true;
        }
+      return false;
 
-      default:
+    }
+
+  /* Now combine based on whether the result is TRUE or FALSE.  */
+  switch (get_code ())
+    {
+
+      /* A logical operation on two ranges is executed with operand ranges that
+        have been determined for both a TRUE and FALSE result..
+        Assuming x_8 is an unsigned char:
+               b_1 = x_8 < 20
+               b_2 = x_8 > 5
+        if we are looking for the range of x_8, the operand ranges will be:
+        will be: 
+        b_1 TRUE       x_8 = [0, 19]
+        b_1 FALSE      x_8 = [20, 255]
+        b_2 TRUE       x_8 = [6, 255]
+        b_2 FALSE      x_8 = [0,5]. */
+              
+      /*       c_2 = b_1 && b_2
+        The result of an AND operation with a TRUE result is the intersection
+        of the 2 TRUE ranges, [0,19] intersect [6,255]  ->   [6, 19]. */
+      case TRUTH_AND_EXPR:
+      case BIT_AND_EXPR:
+        if (!lhs.zero_p ())
+         r = irange_intersect (op1_true, op2_true);
+       else
+         {
+           /* The FALSE side is the union of the other 3 cases.  */
+           irange ff = irange_intersect (op1_false, op2_false);
+           irange tf = irange_intersect (op1_true, op2_false);
+           irange ft = irange_intersect (op1_false, op2_true);
+           r = irange_union (ff, tf);
+           r.union_ (ft);
+         }
         break;
+
+      /*       c_2 = b_1 || b_2
+        An OR operation will only take the FALSE path if both operands are
+        false, so [20, 255] intersect [0, 5] is the union: [0,5][20,255].  */
+      case TRUTH_OR_EXPR:
+      case BIT_IOR_EXPR:
+        if (lhs.zero_p ())
+         r = irange_intersect (op1_false, op2_false);
+       else
+         {
+           /* The TRUE side of the OR operation will be the union of the other
+              three combinations.  */
+           irange tt = irange_intersect (op1_true, op2_true);
+           irange tf = irange_intersect (op1_true, op2_false);
+           irange ft = irange_intersect (op1_false, op2_true);
+           r = irange_union (tt, tf);
+           r.union_ (ft);
+         }
+       break;
+
+      default:
+        gcc_unreachable ();
     }
-  code = ERROR_MARK;
-  return;
+
+  return true;
 }
 
 /* This method will attempt to resolve a unary expression with value R1 to
@@ -144,16 +206,14 @@ bool
 range_stmt::fold (irange &res, const irange& r1) const
 {
   irange r2;
-  irange_operator *handler = irange_op_handler (code);
-  gcc_assert (handler != NULL);
-
+  tree lhs = gimple_get_lhs (g);
   /* Single ssa operations require the LHS type as the second range.  */
   if (lhs)
     r2.set_range_for_type (TREE_TYPE (lhs));
   else
     r2.clear (r1.get_type ());
 
-  return handler->fold_range (res, r1, r2);
+  return handler()->fold_range (res, r1, r2);
 }
 
 /* This method will attempt to resolve a binary expression with operand
@@ -163,62 +223,9 @@ range_stmt::fold (irange &res, const irange& r1) const
 bool
 range_stmt::fold (irange &res, const irange& r1, const irange& r2) const
 {
-  irange_operator *handler = irange_op_handler (code);
-  gcc_assert (handler != NULL);
-
   // Make sure this isnt a unary operation being passed a second range.
-  gcc_assert (op2);
-  return handler->fold_range (res, r1, r2);
-}
-
-/* This method will attempt to evaluate the epression using whatever is
-   globally known about the operands.  If it can be evaluated, TRUE is returned
-   and the range is returned in RES.  */
-
-bool
-range_stmt::fold (irange &res) const
-{
-  irange r1, r2;
-  
-  if (!op2)
-    {
-      get_operand_range (r1, op1);
-      return fold (res, r1);
-    }
-
-  get_operand_range (r1, op1);
-  get_operand_range (r2, op2);
-  return fold (res, r1, r2);
-}
-
-/* This method will attempt to evaluate the expression by replacing any
-   occurrence of ssa_name NAME with the range NAME_RANGE. If it can be
-   evaluated, TRUE is returned and the resulting range returned in RES.  */
-bool
-range_stmt::fold (irange& res, tree name, const irange& name_range) const
-{
-  irange r1, r2;
-
-  if (!op2)
-    {
-      if (ssa1 == name)
-       r1 = name_range;
-      else
-       get_operand_range (r1, op1);
-      return fold (res, r1);
-    }
-
-  if (ssa1 == name)
-    r1 = name_range;
-  else
-    get_operand_range (r1, op1);
-
-  if (ssa2 == name)
-    r2 = name_range;
-  else
-    get_operand_range (r2, op2);
-
-  return fold (res, r1, r2);
+  gcc_assert (operand2 ());
+  return handler() ->fold_range (res, r1, r2);
 }
 
 /* This method will evaluate a range for the operand of a unary expression
@@ -228,7 +235,7 @@ bool
 range_stmt::op1_irange (irange& r, const irange& lhs_range) const
 {  
   irange type_range;
-  type_range.set_range_for_type (TREE_TYPE (op1));
+  type_range.set_range_for_type (TREE_TYPE (operand1 ()));
   return handler ()->op1_irange (r, lhs_range, type_range);
 }
 
@@ -240,7 +247,7 @@ bool
 range_stmt::op1_irange (irange& r, const irange& lhs_range,
                        const irange& op2_range) const
 {  
-  gcc_assert (op2 != NULL);
+  gcc_assert (operand2 () != NULL);
   return handler ()->op1_irange (r, lhs_range, op2_range);
 }
 
@@ -259,6 +266,10 @@ range_stmt::op2_irange (irange& r, const irange& lhs_range,
 void
 range_stmt::dump (FILE *f) const
 {
+  tree lhs = gimple_get_lhs (g);
+  tree op1 = operand1 ();
+  tree op2 = operand2 ();
+
   if (lhs)
     {
       print_generic_expr (f, lhs, TDF_SLIM);
@@ -266,13 +277,13 @@ range_stmt::dump (FILE *f) const
     }
 
   if (!op2)
-    irange_op_handler (code)->dump (f);
+    handler ()->dump (f);
 
   print_generic_expr (f, op1, TDF_SLIM);
 
   if (op2)
     {
-      irange_op_handler (code)->dump (f);
+      handler ()->dump (f);
       print_generic_expr (f, op2, TDF_SLIM);
     }
 
index fe685b010f53ca042a574474cfb4d786b6a72e36..e0d9bf7890679a3415a47d8a30cbb9b33a8bd2d7 100644 (file)
@@ -24,9 +24,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "range.h"
 #include "range-op.h"
 
-/* Return a the range for a single tree object.  */
-bool get_operand_range (irange& r, tree op);
-
 /* This class is used summarize expressions that are supported by the
    irange_operator class, and provide an interface to the operators on
    the expression.  
@@ -43,12 +40,8 @@ bool get_operand_range (irange& r, tree op);
 class range_stmt
 {
 private:
-  tree_code code;
-  tree lhs;
-  tree op1, op2;
-  tree ssa1, ssa2;
-  tree_code validate_operands ();
-  void from_stmt (gimple *s);
+  gimple *g;
+  void validate_stmt (gimple *s);
   class irange_operator *handler() const;
 public:
   range_stmt ();
@@ -64,8 +57,8 @@ public:
   tree ssa_operand1 () const;
   tree ssa_operand2 () const;
 
-  bool fold (irange& res) const;
-  bool fold (irange& res, tree name, const irange& name_range) const;
+  bool logical_expr_p () const;
+
   bool fold (irange& res, const irange& r1) const;
   bool fold (irange& res, const irange& r1, const irange& r2) const;
   bool op1_irange (irange& r, const irange& lhs_range) const;
@@ -74,6 +67,10 @@ public:
   bool op2_irange (irange& r, const irange& lhs_range,
                   const irange& op1_range) const;
 
+  bool fold_logical (irange& r, const irange& lhs, const irange& op1_true,
+                    const irange& op1_false, const irange& op2_true,
+                    const irange& op2_false) const;
+
   void dump (FILE *f) const;
 };
 
@@ -82,21 +79,21 @@ public:
 inline
 range_stmt::range_stmt ()
 {
-  code = ERROR_MARK;
+  g = NULL;
 }
 
 /* Initialize a range statement from gimple statement S.  */
 inline 
 range_stmt::range_stmt (gimple *s)
 {
-  from_stmt (s);
+  validate_stmt (s);
 }
 
 /* Initialize a range statement from gimple statement S.  */
 inline range_stmt&
 range_stmt::operator= (gimple *s)
 {
-  from_stmt (s);
+  validate_stmt (s);
   return *this;
 }
 
@@ -104,43 +101,70 @@ range_stmt::operator= (gimple *s)
 inline bool
 range_stmt::valid () const
 {
-  return code != ERROR_MARK;
+  return g != NULL;
 }
 
 inline tree_code
 range_stmt::get_code () const
 {
-  return code;
+  return gimple_expr_code (g);
 }
 
 inline tree
 range_stmt::operand1 () const
 {
-  return op1;
+  switch (gimple_code (g))
+    {
+      case GIMPLE_COND:
+        return gimple_cond_lhs (g);
+      case GIMPLE_ASSIGN:
+        return gimple_assign_rhs1 (g);
+      default:
+        break;
+    }
+  return NULL;
 }
 
 inline tree
 range_stmt::operand2 () const
 {
-  return op2;
+  switch (gimple_code (g))
+    {
+      case GIMPLE_COND:
+        return gimple_cond_rhs (g);
+      case GIMPLE_ASSIGN:
+        if (gimple_num_ops (g) >= 3)
+         return gimple_assign_rhs2 (g);
+       else
+         return NULL;
+      default:
+        break;
+    }
+  return NULL;
 }
 
 inline tree
 range_stmt::ssa_operand1() const
 {
-  return ssa1;
+  tree op1 = operand1 ();
+  if (op1 && TREE_CODE (op1) == SSA_NAME)
+    return op1;
+  return NULL_TREE;
 }
 
 inline tree
 range_stmt::ssa_operand2 () const
 {
-  return ssa2;
+  tree op2 = operand2 ();
+  if (op2 && TREE_CODE (op2) == SSA_NAME)
+    return op2;
+  return NULL_TREE;
 }
 
 inline irange_operator *
 range_stmt::handler () const
 {
-  return irange_op_handler (code);
+  return irange_op_handler (get_code ());
 }
 
 #endif /* GCC_SSA_RANGE_STMT_H */
index 58595e419bba6bb968c4f081acf1d82171a179e4..7a63089d0d3fabe803e384d848d3c7eae02ce1cb 100644 (file)
@@ -430,6 +430,7 @@ path_ranger::path_range_stmt (irange& r, gimple *g)
   irange range_op1, range_op2;
   range_stmt rn;
   basic_block bb = gimple_bb (g);
+  bool res;
 
   if (is_a <gphi *> (g))
     {
@@ -458,13 +459,16 @@ path_ranger::path_range_stmt (irange& r, gimple *g)
     
   // If this is a unary operation, call fold now.  
   if (!rn.operand2 ())
-    return rn.fold (r, range_op1);
+    res = rn.fold (r, range_op1);
+  else
+    {
 
-  if (!path_get_operand (range_op2, rn.operand2 (), bb))
-    return false;
+      if (!path_get_operand (range_op2, rn.operand2 (), bb))
+       return false;
 
-  normalize_bool_type (range_op1, range_op2);
-  bool res = rn.fold (r, range_op1, range_op2);
+      normalize_bool_type (range_op1, range_op2);
+      res = rn.fold (r, range_op1, range_op2);
+    }
 
   if (name)
     {