On Thu, 21 Jul 2011, Joseph S. Myers wrote:

> On Thu, 21 Jul 2011, Richard Guenther wrote:
> 
> > Patch also handling wider modes and not starting with SImode but
> > the mode of int:
> 
> Use of target int for anything not about C ABIs is certainly wrong.  This 
> might be about what operations the target does efficiently, or what 
> functions are present in libgcc (both of which would be functions of 
> machine modes), but it's not about the choice of C int.

Ok.  Given rths last suggestion I'm testing the following which
checks all integer modes (but never will widen - optabs.c will do
that if it turns out to be profitable).

Richard.

2011-07-22  Richard Guenther  <rguent...@suse.de>

        PR tree-optimization/49715
        * tree-vrp.c: Include expr.h and optabs.h.
        (simplify_float_conversion_using_ranges): New function.
        (simplify_stmt_using_ranges): Call it.
        * Makefile.in (tree-vrp.o): Add $(EXPR_H) and $(OPTABS_H) dependencies.
        * optabs.c (can_float_p): Export.
        * optabs.h (can_float_p): Declare.

        * gcc.target/i386/pr49715-1.c: New testcase.
        * gcc.target/i386/pr49715-2.c: Likewise.

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c.orig 2011-07-21 16:46:39.000000000 +0200
--- gcc/tree-vrp.c      2011-07-21 17:37:09.000000000 +0200
*************** simplify_conversion_using_ranges (gimple
*** 7448,7453 ****
--- 7448,7516 ----
    return true;
  }
  
+ /* Simplify a conversion from integral SSA name to float in STMT.  */
+ 
+ static bool
+ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple 
stmt)
+ {
+   tree rhs1 = gimple_assign_rhs1 (stmt);
+   value_range_t *vr = get_value_range (rhs1);
+   enum machine_mode mode;
+   tree tem;
+   gimple conv;
+ 
+   /* It's not interesting to widen anything.  */
+   if (TYPE_PRECISION (TREE_TYPE (rhs1)) < TYPE_PRECISION (integer_type_node)
+       || (!TYPE_UNSIGNED (TREE_TYPE (rhs1))
+         && (TYPE_PRECISION (TREE_TYPE (rhs1))
+             == TYPE_PRECISION (integer_type_node))))
+     return false;
+ 
+   /* We can only handle constant ranges.  */
+   if (vr->type != VR_RANGE
+       || TREE_CODE (vr->min) != INTEGER_CST
+       || TREE_CODE (vr->max) != INTEGER_CST)
+     return false;
+ 
+   /* Search for a mode we can use.  Start with that of int.  */
+   mode = TYPE_MODE (integer_type_node);
+   do
+     {
+       double_int tem;
+ 
+       tem = double_int_ext (tree_to_double_int (vr->min),
+                           GET_MODE_PRECISION (mode), 0);
+       if (double_int_equal_p (tree_to_double_int (vr->min), tem))
+       {
+         tem = double_int_ext (tree_to_double_int (vr->max),
+                               GET_MODE_PRECISION (mode), 0);
+         if (double_int_equal_p (tree_to_double_int (vr->max), tem))
+           break;
+       }
+ 
+       mode = GET_MODE_WIDER_MODE (mode);
+       if (GET_MODE_PRECISION (mode) > TYPE_PRECISION (TREE_TYPE (rhs1)))
+       return false;
+     }
+   while (mode != VOIDmode);
+ 
+   if (mode == VOIDmode)
+     return false;
+ 
+   /* It works, insert a truncation or sign-change before the
+      float conversion.  */
+   tem = create_tmp_var (build_nonstandard_integer_type
+                         (GET_MODE_PRECISION (mode), 0), NULL);
+   conv = gimple_build_assign_with_ops (NOP_EXPR, tem, rhs1, NULL_TREE);
+   tem = make_ssa_name (tem, conv);
+   gimple_assign_set_lhs (conv, tem);
+   gsi_insert_before (gsi, conv, GSI_SAME_STMT);
+   gimple_assign_set_rhs1 (stmt, tem);
+   update_stmt (stmt);
+ 
+   return true;
+ }
+ 
  /* Simplify STMT using ranges if possible.  */
  
  static bool
*************** simplify_stmt_using_ranges (gimple_stmt_
*** 7507,7512 ****
--- 7570,7581 ----
            return simplify_conversion_using_ranges (stmt);
          break;
  
+       case FLOAT_EXPR:
+         if (TREE_CODE (rhs1) == SSA_NAME
+             && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
+           return simplify_float_conversion_using_ranges (gsi, stmt);
+         break;
+ 
        default:
          break;
        }
Index: gcc/testsuite/gcc.target/i386/pr49715-1.c
===================================================================
*** /dev/null   1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.target/i386/pr49715-1.c   2011-07-21 16:55:57.000000000 
+0200
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -msse -mfpmath=sse" } */
+ 
+ float func(unsigned x)
+ {
+   return (x & 0xfffff) * 0.01f;
+ }
+ 
+ /* { dg-final { scan-assembler-times "cvtsi2ss" 1 } } */
Index: gcc/testsuite/gcc.target/i386/pr49715-2.c
===================================================================
*** /dev/null   1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.target/i386/pr49715-2.c   2011-07-21 17:46:05.000000000 
+0200
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+ /* { dg-require-effective-target lp64 } */
+ /* { dg-options "-O2" } */
+ 
+ double func(unsigned long long x)
+ {
+   if (x <= 0x7ffffffffffffffeULL)
+     return (x + 1) * 0.01;
+   return 0.0;
+ }
+ 
+ /* { dg-final { scan-assembler-times "cvtsi2sdq" 1 } } */

Reply via email to