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;