diff mbox series

[COMMITTED] Add gimple_range_type for statements.

Message ID 93773969-4bab-94e4-2edb-67796c6c9049@redhat.com
State New
Headers show
Series [COMMITTED] Add gimple_range_type for statements. | expand

Commit Message

Andrew MacLeod July 15, 2021, 7:59 p.m. UTC
On 7/15/21 9:06 AM, Richard Biener wrote:
> On Thu, Jul 15, 2021 at 1:06 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>>
>> Currently gimple_expr_type is ICEing because it calls gimple_call_return_type.
>>
>> I still think gimple_call_return_type should return void_type_node
>> instead of ICEing, but this will also fix my problem.
>>
>> Anyone have a problem with this?
> It's still somewhat inconsistent, no?  Because for a call without a LHS
> it's now either void_type_node or the type of the return value.
>
> It's probably known I dislike gimple_expr_type itself (it was introduced
> to make the transition to tuples easier).  I wonder why you can't simply
> fix range_of_call to do
>
>     tree lhs = gimple_call_lhs (call);
>     if (lhs)
>       type = TREE_TYPE (lhs);
>
> Richard.

You are correct. There are indeed inconsistencies, and they exist in 
multiple places.  In fact, none of them do exactly what we are looking 
for all the time, and there are times we do care about the stmt when 
there is no LHS.    In addition, we almost always then have to check 
whether the type we found is supported.

So instead, much as we did for types with range_compatible_p (), we'll 
provide a function for statements which does exactly what we need. This 
patch eliminates all the ranger calls to both gimple_expr_type ()  and  
gimple_call_return_type () .    This will also simplify the life of 
anyone who goes to eventually remove gimple_expr_type () as there will 
now be less uses.

The function will return a type if and only if we can find the type in 
an orderly fashion, and then determine if it is also supported by ranger.

Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.

Andrew

Comments

Richard Biener July 16, 2021, 7:07 a.m. UTC | #1
On Thu, Jul 15, 2021 at 10:00 PM Andrew MacLeod <amacleod@redhat.com> wrote:
>
> On 7/15/21 9:06 AM, Richard Biener wrote:
> > On Thu, Jul 15, 2021 at 1:06 PM Aldy Hernandez <aldyh@redhat.com> wrote:
> >>
> >> Currently gimple_expr_type is ICEing because it calls gimple_call_return_type.
> >>
> >> I still think gimple_call_return_type should return void_type_node
> >> instead of ICEing, but this will also fix my problem.
> >>
> >> Anyone have a problem with this?
> > It's still somewhat inconsistent, no?  Because for a call without a LHS
> > it's now either void_type_node or the type of the return value.
> >
> > It's probably known I dislike gimple_expr_type itself (it was introduced
> > to make the transition to tuples easier).  I wonder why you can't simply
> > fix range_of_call to do
> >
> >     tree lhs = gimple_call_lhs (call);
> >     if (lhs)
> >       type = TREE_TYPE (lhs);
> >
> > Richard.
>
> You are correct. There are indeed inconsistencies, and they exist in
> multiple places.  In fact, none of them do exactly what we are looking
> for all the time, and there are times we do care about the stmt when
> there is no LHS.    In addition, we almost always then have to check
> whether the type we found is supported.
>
> So instead, much as we did for types with range_compatible_p (), we'll
> provide a function for statements which does exactly what we need. This
> patch eliminates all the ranger calls to both gimple_expr_type ()  and
> gimple_call_return_type () .    This will also simplify the life of
> anyone who goes to eventually remove gimple_expr_type () as there will
> now be less uses.

Thanks a lot!

Richard.

> The function will return a type if and only if we can find the type in
> an orderly fashion, and then determine if it is also supported by ranger.
>
> Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.
>
> Andrew
>
diff mbox series

Patch

commit 478cc962ad174bfc64c573152a0658935651fce3
Author: Andrew MacLeod <amacleod@redhat.com>
Date:   Thu Jul 15 11:07:12 2021 -0400

    Add gimple_range_type for statements.
    
    The existing mechanisms for picking up the type of a statement are
    inconsistent with the needs of ranger. Encapsulate all the bits
    required to pick up the return type of a statement in one place, and check
    whether the type is supported.
    
            * gimple-range-fold.cc (adjust_pointer_diff_expr): Use
            gimple_range_type.
            (fold_using_range::fold_stmt): Ditto.
            (fold_using_range::range_of_range_op): Ditto.
            (fold_using_range::range_of_phi): Ditto.
            (fold_using_range::range_of_call): Ditto.
            (fold_using_range::range_of_builtin_ubsan_call): Ditto.
            (fold_using_range::range_of_builtin_call): Ditto.
            (fold_using_range::range_of_cond_expr): Ditto.
            * gimple-range-fold.h (gimple_range_type): New.

diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index eff5d1f89f2..f8578c013bc 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -362,7 +362,7 @@  adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt)
     {
       tree max = vrp_val_max (ptrdiff_type_node);
       wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
-      tree expr_type = gimple_expr_type (diff_stmt);
+      tree expr_type = gimple_range_type (diff_stmt);
       tree range_min = build_zero_cst (expr_type);
       tree range_max = wide_int_to_tree (expr_type, wmax - 1);
       int_range<2> r (range_min, range_max);
@@ -522,16 +522,8 @@  fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
 
   if (!res)
     {
-      // If no name is specified, try the expression kind.
-      if (!name)
-	{
-	  tree t = gimple_expr_type (s);
-	  if (!irange::supports_type_p (t))
-	    return false;
-	  r.set_varying (t);
-	  return true;
-	}
-      if (!gimple_range_ssa_p (name))
+      // If no name specified or range is unsupported, bail.
+      if (!name || !gimple_range_ssa_p (name))
 	return false;
       // We don't understand the stmt, so return the global range.
       r = gimple_range_global (name);
@@ -558,10 +550,11 @@  bool
 fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
 {
   int_range_max range1, range2;
-  tree type = gimple_expr_type (s);
+  tree type = gimple_range_type (s);
+  if (!type)
+    return false;
   range_operator *handler = gimple_range_handler (s);
   gcc_checking_assert (handler);
-  gcc_checking_assert (irange::supports_type_p (type));
 
   tree lhs = gimple_get_lhs (s);
   tree op1 = gimple_range_operand1 (s);
@@ -719,11 +712,11 @@  bool
 fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
 {
   tree phi_def = gimple_phi_result (phi);
-  tree type = TREE_TYPE (phi_def);
+  tree type = gimple_range_type (phi);
   int_range_max arg_range;
   unsigned x;
 
-  if (!irange::supports_type_p (type))
+  if (!type)
     return false;
 
   // Start with an empty range, unioning in each argument's range.
@@ -780,13 +773,13 @@  fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
 bool
 fold_using_range::range_of_call (irange &r, gcall *call, fur_source &src)
 {
-  tree type = gimple_call_return_type (call);
+  tree type = gimple_range_type (call);
+  if (!type)
+    return false;
+
   tree lhs = gimple_call_lhs (call);
   bool strict_overflow_p;
 
-  if (!irange::supports_type_p (type))
-    return false;
-
   if (range_of_builtin_call (r, call, src))
     ;
   else if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p))
@@ -817,7 +810,7 @@  fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call,
 {
   gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR
 		       || code == MULT_EXPR);
-  tree type = gimple_call_return_type (call);
+  tree type = gimple_range_type (call);
   range_operator *op = range_op_handler (code, type);
   gcc_checking_assert (op);
   int_range_max ir0, ir1;
@@ -853,7 +846,7 @@  fold_using_range::range_of_builtin_call (irange &r, gcall *call,
   if (func == CFN_LAST)
     return false;
 
-  tree type = gimple_call_return_type (call);
+  tree type = gimple_range_type (call);
   tree arg;
   int mini, maxi, zerov = 0, prec;
   scalar_int_mode mode;
@@ -1094,12 +1087,12 @@  fold_using_range::range_of_cond_expr  (irange &r, gassign *s, fur_source &src)
   tree op1 = gimple_assign_rhs2 (s);
   tree op2 = gimple_assign_rhs3 (s);
 
-  gcc_checking_assert (gimple_assign_rhs_code (s) == COND_EXPR);
-  gcc_checking_assert (useless_type_conversion_p  (TREE_TYPE (op1),
-						   TREE_TYPE (op2)));
-  if (!irange::supports_type_p (TREE_TYPE (op1)))
+  tree type = gimple_range_type (s);
+  if (!type)
     return false;
 
+  gcc_checking_assert (gimple_assign_rhs_code (s) == COND_EXPR);
+  gcc_checking_assert (range_compatible_p (TREE_TYPE (op1), TREE_TYPE (op2)));
   src.get_operand (cond_range, cond);
   src.get_operand (range1, op1);
   src.get_operand (range2, op2);
@@ -1118,6 +1111,7 @@  fold_using_range::range_of_cond_expr  (irange &r, gassign *s, fur_source &src)
       r = range1;
       r.union_ (range2);
     }
+  gcc_checking_assert (range_compatible_p (r.type (), type));
   return true;
 }
 
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index dc1b28f9acc..ceed7ba48e1 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -56,6 +56,36 @@  gimple_range_handler (const gimple *s)
   return NULL;
 }
 
+// Return the type of range which statement S calculates.  If the type is
+// unsupported or no type can be determined, return NULL_TREE.
+
+static inline tree
+gimple_range_type (const gimple *s)
+{
+  tree lhs = gimple_get_lhs (s);
+  tree type = NULL_TREE;
+  if (lhs)
+    type = TREE_TYPE (lhs);
+  else
+    {
+      enum gimple_code code = gimple_code (s);
+      if (code == GIMPLE_COND)
+	type = boolean_type_node;
+      else if (code == GIMPLE_PHI)
+	type = TREE_TYPE (gimple_phi_result (s));
+      else if (code == GIMPLE_CALL)
+	{
+	  type = gimple_call_fntype (s);
+	  // If it has a type, get the return type.
+	  if (type)
+	    type = TREE_TYPE (type);
+	}
+    }
+  if (irange::supports_type_p (type))
+    return type;
+  return NULL_TREE;
+}
+
 // Return EXP if it is an SSA_NAME with a type supported by gimple ranges.
 
 static inline tree