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
This commit is contained in:
parent
d92562770a
commit
ebeadd9141
8 changed files with 144 additions and 2 deletions
|
@ -1,3 +1,14 @@
|
|||
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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
9
gcc/testsuite/gcc.target/i386/pr49715-1.c
Normal file
9
gcc/testsuite/gcc.target/i386/pr49715-1.c
Normal file
|
@ -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 } } */
|
12
gcc/testsuite/gcc.target/i386/pr49715-2.c
Normal file
12
gcc/testsuite/gcc.target/i386/pr49715-2.c
Normal file
|
@ -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 } } */
|
101
gcc/tree-vrp.c
101
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue