diff mbox

Fix PHI optimization issue with boolean types

Message ID 1842011.oP9bEcZBzd@polaris
State New
Headers show

Commit Message

Eric Botcazou Oct. 24, 2016, 11:39 a.m. UTC
> > But integer_truep is just integer_onep for BOOLEAN_TYPEs.

> 

> Yes, but it's more descriptive IMHO.


At the cost of consistency with fits_to_tree_p though.

> fits_to_tree_p avoids creating an INTEGER_CST in ggc memory and thus is the

> prefered way to test if you have a wide-int but not yet an INTEGER_CST.


OK, I was confused by int_fits_type_p, which calls it on an INTEGER_CST (which 
now breaks with the additional test in the function).

The attached fix seems to work and passes regression testing (all languages).


	* tree.h (wi::fits_to_tree_p): Accept only 0 and 1 for boolean types.
	* tree.c (int_fits_type_p): Likewise.  Pass the integer constant as a
	widest_int to above.

-- 
Eric Botcazou

Comments

Richard Biener Oct. 24, 2016, 11:49 a.m. UTC | #1
On Mon, Oct 24, 2016 at 1:39 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> > But integer_truep is just integer_onep for BOOLEAN_TYPEs.

>>

>> Yes, but it's more descriptive IMHO.

>

> At the cost of consistency with fits_to_tree_p though.

>

>> fits_to_tree_p avoids creating an INTEGER_CST in ggc memory and thus is the

>> prefered way to test if you have a wide-int but not yet an INTEGER_CST.

>

> OK, I was confused by int_fits_type_p, which calls it on an INTEGER_CST (which

> now breaks with the additional test in the function).

>

> The attached fix seems to work and passes regression testing (all languages).


Is the change to pass wi::to_widest really necessary?  I think it has a
runtime penalty.

Otherwise ok.

Thanks,
Richard.

>

>         * tree.h (wi::fits_to_tree_p): Accept only 0 and 1 for boolean types.

>         * tree.c (int_fits_type_p): Likewise.  Pass the integer constant as a

>         widest_int to above.

>

> --

> Eric Botcazou
Eric Botcazou Oct. 25, 2016, 8:17 a.m. UTC | #2
> Is the change to pass wi::to_widest really necessary?  I think it has a

> runtime penalty.


Yes, because there is no == operator for a (tree, int) pair.  Is there a cheap 
way to convert a tree back into a wide_int?  wi::to_wide?  Or a combination 
with decompose?  Otherwise you can use eq_p, but this means that all other 
callers of fits_to_tree_p are affected:

template <typename T>
bool
wi::fits_to_tree_p (const T &x, const_tree type)
{
  /* Short-circuit boolean types since various transformations assume that
     they can only take values 0 and 1.  */
  if (TREE_CODE (type) == BOOLEAN_TYPE)
    return eq_p (x, 0) || eq_p (x, 1);

instead of just int_fits_type_p (but I don't really know if there is a penalty 
associated with eq_p here).

-- 
Eric Botcazou
Richard Biener Oct. 25, 2016, 8:25 a.m. UTC | #3
On Tue, Oct 25, 2016 at 10:17 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> Is the change to pass wi::to_widest really necessary?  I think it has a

>> runtime penalty.

>

> Yes, because there is no == operator for a (tree, int) pair.


Ah, yes.  But operator== simply maps to wi::eq_p, so ...

>  Is there a cheap

> way to convert a tree back into a wide_int?  wi::to_wide?  Or a combination

> with decompose?  Otherwise you can use eq_p, but this means that all other

> callers of fits_to_tree_p are affected:

>

> template <typename T>

> bool

> wi::fits_to_tree_p (const T &x, const_tree type)

> {

>   /* Short-circuit boolean types since various transformations assume that

>      they can only take values 0 and 1.  */

>   if (TREE_CODE (type) == BOOLEAN_TYPE)

>     return eq_p (x, 0) || eq_p (x, 1);

>

> instead of just int_fits_type_p (but I don't really know if there is a penalty

> associated with eq_p here).


... this variant is fine it doesn't have any extra cost (the to_widest
in int_fits_type_p has).

I'm not sure what you mean with "all other callers of fits_to_tree_p
are affected" - that was desired.

Thanks,
Richard.


> --

> Eric Botcazou
Eric Botcazou Oct. 25, 2016, 10:22 a.m. UTC | #4
> I'm not sure what you mean with "all other callers of fits_to_tree_p

> are affected" - that was desired.


Affected by the from == to eq_p change:

+  if (TREE_CODE (type) == BOOLEAN_TYPE)
+    return x == 0 || x == 1;

vs

+  if (TREE_CODE (type) == BOOLEAN_TYPE)
+    return eq_p (x, 0) || eq_p (x, 1);

Is eq_p free for them too?  If no, then you distribute the overhead over all 
the callers instead of just int_fits_type_p (for which the call is unlikely).

-- 
Eric Botcazou
Richard Biener Oct. 25, 2016, 10:31 a.m. UTC | #5
On Tue, Oct 25, 2016 at 12:22 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> I'm not sure what you mean with "all other callers of fits_to_tree_p

>> are affected" - that was desired.

>

> Affected by the from == to eq_p change:

>

> +  if (TREE_CODE (type) == BOOLEAN_TYPE)

> +    return x == 0 || x == 1;

>

> vs

>

> +  if (TREE_CODE (type) == BOOLEAN_TYPE)

> +    return eq_p (x, 0) || eq_p (x, 1);

>

> Is eq_p free for them too?  If no, then you distribute the overhead over all

> the callers instead of just int_fits_type_p (for which the call is unlikely).


Yes, eq_p is equivalent to == (apart from the overloading issue you ran into).

Richard.

> --

> Eric Botcazou
diff mbox

Patch

Index: tree.c
===================================================================
--- tree.c	(revision 241437)
+++ tree.c	(working copy)
@@ -9065,8 +9065,8 @@  get_narrower (tree op, int *unsignedp_pt
   return win;
 }
 
-/* Returns true if integer constant C has a value that is permissible
-   for type TYPE (an INTEGER_TYPE).  */
+/* Return true if integer constant C has a value that is permissible
+   for TYPE, an integral type.  */
 
 bool
 int_fits_type_p (const_tree c, const_tree type)
@@ -9075,6 +9075,11 @@  int_fits_type_p (const_tree c, const_tre
   bool ok_for_low_bound, ok_for_high_bound;
   signop sgn_c = TYPE_SIGN (TREE_TYPE (c));
 
+  /* Short-circuit boolean types since various transformations assume that
+     they can only take values 0 and 1.  */
+  if (TREE_CODE (type) == BOOLEAN_TYPE)
+    return integer_zerop (c) || integer_truep (c);
+
 retry:
   type_low_bound = TYPE_MIN_VALUE (type);
   type_high_bound = TYPE_MAX_VALUE (type);
@@ -9154,7 +9159,7 @@  retry:
     }
 
   /* Or to fits_to_tree_p, if nothing else.  */
-  return wi::fits_to_tree_p (c, type);
+  return wi::fits_to_tree_p (wi::to_widest (c), type);
 }
 
 /* Stores bounds of an integer TYPE in MIN and MAX.  If TYPE has non-constant
Index: tree.h
===================================================================
--- tree.h	(revision 241437)
+++ tree.h	(working copy)
@@ -5295,6 +5295,11 @@  template <typename T>
 bool
 wi::fits_to_tree_p (const T &x, const_tree type)
 {
+  /* Short-circuit boolean types since various transformations assume that
+     they can only take values 0 and 1.  */
+  if (TREE_CODE (type) == BOOLEAN_TYPE)
+    return x == 0 || x == 1;
+
   if (TYPE_SIGN (type) == UNSIGNED)
     return eq_p (x, zext (x, TYPE_PRECISION (type)));
   else