On Wed, 25 Apr 2012, Richard Guenther wrote:

On Wed, Apr 25, 2012 at 10:12 AM, Marc Glisse <marc.gli...@inria.fr> wrote:
Hello,

a conversion like int->double->int is just the identity, as long as double
is big enough to represent all ints exactly. The most natural way I found to
do this optimization is the attached:

2012-04-25  Marc Glisse  <marc.gli...@inria.fr>

       PR middle-end/27139
       * tree-ssa-forwprop.c (combine_conversions): Handle INT->FP->INT.

Does the approach make sense? I don't know that code, and adding FLOAT_EXPR
/ FIX_TRUNC_EXPR was a bit of guesswork. The precision of double could be
multiplied by log2(base), but not doing it is safe. If the approach is ok, I
could extend it so int->double->long also skips the intermediate conversion.

Bootstrapped and regression tested on linux-x86_64.

Should I try and write a testcase for a specific target checking for
specific asm instructions there, or is there a better way?

Well, scanning the forwprop dump for example.

Btw, I think not munging this new case into the existing CONVERT_EXPR_P
code would be better - it makes the code (even) harder to understand and
I'm not convinced that adding FLOAT_EXPR/FIX_TRUNC_EXPR handling
does not wreck any assumptions in that code.

It also seems that for DECIMAL_FLOAT_TYPE_P the transform is always
valid?

Richard.

(note that I can't commit)

Here is take 2 on this patch, which seems cleaner. Bootstrapped and regression tested.

gcc/ChangeLog
2012-04-25  Marc Glisse  <marc.gli...@inria.fr>

        PR middle-end/27139
        * tree-ssa-forwprop.c (combine_conversions): Handle INT->FP->INT.

gcc/testsuite/ChangeLog
2012-04-25  Marc Glisse  <marc.gli...@inria.fr>

        PR middle-end/27139
        * gcc.dg/tree-ssa/forwprop-18.c: New test.


In my patch, the lines with gimple_assign_* are vaguely guessed from what is around, I don't pretend to understand them.


While doing this, I noticed what I think is a mistake in a comment:

--- gcc/real.c      (revision 186761)
+++ gcc/real.c      (working copy)
@@ -2814,11 +2814,11 @@ significand_size (enum machine_mode mode
     return 0;

   if (fmt->b == 10)
     {
       /* Return the size in bits of the largest binary value that can be
-        held by the decimal coefficient for this mode.  This is one more
+        held by the decimal coefficient for this mode.  This is one less
         than the number of bits required to hold the largest coefficient
         of this mode.  */
       double log2_10 = 3.3219281;
       return fmt->p * log2_10;
     }

--
Marc Glisse
Index: testsuite/gcc.dg/tree-ssa/forwprop-18.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/forwprop-18.c     (revision 0)
+++ testsuite/gcc.dg/tree-ssa/forwprop-18.c     (revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-forwprop1" } */
+
+short f1(short n)
+{
+  return (double)n;
+}
+long f2(short n)
+{
+  return (double)n;
+}
+
+long g1(long n)
+{
+  return (float)n;
+}
+short g2(long n)
+{
+  return (float)n;
+}
+
+/* { dg-final { scan-tree-dump-times "\\\(float\\\)" 2 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not "\\\(double\\\)" "forwprop1" } } */
+/* { dg-final { cleanup-tree-dump "forwprop1" } } */

Property changes on: testsuite/gcc.dg/tree-ssa/forwprop-18.c
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision URL
Added: svn:eol-style
   + native

Index: tree-ssa-forwprop.c
===================================================================
--- tree-ssa-forwprop.c (revision 186761)
+++ tree-ssa-forwprop.c (working copy)
@@ -2403,10 +2403,11 @@ combine_conversions (gimple_stmt_iterato
 {
   gimple stmt = gsi_stmt (*gsi);
   gimple def_stmt;
   tree op0, lhs;
   enum tree_code code = gimple_assign_rhs_code (stmt);
+  enum tree_code code2;
 
   gcc_checking_assert (CONVERT_EXPR_CODE_P (code)
                       || code == FLOAT_EXPR
                       || code == FIX_TRUNC_EXPR);
 
@@ -2423,11 +2424,13 @@ combine_conversions (gimple_stmt_iterato
 
   def_stmt = SSA_NAME_DEF_STMT (op0);
   if (!is_gimple_assign (def_stmt))
     return 0;
 
-  if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
+  code2 = gimple_assign_rhs_code (def_stmt);
+
+  if (CONVERT_EXPR_CODE_P (code2))
     {
       tree defop0 = gimple_assign_rhs1 (def_stmt);
       tree type = TREE_TYPE (lhs);
       tree inside_type = TREE_TYPE (defop0);
       tree inter_type = TREE_TYPE (op0);
@@ -2552,10 +2555,45 @@ combine_conversions (gimple_stmt_iterato
            gimple_assign_set_rhs_from_tree (gsi, tem);
          update_stmt (gsi_stmt (*gsi));
          return 1;
        }
     }
+  else if (code == FIX_TRUNC_EXPR && code2 == FLOAT_EXPR)
+    {
+      tree defop0 = gimple_assign_rhs1 (def_stmt);
+      tree type = TREE_TYPE (lhs);
+      tree inside_type = TREE_TYPE (defop0);
+      tree inter_type = TREE_TYPE (op0);
+      int inside_int = INTEGRAL_TYPE_P (inside_type);
+      int inter_float = FLOAT_TYPE_P (inter_type);
+      int final_int = INTEGRAL_TYPE_P (type);
+      int inside_prec = TYPE_PRECISION (inside_type);
+      int inside_unsignedp = TYPE_UNSIGNED (inside_type);
+
+      /* If we are converting an integer to a floating-point that can
+        represent it exactly and back to an integer, we can skip the
+        floating-point conversion.  */
+      if (inside_int && inter_float && final_int &&
+          significand_size (TYPE_MODE (inter_type))
+          >= inside_prec - !inside_unsignedp)
+        {
+         if (useless_type_conversion_p (type, inside_type))
+           {
+             gimple_assign_set_rhs1 (stmt, unshare_expr (defop0));
+             gimple_assign_set_rhs_code (stmt, TREE_CODE (defop0));
+             update_stmt (stmt);
+             return remove_prop_source_from_use (op0) ? 2 : 1;
+           }
+         else
+           {
+             gimple_assign_set_rhs1 (stmt, defop0);
+             gimple_assign_set_rhs_code (stmt, CONVERT_EXPR);
+             update_stmt (stmt);
+             return remove_prop_source_from_use (op0) ? 2 : 1;
+           }
+       }
+    }
 
   return 0;
 }
 
 /* Main entry point for the forward propagation and statement combine

Reply via email to