Patchwork [tree-optimization] : Try to do type sinking on comparisons

login
register
mail settings
Submitter Kai Tietz
Date June 27, 2011, 6:52 p.m.
Message ID <1683929363.797422.1309200732908.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com>
Download mbox | patch
Permalink /patch/102259/
State New
Headers show

Comments

Kai Tietz - June 27, 2011, 6:52 p.m.
Hello,

this patch tries to sink conversions for comparisons patterns:
a) (type) X cmp (type) Y => x cmp y.
b) (type) X cmp CST => x cmp ((type-x) CST).
c) CST cmp (type) X => ((type-x) CST) cmp x.

This patch just allows type sinking for the case that type-precision of type is wider or equal to type-precision of type-x. Or if type and type-x have same signess and CST fits into type-x. For cmp operation is == or !=, we allow also that type and type-x have different signess, as long as CST fits into type-x without truncation. 

ChangeLog

2011-06-27  Kai Tietz  <ktietz@redhat.com>

        * tree-ssa-forwprop.c (forward_propagate_into_comparision):
        Sink types within comparison operands, if suitable.

Bootstrapped and regression tested for x86_64-pc-linux-gnu. Ok for apply?

Regards,
Kai
Richard Guenther - June 28, 2011, 8:45 a.m.
On Mon, Jun 27, 2011 at 8:52 PM, Kai Tietz <ktietz@redhat.com> wrote:
> Hello,
>
> this patch tries to sink conversions for comparisons patterns:
> a) (type) X cmp (type) Y => x cmp y.
> b) (type) X cmp CST => x cmp ((type-x) CST).
> c) CST cmp (type) X => ((type-x) CST) cmp x.
>
> This patch just allows type sinking for the case that type-precision of type is wider or equal to type-precision of type-x. Or if type and type-x have same signess and CST fits into type-x. For cmp operation is == or !=, we allow also that type and type-x have different signess, as long as CST fits into type-x without truncation.
>
> ChangeLog
>
> 2011-06-27  Kai Tietz  <ktietz@redhat.com>
>
>        * tree-ssa-forwprop.c (forward_propagate_into_comparision):
>        Sink types within comparison operands, if suitable.
>
> Bootstrapped and regression tested for x86_64-pc-linux-gnu. Ok for apply?

Hmm, why does fold_widened_comparison and fold_sign_changed_comparison
not handle these cases?  We already dispatch to fold in this function,
so this is a case where we'd want fold to be improved.  You didn't add
testcases - do you have some that are not handled by fold already?

Thanks,
Richard.

> Regards,
> Kai
>
Kai Tietz - June 28, 2011, 10:16 a.m.
----- Original Message -----
From: "Richard Guenther" <richard.guenther@gmail.com>
To: "Kai Tietz" <ktietz@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Sent: Tuesday, June 28, 2011 10:45:20 AM
Subject: Re: [patch tree-optimization]: Try to do type sinking on comparisons

On Mon, Jun 27, 2011 at 8:52 PM, Kai Tietz <ktietz@redhat.com> wrote:
> Hello,
>
> this patch tries to sink conversions for comparisons patterns:
> a) (type) X cmp (type) Y => x cmp y.
> b) (type) X cmp CST => x cmp ((type-x) CST).
> c) CST cmp (type) X => ((type-x) CST) cmp x.
>
> This patch just allows type sinking for the case that type-precision of type is wider or equal to type-precision of type-x. Or if type and type-x have same signess and CST fits into type-x. For cmp operation is == or !=, we allow also that type and type-x have different signess, as long as CST fits into type-x without truncation.
>
> ChangeLog
>
> 2011-06-27  Kai Tietz  <ktietz@redhat.com>
>
>        * tree-ssa-forwprop.c (forward_propagate_into_comparision):
>        Sink types within comparison operands, if suitable.
>
> Bootstrapped and regression tested for x86_64-pc-linux-gnu. Ok for apply?

Hmm, why does fold_widened_comparison and fold_sign_changed_comparison
not handle these cases?  We already dispatch to fold in this function,
so this is a case where we'd want fold to be improved.  You didn't add
testcases - do you have some that are not handled by fold already?

Thanks,
Richard.

> Regards,
> Kai
>

Well, I noticed this kind of patterns in case for boolification of comparisons.  They seem to appear if one of the comparison operands itself has type-promotion and has non-trivial tree.
Nevertheless I am about to rework this patch a bit, as it has some issues about type-truncation, if outer type has smaller precision then inner type. I think for now
it would be ok to do operations only for case that inner type has smaller or equal precision then outer type, and inner and outer type are of integer kind.
In the other case we might want to transform such integer-comparisons from ((char) a:int) cmp CST to (a:int & (char) ~0) cmp (char) CST. So we are truncation proper for comparison.

Nevertheless the more interesting part is, if inner type has smaller or equal precision to outer type.

Kai

Patch

Index: gcc-head/gcc/tree-ssa-forwprop.c
===================================================================
--- gcc-head.orig/gcc/tree-ssa-forwprop.c
+++ gcc-head/gcc/tree-ssa-forwprop.c
@@ -432,11 +432,73 @@  forward_propagate_into_comparison_1 (loc
   /* If that wasn't successful either, try both operands.  */
   if (rhs0 != NULL_TREE
       && rhs1 != NULL_TREE)
-    tmp = combine_cond_expr_cond (loc, code, type,
-				  rhs0, rhs1,
-				  !(single_use0_p && single_use1_p));
-
-  return tmp;
+    {
+      tmp = combine_cond_expr_cond (loc, code, type,
+				    rhs0, rhs1,
+				    !(single_use0_p && single_use1_p));
+      if (tmp)
+        return tmp;
+    }
+  /* Sink types of comparison, if (type) CMP (type) Y, if types
+     of X and Y are compatible.  */
+  if (rhs0 != NULL_TREE && rhs1 != NULL_TREE
+      && CONVERT_EXPR_CODE_P (TREE_CODE (rhs0))
+      && CONVERT_EXPR_CODE_P (TREE_CODE (rhs1))
+      && types_compatible_p (TREE_TYPE (TREE_OPERAND (rhs0, 0)),
+			     TREE_TYPE (TREE_OPERAND (rhs1, 0)))
+      /* Make sure that the conversion widens the operands, or has same
+	 precision.  */
+      && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (rhs0, 0)))
+	   <= TYPE_PRECISION (TREE_TYPE (rhs0)))
+      && (code == EQ_EXPR || code == NE_EXPR
+	  || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (rhs0, 0)))
+	     == TYPE_UNSIGNED (TREE_TYPE (rhs0))))
+     return fold_build2_loc (loc, code, type, TREE_OPERAND (rhs0, 0),
+			     TREE_OPERAND (rhs1, 0));
+  /* Check if (type) X cmp CST can be convered into
+     (type) (X cmp (type-x) CST).  */
+  if (rhs0 != NULL_TREE
+      && CONVERT_EXPR_CODE_P (TREE_CODE (rhs0))
+      && TREE_CODE (op1) == INTEGER_CST
+      && INTEGRAL_TYPE_P (TREE_OPERAND (rhs0, 0))
+      && INTEGRAL_TYPE_P (rhs0)
+      && (code == EQ_EXPR || code == NE_EXPR
+	  || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (rhs0, 0)))
+	     == TYPE_UNSIGNED (TREE_TYPE (rhs0))))
+    {
+      tree folded_int = fold_convert_loc (loc,
+					  TREE_TYPE (TREE_OPERAND (rhs0, 0)),
+					  op1);
+      /* Is the back casted folded integer identical to original
+	 integer?  */
+      if (operand_equal_p (op1, fold_convert_loc (loc, TREE_TYPE (op0),
+						  folded_int), 0))
+        return fold_build2_loc (loc, code, type, TREE_OPERAND (rhs0, 0),
+				folded_int);
+    }
+
+  /* Check if CST op (type) X can be converted into
+     (type) ((type-x) CST op X).  */
+  if (rhs1 != NULL_TREE
+      && CONVERT_EXPR_CODE_P (TREE_CODE (rhs1))
+      && TREE_CODE (op0) == INTEGER_CST
+      && INTEGRAL_TYPE_P (TREE_OPERAND (rhs1, 0))
+      && INTEGRAL_TYPE_P (rhs1)
+      && (code == EQ_EXPR || code == NE_EXPR
+	  || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (rhs1, 0)))
+	     == TYPE_UNSIGNED (TREE_TYPE (rhs1))))
+    {
+      tree folded_int = fold_convert_loc (loc,
+					  TREE_TYPE (TREE_OPERAND (rhs1, 0)),
+					  op0);
+      /* Is the back casted folded integer identical to original
+	 integer?  */
+      if (operand_equal_p (op0, fold_convert_loc (loc, TREE_TYPE (op1),
+						  folded_int), 0))
+        return fold_build2_loc (loc, code, type, folded_int,
+				TREE_OPERAND (rhs1, 0));
+    }
+  return NULL_TREE;
 }
 
 /* Propagate from the ssa name definition statements of the assignment