diff options
author | Richard Guenther <rguenther@suse.de> | 2011-07-25 08:30:46 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2011-07-25 08:30:46 +0000 |
commit | ebeadd9141ed7d9335e1612029ba3b6115e1bb26 (patch) | |
tree | bb094ce476757d492245a62154085f6ad83c0612 /gcc | |
parent | d92562770a09498c0e39214b59ecfd3725198a8d (diff) | |
download | gcc-ebeadd9141ed7d9335e1612029ba3b6115e1bb26.zip gcc-ebeadd9141ed7d9335e1612029ba3b6115e1bb26.tar.gz gcc-ebeadd9141ed7d9335e1612029ba3b6115e1bb26.tar.bz2 |
re PR tree-optimization/49715 (Could do more efficient unsigned-to-float to conversions based on range information)
2011-07-25 Richard Guenther <rguenther@suse.de>
PR tree-optimization/49715
* tree-vrp.c: Include expr.h and optabs.h.
(range_fits_type_): New function.
(simplify_float_conversion_using_ranges): Likewise.
(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.
From-SVN: r176735
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/optabs.c | 2 | ||||
-rw-r--r-- | gcc/optabs.h | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr49715-1.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr49715-2.c | 12 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 101 |
8 files changed, 144 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 47b1b3b..cf4463d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2011-07-25 Richard Guenther <rguenther@suse.de> + PR tree-optimization/49715 + * tree-vrp.c: Include expr.h and optabs.h. + (range_fits_type_): New function. + (simplify_float_conversion_using_ranges): Likewise. + (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. + +2011-07-25 Richard Guenther <rguenther@suse.de> + * tree-vrp.c (num_vr_values, values_propagated): New global vars. (get_value_range): For out-of-range SSA names or names created after propagation return a read-only varying range. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index b215cd6..88d8513 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2504,7 +2504,7 @@ tree-vrp.o : tree-vrp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(GGC_H) \ $(BASIC_BLOCK_H) tree-ssa-propagate.h $(FLAGS_H) $(TREE_DUMP_H) \ $(CFGLOOP_H) $(SCEV_H) $(TIMEVAR_H) intl.h tree-pretty-print.h \ - gimple-pretty-print.h gimple-fold.h + gimple-pretty-print.h gimple-fold.h $(OPTABS_H) $(EXPR_H) tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \ $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \ diff --git a/gcc/optabs.c b/gcc/optabs.c index 915a45e..12717b6 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4626,7 +4626,7 @@ can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode, return CODE_FOR_nothing; } -static enum insn_code +enum insn_code can_float_p (enum machine_mode fltmode, enum machine_mode fixmode, int unsignedp) { diff --git a/gcc/optabs.h b/gcc/optabs.h index 477fce3..c7cb123 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -849,6 +849,9 @@ extern void expand_fixed_convert (rtx, rtx, int, int); /* Generate code for a FLOAT_EXPR. */ extern void expand_float (rtx, rtx, int); +/* Return the insn_code for a FLOAT_EXPR. */ +enum insn_code can_float_p (enum machine_mode, enum machine_mode, int); + /* Generate code for a FIX_EXPR. */ extern void expand_fix (rtx, rtx, int); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9eb5de6..4869657 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-07-25 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/49715 + * gcc.target/i386/pr49715-1.c: New testcase. + * gcc.target/i386/pr49715-2.c: Likewise. + 2011-07-23 Jason Merrill <jason@redhat.com> * g++.dg/cpp0x/decltype21.C: Add 49823 examples. diff --git a/gcc/testsuite/gcc.target/i386/pr49715-1.c b/gcc/testsuite/gcc.target/i386/pr49715-1.c new file mode 100644 index 0000000..d959f9e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr49715-1.c @@ -0,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 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr49715-2.c b/gcc/testsuite/gcc.target/i386/pr49715-2.c new file mode 100644 index 0000000..3fc8e4e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr49715-2.c @@ -0,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 } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 380c17f..c6a4c44 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -40,6 +40,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-propagate.h" #include "tree-chrec.h" #include "gimple-fold.h" +#include "expr.h" +#include "optabs.h" /* Type of value ranges. See value_range_d for a description of these @@ -7415,6 +7417,99 @@ simplify_conversion_using_ranges (gimple stmt) return true; } +/* Return whether the value range *VR fits in an integer type specified + by PRECISION and UNSIGNED_P. */ + +static bool +range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p) +{ + double_int tem; + + /* 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; + + tem = double_int_ext (tree_to_double_int (vr->min), precision, unsigned_p); + if (!double_int_equal_p (tree_to_double_int (vr->min), tem)) + return false; + + tem = double_int_ext (tree_to_double_int (vr->max), precision, unsigned_p); + if (!double_int_equal_p (tree_to_double_int (vr->max), tem)) + return false; + + 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 fltmode = TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))); + enum machine_mode mode; + tree tem; + gimple conv; + + /* 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; + + /* First check if we can use a signed type in place of an unsigned. */ + if (TYPE_UNSIGNED (TREE_TYPE (rhs1)) + && (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)), 0) + != CODE_FOR_nothing) + && range_fits_type_p (vr, GET_MODE_PRECISION + (TYPE_MODE (TREE_TYPE (rhs1))), 0)) + mode = TYPE_MODE (TREE_TYPE (rhs1)); + /* If we can do the conversion in the current input mode do nothing. */ + else if (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)), + TYPE_UNSIGNED (TREE_TYPE (rhs1)))) + return false; + /* Otherwise search for a mode we can use, starting from the narrowest + integer mode available. */ + else + { + mode = GET_CLASS_NARROWEST_MODE (MODE_INT); + do + { + /* If we cannot do a signed conversion to float from mode + or if the value-range does not fit in the signed type + try with a wider mode. */ + if (can_float_p (fltmode, mode, 0) != CODE_FOR_nothing + && range_fits_type_p (vr, GET_MODE_PRECISION (mode), 0)) + break; + + mode = GET_MODE_WIDER_MODE (mode); + /* But do not widen the input. Instead leave that to the + optabs expansion code. */ + 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 @@ -7474,6 +7569,12 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) 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; } |