On Thu, 21 Jul 2011, Joseph S. Myers wrote: > On Thu, 21 Jul 2011, Richard Henderson wrote: > > > On 07/21/2011 08:09 AM, Richard Guenther wrote: > > > + /* It's not interesting to widen anything smaller than SImode. */ > > > + if (TYPE_PRECISION (TREE_TYPE (rhs1)) < GET_MODE_PRECISION (SImode) > > > + || (!TYPE_UNSIGNED (TREE_TYPE (rhs1)) > > > + && TYPE_PRECISION (TREE_TYPE (rhs1)) == GET_MODE_PRECISION > > > (SImode))) > > > + return false; > > > > Hard-coding SImode? Really? You might as well hard-code 32. At least > > that's "more correct" when someone does have BITS_PER_UNIT != 8. > > I'd guess this is intended to match the hardcoding of SImode in > optabs.c:expand_float - both of which should maybe use the same target > hook (that defaults to using SImode) rather than hardcoding SImode. > (Strictly, in the model that the very existence of SImode should be > target-dependent, the default hook definition would go in a file in > config/ that's shared by all targets with BITS_PER_UNIT == 8 and the > classic set of machine modes, rather than in targhooks.c, but I don't > think we need to worry about that for now.)
Hm, of course some targets define unsigned float expanders just do do the complicated stuff manually (which is why I didn't look at the conversion optabs). I assume that if a target can do an unsigned -> float conversion it can also to a signed -> float conversion of the same source mode (probably a safe assumption?). Patch also handling wider modes and not starting with SImode but the mode of int: 2011-07-21 Richard Guenther <rguent...@suse.de> PR tree-optimization/49715 * tree-vrp.c (simplify_float_conversion_using_ranges): New function. (simplify_stmt_using_ranges): Call it. * 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 } } */