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?

(note that I can't commit)

--
Marc Glisse
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) || code2 == FLOAT_EXPR
+      || code2 == FIX_TRUNC_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);
@@ -2453,13 +2456,16 @@ combine_conversions (gimple_stmt_iterato
       /* In addition to the cases of two conversions in a row
         handled below, if we are converting something to its own
         type via an object of identical or wider precision, neither
         conversion is needed.  */
       if (useless_type_conversion_p (type, inside_type)
-         && (((inter_int || inter_ptr) && final_int)
-             || (inter_float && final_float))
-         && inter_prec >= final_prec)
+         && (((((inter_int || inter_ptr) && final_int)
+               || (inter_float && final_float))
+              && inter_prec >= final_prec)
+             || (inside_int && final_int && inter_float
+                 && REAL_MODE_FORMAT (TYPE_MODE (inter_type))->p
+                    >= (int) inside_prec - !inside_unsignedp)))
        {
          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;

Reply via email to