public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] analyzer: avoid comparisons between uncomparable types (PR 93450)
@ 2020-01-30 14:43 David Malcolm
  2020-01-30 14:54 ` Jakub Jelinek
  0 siblings, 1 reply; 8+ messages in thread
From: David Malcolm @ 2020-01-30 14:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

PR analyzer/93450 reports an ICE trying to fold an EQ_EXPR comparison
of (int)0 with (float)Inf.

Most comparisons inside the analyzer come from gimple conditions, for
which the necessary casts have already been added.

This one is done inside constant_svalue::eval_condition as part of
purging sm-state for an unknown function call, and fails to check
the types being compared, leading to the ICE.

sm_state_map::set_state calls region_model::eval_condition_without_cm in
order to handle pointer equality (so that e.g. (void *)&r and (foo *)&r
transition together), which leads to this code generating a bogus query
to see if the two constants are equal.

This patch fixes the ICE in two ways:

- It avoids generating comparisons within
  constant_svalue::eval_condition unless the types are equal (thus for
  constants, but not for pointer values, which are handled by
  region_svalue).

- It updates sm_state_map::set_state to bail immediately if the new
  state is the same as the old one, thus avoiding the above for the
  common case where an svalue_id has no sm-state (such as for the int
  and float constants in the reproducer), for which the above becomes a
  no-op.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Committed to master as r10-6351-gd177c49cd31131c8cededb216da30877d8a3856d.

gcc/analyzer/ChangeLog:
	PR analyzer/93450
	* program-state.cc (sm_state_map::set_state): For the overload
	taking an svalue_id, bail out if the set_state on the ec does
	nothing.  Convert the latter's return type from void to bool,
	returning true if anything changed.
	(sm_state_map::impl_set_state): Convert the return type from void
	to bool, returning true if the state changed.
	* program-state.h (sm_state_map::set_state): Convert return type
	from void to bool.
	(sm_state_map::impl_set_state): Likewise.
	* region-model.cc (constant_svalue::eval_condition): Only call
	fold_build2 if the types are the same.

gcc/testsuite/ChangeLog:
	PR analyzer/93450
	* gcc.dg/analyzer/torture/pr93450.c: New test.
---
 gcc/analyzer/program-state.cc                 | 23 +++++++++++------
 gcc/analyzer/program-state.h                  |  4 +--
 gcc/analyzer/region-model.cc                  | 16 +++++++-----
 .../gcc.dg/analyzer/torture/pr93450.c         | 25 +++++++++++++++++++
 4 files changed, 53 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/torture/pr93450.c

diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index a9e300fba0f..f41f105ce6b 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -259,7 +259,8 @@ sm_state_map::set_state (region_model *model,
   if (model == NULL)
     return;
   equiv_class &ec = model->get_constraints ()->get_equiv_class (sid);
-  set_state (ec, state, origin);
+  if (!set_state (ec, state, origin))
+    return;
 
   /* Also do it for all svalues that are equal via non-cm, so that
      e.g. (void *)&r and (foo *)&r transition together.  */
@@ -276,34 +277,42 @@ sm_state_map::set_state (region_model *model,
 }
 
 /* Set the state of EC to STATE, recording that the state came from
-   ORIGIN.  */
+   ORIGIN.
+   Return true if any states of svalue_ids within EC changed.  */
 
-void
+bool
 sm_state_map::set_state (const equiv_class &ec,
 			 state_machine::state_t state,
 			 svalue_id origin)
 {
   int i;
   svalue_id *sid;
+  bool any_changed = false;
   FOR_EACH_VEC_ELT (ec.m_vars, i, sid)
-    impl_set_state (*sid, state, origin);
+    any_changed |= impl_set_state (*sid, state, origin);
+  return any_changed;
 }
 
-/* Set state of PV to STATE, bypassing equivalence classes.  */
+/* Set state of SID to STATE, bypassing equivalence classes.
+   Return true if the state changed.  */
 
-void
+bool
 sm_state_map::impl_set_state (svalue_id sid, state_machine::state_t state,
 			      svalue_id origin)
 {
+  if (get_state (sid) == state)
+    return false;
+
   /* Special-case state 0 as the default value.  */
   if (state == 0)
     {
       if (m_map.get (sid))
 	m_map.remove (sid);
-      return;
+      return true;
     }
   gcc_assert (!sid.null_p ());
   m_map.put (sid, entry_t (state, origin));
+  return true;
 }
 
 /* Set the "global" state within this state map to STATE.  */
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index adc71a4eda2..0a4e35f3d5d 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -161,10 +161,10 @@ public:
 		  svalue_id sid,
 		  state_machine::state_t state,
 		  svalue_id origin);
-  void set_state (const equiv_class &ec,
+  bool set_state (const equiv_class &ec,
 		  state_machine::state_t state,
 		  svalue_id origin);
-  void impl_set_state (svalue_id sid,
+  bool impl_set_state (svalue_id sid,
 		       state_machine::state_t state,
 		       svalue_id origin);
 
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index a5b3dffcc27..c838454a1eb 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -666,12 +666,16 @@ constant_svalue::eval_condition (constant_svalue *lhs,
   gcc_assert (CONSTANT_CLASS_P (lhs_const));
   gcc_assert (CONSTANT_CLASS_P (rhs_const));
 
-  tree comparison
-    = fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
-  if (comparison == boolean_true_node)
-    return tristate (tristate::TS_TRUE);
-  if (comparison == boolean_false_node)
-    return tristate (tristate::TS_FALSE);
+  /* Check for comparable types.  */
+  if (TREE_TYPE (lhs_const) == TREE_TYPE (rhs_const))
+    {
+      tree comparison
+	= fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
+      if (comparison == boolean_true_node)
+	return tristate (tristate::TS_TRUE);
+      if (comparison == boolean_false_node)
+	return tristate (tristate::TS_FALSE);
+    }
   return tristate::TS_UNKNOWN;
 }
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr93450.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr93450.c
new file mode 100644
index 00000000000..7f6cba0db6d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr93450.c
@@ -0,0 +1,25 @@
+void
+ed (int);
+
+double
+bg (void)
+{
+  double kl = __builtin_huge_val ();
+
+  ed (0);
+
+  return kl;
+}
+
+static double __attribute__((noinline))
+get_hugeval (void)
+{
+  return __builtin_huge_val ();
+}
+
+int test_2 (int i)
+{
+  if (i < get_hugeval ())
+    return 42;
+  return 0;
+}
-- 
2.21.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [committed] analyzer: avoid comparisons between uncomparable types (PR 93450)
  2020-01-30 14:43 [committed] analyzer: avoid comparisons between uncomparable types (PR 93450) David Malcolm
@ 2020-01-30 14:54 ` Jakub Jelinek
  2020-01-31  1:32   ` David Malcolm
  0 siblings, 1 reply; 8+ messages in thread
From: Jakub Jelinek @ 2020-01-30 14:54 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

On Thu, Jan 30, 2020 at 09:27:33AM -0500, David Malcolm wrote:
> --- a/gcc/analyzer/region-model.cc
> +++ b/gcc/analyzer/region-model.cc
> @@ -666,12 +666,16 @@ constant_svalue::eval_condition (constant_svalue *lhs,
>    gcc_assert (CONSTANT_CLASS_P (lhs_const));
>    gcc_assert (CONSTANT_CLASS_P (rhs_const));
>  
> -  tree comparison
> -    = fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
> -  if (comparison == boolean_true_node)
> -    return tristate (tristate::TS_TRUE);
> -  if (comparison == boolean_false_node)
> -    return tristate (tristate::TS_FALSE);
> +  /* Check for comparable types.  */
> +  if (TREE_TYPE (lhs_const) == TREE_TYPE (rhs_const))

Isn't the analyzer invoked on GIMPLE?  In GIMPLE, pointer equality of types
is often not guaranteed and the compiler generally doesn't care about that,
what we care about is whether the two types are compatible
(types_compatible_p).  E.g. if originally both types were say long int,
but on lp64 one of the arguments was cast from long long int to long int,
you can end up with one operand long int and the other long long int;
they have the same precision etc., so it is ok to compare them.

> +    {
> +      tree comparison
> +	= fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
> +      if (comparison == boolean_true_node)
> +	return tristate (tristate::TS_TRUE);
> +      if (comparison == boolean_false_node)
> +	return tristate (tristate::TS_FALSE);

This seems to be a waste of compile time memory.  fold_build2 is essentially
  tem = fold_binary_loc (loc, code, type, op0, op1);
  if (!tem)
    tem = build2_loc (loc, code, type, op0, op1 PASS_MEM_STAT);
but as you only care if the result is boolean_true_node or
boolean_false_node, the build2_loc is unnecessary.  So, just use
fold_binary instead?  If it returns NULL_TREE, it won't compare equal to
either and will fall through to the TS_UNKNOWN case.
> +    }
>    return tristate::TS_UNKNOWN;
>  }

	Jakub

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [committed] analyzer: avoid comparisons between uncomparable types (PR 93450)
  2020-01-30 14:54 ` Jakub Jelinek
@ 2020-01-31  1:32   ` David Malcolm
  2020-01-31  2:03     ` [PATCH 2/2] analyzer: avoid use of fold_build2 David Malcolm
  2020-01-31  8:03     ` [PATCH 1/2] analyzer: further fixes for comparisons between uncomparable types (PR 93450) David Malcolm
  0 siblings, 2 replies; 8+ messages in thread
From: David Malcolm @ 2020-01-31  1:32 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, David Malcolm

On Thu, 2020-01-30 at 15:36 +0100, Jakub Jelinek wrote:
> On Thu, Jan 30, 2020 at 09:27:33AM -0500, David Malcolm wrote:
> > --- a/gcc/analyzer/region-model.cc
> > +++ b/gcc/analyzer/region-model.cc
> > @@ -666,12 +666,16 @@ constant_svalue::eval_condition
> > (constant_svalue *lhs,
> >    gcc_assert (CONSTANT_CLASS_P (lhs_const));
> >    gcc_assert (CONSTANT_CLASS_P (rhs_const));
> >  
> > -  tree comparison
> > -    = fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
> > -  if (comparison == boolean_true_node)
> > -    return tristate (tristate::TS_TRUE);
> > -  if (comparison == boolean_false_node)
> > -    return tristate (tristate::TS_FALSE);
> > +  /* Check for comparable types.  */
> > +  if (TREE_TYPE (lhs_const) == TREE_TYPE (rhs_const))
> 
> Isn't the analyzer invoked on GIMPLE?  In GIMPLE, pointer equality of
> types
> is often not guaranteed and the compiler generally doesn't care about
> that,
> what we care about is whether the two types are compatible
> (types_compatible_p).  E.g. if originally both types were say long
> int,
> but on lp64 one of the arguments was cast from long long int to long
> int,
> you can end up with one operand long int and the other long long int;
> they have the same precision etc., so it is ok to compare them.

Thanks.  In patch 1 of the attached I've replaced the pointer comparison
with a call to types_compatible_p, and added a call to
types_compatible_p to guard a place where constants were being compared.

> > +    {
> > +      tree comparison
> > +	= fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
> > +      if (comparison == boolean_true_node)
> > +	return tristate (tristate::TS_TRUE);
> > +      if (comparison == boolean_false_node)
> > +	return tristate (tristate::TS_FALSE);
> 
> This seems to be a waste of compile time memory.  fold_build2 is
> essentially
>   tem = fold_binary_loc (loc, code, type, op0, op1);
>   if (!tem)
>     tem = build2_loc (loc, code, type, op0, op1 PASS_MEM_STAT);
> but as you only care if the result is boolean_true_node or
> boolean_false_node, the build2_loc is unnecessary.  So, just use
> fold_binary instead?  If it returns NULL_TREE, it won't compare equal
> to
> either and will fall through to the TS_UNKNOWN case.

Thanks.  I did some grepping and found that I'd made this mistake in
six places in the analyzer.  Sorry about that.  Patch 2 should fix all
of them.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.

OK for master?

David Malcolm (2):
  analyzer: further fixes for comparisons between uncomparable types (PR
    93450)
  analyzer: avoid use of fold_build2

 gcc/analyzer/constraint-manager.cc | 19 +++++++++----------
 gcc/analyzer/region-model.cc       |  8 ++++----
 2 files changed, 13 insertions(+), 14 deletions(-)

-- 
2.21.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2/2] analyzer: avoid use of fold_build2
  2020-01-31  1:32   ` David Malcolm
@ 2020-01-31  2:03     ` David Malcolm
  2020-01-31 10:57       ` Jakub Jelinek
  2020-01-31 11:06       ` Andrew Pinski
  2020-01-31  8:03     ` [PATCH 1/2] analyzer: further fixes for comparisons between uncomparable types (PR 93450) David Malcolm
  1 sibling, 2 replies; 8+ messages in thread
From: David Malcolm @ 2020-01-31  2:03 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, David Malcolm

Various places in the analyzer use fold_build2, test the result, then
discard it.  It's more efficient to use fold_binary, which avoids
building and GC-ing a redundant tree for the cases where folding fails.

gcc/analyzer/ChangeLog:
	* constraint-manager.cc (range::constrained_to_single_element):
	Replace fold_build2 with fold_binary.  Remove unnecessary newline.
	(constraint_manager::get_or_add_equiv_class): Replace fold_build2
	with fold_binary in two places, and remove out-of-date comment.
	(constraint_manager::eval_condition): Replace fold_build2 with
	fold_binary.
	* region-model.cc (constant_svalue::eval_condition): Likewise.
	(region_model::on_assignment): Likewise.
---
 gcc/analyzer/constraint-manager.cc | 15 ++++++---------
 gcc/analyzer/region-model.cc       |  6 +++---
 2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index f3e31ee0830..4d138188856 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -145,10 +145,9 @@ range::constrained_to_single_element (tree *out)
   m_upper_bound.ensure_closed (true);
 
   // Are they equal?
-  tree comparison
-    = fold_build2 (EQ_EXPR, boolean_type_node,
-		   m_lower_bound.m_constant,
-		   m_upper_bound.m_constant);
+  tree comparison = fold_binary (EQ_EXPR, boolean_type_node,
+				 m_lower_bound.m_constant,
+				 m_upper_bound.m_constant);
   if (comparison == boolean_true_node)
     {
       *out = m_lower_bound.m_constant;
@@ -930,7 +929,7 @@ constraint_manager::get_or_add_equiv_class (svalue_id sid)
       FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
 	if (ec->m_constant)
 	  {
-	    tree eq = fold_build2 (EQ_EXPR, boolean_type_node,
+	    tree eq = fold_binary (EQ_EXPR, boolean_type_node,
 				   cst, ec->m_constant);
 	    if (eq == boolean_true_node)
 	      {
@@ -967,10 +966,8 @@ constraint_manager::get_or_add_equiv_class (svalue_id sid)
 		 Determine the direction of the inequality, and record that
 		 fact.  */
 	      tree lt
-		= fold_build2 (LT_EXPR, boolean_type_node,
+		= fold_binary (LT_EXPR, boolean_type_node,
 			       new_ec->m_constant, other_ec.m_constant);
-	      //gcc_assert (lt == boolean_true_node || lt == boolean_false_node);
-	      // not true for int vs float comparisons
 	      if (lt == boolean_true_node)
 		add_constraint_internal (new_id, CONSTRAINT_LT, other_id);
 	      else if (lt == boolean_false_node)
@@ -1016,7 +1013,7 @@ constraint_manager::eval_condition (equiv_class_id lhs_ec,
   if (lhs_const && rhs_const)
     {
       tree comparison
-	= fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
+	= fold_binary (op, boolean_type_node, lhs_const, rhs_const);
       if (comparison == boolean_true_node)
 	return tristate (tristate::TS_TRUE);
       if (comparison == boolean_false_node)
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index b546114bfd5..95d002f9c28 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -670,7 +670,7 @@ constant_svalue::eval_condition (constant_svalue *lhs,
   if (types_compatible_p (TREE_TYPE (lhs_const), TREE_TYPE (rhs_const)))
     {
       tree comparison
-	= fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
+	= fold_binary (op, boolean_type_node, lhs_const, rhs_const);
       if (comparison == boolean_true_node)
 	return tristate (tristate::TS_TRUE);
       if (comparison == boolean_false_node)
@@ -4070,9 +4070,9 @@ region_model::on_assignment (const gassign *assign, region_model_context *ctxt)
 	if (tree rhs1_cst = maybe_get_constant (rhs1_sid))
 	  if (tree rhs2_cst = maybe_get_constant (rhs2_sid))
 	    {
-	      tree result = fold_build2 (op, TREE_TYPE (lhs),
+	      tree result = fold_binary (op, TREE_TYPE (lhs),
 					 rhs1_cst, rhs2_cst);
-	      if (CONSTANT_CLASS_P (result))
+	      if (result && CONSTANT_CLASS_P (result))
 		{
 		  svalue_id result_sid
 		    = get_or_create_constant_svalue (result);
-- 
2.21.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] analyzer: further fixes for comparisons between uncomparable types (PR 93450)
  2020-01-31  1:32   ` David Malcolm
  2020-01-31  2:03     ` [PATCH 2/2] analyzer: avoid use of fold_build2 David Malcolm
@ 2020-01-31  8:03     ` David Malcolm
  2020-01-31 10:12       ` Jakub Jelinek
  1 sibling, 1 reply; 8+ messages in thread
From: David Malcolm @ 2020-01-31  8:03 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, David Malcolm

gcc/analyzer/ChangeLog:
	PR analyzer/93450
	* constraint-manager.cc
	(constraint_manager::get_or_add_equiv_class): Only compare constants
	if their types are compatible.
	* region-model.cc (constant_svalue::eval_condition): Replace check
	for identical types with call to types_compatible_p.
---
 gcc/analyzer/constraint-manager.cc | 4 +++-
 gcc/analyzer/region-model.cc       | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index 777bd1b13c9..f3e31ee0830 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -958,7 +958,9 @@ constraint_manager::get_or_add_equiv_class (svalue_id sid)
 	   other_id.m_idx++)
 	{
 	  const equiv_class &other_ec = other_id.get_obj (*this);
-	  if (other_ec.m_constant)
+	  if (other_ec.m_constant
+	      && types_compatible_p (TREE_TYPE (new_ec->m_constant),
+				     TREE_TYPE (other_ec.m_constant)))
 	    {
 	      /* If we have two ECs, both with constants, the constants must be
 		 non-equal (or they would be in the same EC).
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index a15088a2e3c..b546114bfd5 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -667,7 +667,7 @@ constant_svalue::eval_condition (constant_svalue *lhs,
   gcc_assert (CONSTANT_CLASS_P (rhs_const));
 
   /* Check for comparable types.  */
-  if (TREE_TYPE (lhs_const) == TREE_TYPE (rhs_const))
+  if (types_compatible_p (TREE_TYPE (lhs_const), TREE_TYPE (rhs_const)))
     {
       tree comparison
 	= fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
-- 
2.21.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] analyzer: further fixes for comparisons between uncomparable types (PR 93450)
  2020-01-31  8:03     ` [PATCH 1/2] analyzer: further fixes for comparisons between uncomparable types (PR 93450) David Malcolm
@ 2020-01-31 10:12       ` Jakub Jelinek
  0 siblings, 0 replies; 8+ messages in thread
From: Jakub Jelinek @ 2020-01-31 10:12 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

On Thu, Jan 30, 2020 at 08:19:17PM -0500, David Malcolm wrote:
> gcc/analyzer/ChangeLog:
> 	PR analyzer/93450
> 	* constraint-manager.cc
> 	(constraint_manager::get_or_add_equiv_class): Only compare constants
> 	if their types are compatible.
> 	* region-model.cc (constant_svalue::eval_condition): Replace check
> 	for identical types with call to types_compatible_p.

LGTM.

	Jakub

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] analyzer: avoid use of fold_build2
  2020-01-31  2:03     ` [PATCH 2/2] analyzer: avoid use of fold_build2 David Malcolm
@ 2020-01-31 10:57       ` Jakub Jelinek
  2020-01-31 11:06       ` Andrew Pinski
  1 sibling, 0 replies; 8+ messages in thread
From: Jakub Jelinek @ 2020-01-31 10:57 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

On Thu, Jan 30, 2020 at 08:19:18PM -0500, David Malcolm wrote:
> gcc/analyzer/ChangeLog:
> 	* constraint-manager.cc (range::constrained_to_single_element):
> 	Replace fold_build2 with fold_binary.  Remove unnecessary newline.
> 	(constraint_manager::get_or_add_equiv_class): Replace fold_build2
> 	with fold_binary in two places, and remove out-of-date comment.
> 	(constraint_manager::eval_condition): Replace fold_build2 with
> 	fold_binary.
> 	* region-model.cc (constant_svalue::eval_condition): Likewise.
> 	(region_model::on_assignment): Likewise.

LGTM.

	Jakub

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] analyzer: avoid use of fold_build2
  2020-01-31  2:03     ` [PATCH 2/2] analyzer: avoid use of fold_build2 David Malcolm
  2020-01-31 10:57       ` Jakub Jelinek
@ 2020-01-31 11:06       ` Andrew Pinski
  1 sibling, 0 replies; 8+ messages in thread
From: Andrew Pinski @ 2020-01-31 11:06 UTC (permalink / raw)
  To: David Malcolm; +Cc: Jakub Jelinek, GCC Patches

On Thu, Jan 30, 2020 at 5:19 PM David Malcolm <dmalcolm@redhat.com> wrote:
>
> Various places in the analyzer use fold_build2, test the result, then
> discard it.  It's more efficient to use fold_binary, which avoids
> building and GC-ing a redundant tree for the cases where folding fails.

If these are all true integer constants, then you might want to use
tree_int_cst_compare instead of even using fold_binary/fold_build2.
Also if you are doing equal but always constant (but not always
integer ones), you could use simple_cst_equal instead.

Thanks,
Andrew Pinski

>
> gcc/analyzer/ChangeLog:
>         * constraint-manager.cc (range::constrained_to_single_element):
>         Replace fold_build2 with fold_binary.  Remove unnecessary newline.
>         (constraint_manager::get_or_add_equiv_class): Replace fold_build2
>         with fold_binary in two places, and remove out-of-date comment.
>         (constraint_manager::eval_condition): Replace fold_build2 with
>         fold_binary.
>         * region-model.cc (constant_svalue::eval_condition): Likewise.
>         (region_model::on_assignment): Likewise.
> ---
>  gcc/analyzer/constraint-manager.cc | 15 ++++++---------
>  gcc/analyzer/region-model.cc       |  6 +++---
>  2 files changed, 9 insertions(+), 12 deletions(-)
>
> diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
> index f3e31ee0830..4d138188856 100644
> --- a/gcc/analyzer/constraint-manager.cc
> +++ b/gcc/analyzer/constraint-manager.cc
> @@ -145,10 +145,9 @@ range::constrained_to_single_element (tree *out)
>    m_upper_bound.ensure_closed (true);
>
>    // Are they equal?
> -  tree comparison
> -    = fold_build2 (EQ_EXPR, boolean_type_node,
> -                  m_lower_bound.m_constant,
> -                  m_upper_bound.m_constant);
> +  tree comparison = fold_binary (EQ_EXPR, boolean_type_node,
> +                                m_lower_bound.m_constant,
> +                                m_upper_bound.m_constant);
>    if (comparison == boolean_true_node)
>      {
>        *out = m_lower_bound.m_constant;
> @@ -930,7 +929,7 @@ constraint_manager::get_or_add_equiv_class (svalue_id sid)
>        FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
>         if (ec->m_constant)
>           {
> -           tree eq = fold_build2 (EQ_EXPR, boolean_type_node,
> +           tree eq = fold_binary (EQ_EXPR, boolean_type_node,
>                                    cst, ec->m_constant);
>             if (eq == boolean_true_node)
>               {
> @@ -967,10 +966,8 @@ constraint_manager::get_or_add_equiv_class (svalue_id sid)
>                  Determine the direction of the inequality, and record that
>                  fact.  */
>               tree lt
> -               = fold_build2 (LT_EXPR, boolean_type_node,
> +               = fold_binary (LT_EXPR, boolean_type_node,
>                                new_ec->m_constant, other_ec.m_constant);
> -             //gcc_assert (lt == boolean_true_node || lt == boolean_false_node);
> -             // not true for int vs float comparisons
>               if (lt == boolean_true_node)
>                 add_constraint_internal (new_id, CONSTRAINT_LT, other_id);
>               else if (lt == boolean_false_node)
> @@ -1016,7 +1013,7 @@ constraint_manager::eval_condition (equiv_class_id lhs_ec,
>    if (lhs_const && rhs_const)
>      {
>        tree comparison
> -       = fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
> +       = fold_binary (op, boolean_type_node, lhs_const, rhs_const);
>        if (comparison == boolean_true_node)
>         return tristate (tristate::TS_TRUE);
>        if (comparison == boolean_false_node)
> diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
> index b546114bfd5..95d002f9c28 100644
> --- a/gcc/analyzer/region-model.cc
> +++ b/gcc/analyzer/region-model.cc
> @@ -670,7 +670,7 @@ constant_svalue::eval_condition (constant_svalue *lhs,
>    if (types_compatible_p (TREE_TYPE (lhs_const), TREE_TYPE (rhs_const)))
>      {
>        tree comparison
> -       = fold_build2 (op, boolean_type_node, lhs_const, rhs_const);
> +       = fold_binary (op, boolean_type_node, lhs_const, rhs_const);
>        if (comparison == boolean_true_node)
>         return tristate (tristate::TS_TRUE);
>        if (comparison == boolean_false_node)
> @@ -4070,9 +4070,9 @@ region_model::on_assignment (const gassign *assign, region_model_context *ctxt)
>         if (tree rhs1_cst = maybe_get_constant (rhs1_sid))
>           if (tree rhs2_cst = maybe_get_constant (rhs2_sid))
>             {
> -             tree result = fold_build2 (op, TREE_TYPE (lhs),
> +             tree result = fold_binary (op, TREE_TYPE (lhs),
>                                          rhs1_cst, rhs2_cst);
> -             if (CONSTANT_CLASS_P (result))
> +             if (result && CONSTANT_CLASS_P (result))
>                 {
>                   svalue_id result_sid
>                     = get_or_create_constant_svalue (result);
> --
> 2.21.0
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-01-31 10:04 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-30 14:43 [committed] analyzer: avoid comparisons between uncomparable types (PR 93450) David Malcolm
2020-01-30 14:54 ` Jakub Jelinek
2020-01-31  1:32   ` David Malcolm
2020-01-31  2:03     ` [PATCH 2/2] analyzer: avoid use of fold_build2 David Malcolm
2020-01-31 10:57       ` Jakub Jelinek
2020-01-31 11:06       ` Andrew Pinski
2020-01-31  8:03     ` [PATCH 1/2] analyzer: further fixes for comparisons between uncomparable types (PR 93450) David Malcolm
2020-01-31 10:12       ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).