Hello, this patch sink type conversions in forward-propagate for the following patterns: - ((type) X) op ((type) Y): If X and Y have compatible types. - ((type) X) op CST: If the conversion of (type) ((type-x) CST) == CST and X has integral type. - CST op ((type) X): If the conversion of (type) ((type-x) CST) == CST and X has integral type.
Additionally it fixes another issue shown by this type-sinking in bswap detection. The bswap pattern matching algorithm goes for the first hit, and not tries to seek for best hit. So we search here two times. First for di case (if present) and then for si mode case. ChangeLog 2011-06-27 Kai Tietz <kti...@redhat.com> * tree-ssa-forwprop.c (simplify_bitwise_binary): Improve type sinking. * tree-ssa-math-opts.c (execute_optimize_bswap): Separate search for di/si mode patterns for finding widest match. Bootstrapped and regression tested for x86_64-pc-linux-gnu. Ok for apply? Regards, Kai
Index: gcc-head/gcc/tree-ssa-forwprop.c =================================================================== --- gcc-head.orig/gcc/tree-ssa-forwprop.c +++ gcc-head/gcc/tree-ssa-forwprop.c @@ -1624,30 +1624,56 @@ simplify_bitwise_binary (gimple_stmt_ite /* If the first argument is an SSA name that is itself a result of a typecast of an ADDR_EXPR to an integer, feed the ADDR_EXPR to the folder rather than the ssa name. */ - if (code == BIT_AND_EXPR - && TREE_CODE (arg2) == INTEGER_CST + if (TREE_CODE (arg2) == INTEGER_CST && TREE_CODE (arg1) == SSA_NAME) { gimple def = SSA_NAME_DEF_STMT (arg1); tree op = arg1; + tree opp = NULL_TREE; + tree folded_int = NULL_TREE; - /* ??? This looks bogus - the conversion could be truncating. */ if (is_gimple_assign (def) && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)) && INTEGRAL_TYPE_P (TREE_TYPE (arg1))) { - tree opp = gimple_assign_rhs1 (def); - if (TREE_CODE (opp) == ADDR_EXPR) + opp = gimple_assign_rhs1 (def); + folded_int = fold_convert_loc (gimple_location (stmt), + TREE_TYPE (opp), arg2); + /* Check if integer value remains the same on cast back + to original type. */ + if (!operand_equal_p (arg2, fold_convert (TREE_TYPE (arg1), + folded_int), 0)) + folded_int = NULL_TREE; + if (TREE_CODE (opp) == ADDR_EXPR && folded_int) op = opp; } + if (code == BIT_AND_EXPR) + { + res = fold_binary_loc (gimple_location (stmt), + BIT_AND_EXPR, + TREE_TYPE (gimple_assign_lhs (stmt)), + op, arg2); + if (res && is_gimple_min_invariant (res)) + { + gimple_assign_set_rhs_from_tree (gsi, res); + update_stmt (stmt); + return true; + } + } - res = fold_binary_loc (gimple_location (stmt), - BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)), - op, arg2); - if (res && is_gimple_min_invariant (res)) - { - gimple_assign_set_rhs_from_tree (gsi, res); - update_stmt (stmt); + /* Convert (type) X & CST -> (type) (X & (typeof-X) CST), + if conversion of CST is reversible. */ + if (opp != NULL_TREE && folded_int != NULL_TREE) + { + gimple newop; + tree tem = create_tmp_reg (TREE_TYPE (opp), NULL); + newop = gimple_build_assign_with_ops (code, tem, opp, folded_int); + tem = make_ssa_name (tem, newop); + gimple_assign_set_lhs (newop, tem); + gsi_insert_before (gsi, newop, GSI_SAME_STMT); + gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR, + tem, NULL_TREE, NULL_TREE); + update_stmt (gsi_stmt (*gsi)); return true; } } @@ -1682,10 +1708,11 @@ simplify_bitwise_binary (gimple_stmt_ite if (CONVERT_EXPR_CODE_P (def1_code) && CONVERT_EXPR_CODE_P (def2_code) && types_compatible_p (TREE_TYPE (def1_arg1), TREE_TYPE (def2_arg1)) - /* Make sure that the conversion widens the operands or that it - changes the operation to a bitfield precision. */ + /* Make sure that the conversion widens the operands, or has same + precision, or that it changes the operation to a bitfield + precision. */ && ((TYPE_PRECISION (TREE_TYPE (def1_arg1)) - < TYPE_PRECISION (TREE_TYPE (arg1))) + <= TYPE_PRECISION (TREE_TYPE (arg1))) || (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (arg1))) != MODE_INT) || (TYPE_PRECISION (TREE_TYPE (arg1)) Index: gcc-head/gcc/tree-ssa-math-opts.c =================================================================== --- gcc-head.orig/gcc/tree-ssa-math-opts.c +++ gcc-head/gcc/tree-ssa-math-opts.c @@ -1785,6 +1785,7 @@ execute_optimize_bswap (void) bool bswap32_p, bswap64_p; bool changed = false; tree bswap32_type = NULL_TREE, bswap64_type = NULL_TREE; + int iter = 0; if (BITS_PER_UNIT != 8) return 0; @@ -1815,108 +1816,123 @@ execute_optimize_bswap (void) bswap64_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); } + /* Is 64-bit bswap not supported? */ + if (!bswap64_p) + iter = 1; + memset (&bswap_stats, 0, sizeof (bswap_stats)); - FOR_EACH_BB (bb) + /* If iter has value of zero, then seek for 64-bit bswap, + If iter has value of one, then seek for 32-bit bswap. */ + for (; iter < 2; iter++) { - gimple_stmt_iterator gsi; + FOR_EACH_BB (bb) + { + gimple_stmt_iterator gsi; - for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple stmt = gsi_stmt (gsi); - tree bswap_src, bswap_type; - tree bswap_tmp; - tree fndecl = NULL_TREE; - int type_size; - gimple call; - - if (!is_gimple_assign (stmt) - || gimple_assign_rhs_code (stmt) != BIT_IOR_EXPR) - continue; + for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + tree bswap_src, bswap_type; + tree bswap_tmp; + tree fndecl = NULL_TREE; + int type_size; + gimple call; + + if (!is_gimple_assign (stmt) + || gimple_assign_rhs_code (stmt) != BIT_IOR_EXPR) + continue; - type_size = TYPE_PRECISION (gimple_expr_type (stmt)); + type_size = TYPE_PRECISION (gimple_expr_type (stmt)); - switch (type_size) - { - case 32: - if (bswap32_p) + switch (type_size) { - fndecl = built_in_decls[BUILT_IN_BSWAP32]; - bswap_type = bswap32_type; - } - break; - case 64: - if (bswap64_p) - { - fndecl = built_in_decls[BUILT_IN_BSWAP64]; - bswap_type = bswap64_type; + case 32: + if (iter != 1) + continue; + if (bswap32_p) + { + fndecl = built_in_decls[BUILT_IN_BSWAP32]; + bswap_type = bswap32_type; + } + break; + case 64: + if (iter != 0) + continue; + if (bswap64_p) + { + fndecl = built_in_decls[BUILT_IN_BSWAP64]; + bswap_type = bswap64_type; + } + break; + default: + continue; } - break; - default: - continue; - } - if (!fndecl) - continue; + if (!fndecl) + continue; - bswap_src = find_bswap (stmt); + bswap_src = find_bswap (stmt); - if (!bswap_src) - continue; + if (!bswap_src) + continue; - changed = true; - if (type_size == 32) - bswap_stats.found_32bit++; - else - bswap_stats.found_64bit++; + changed = true; + if (type_size == 32) + bswap_stats.found_32bit++; + else + bswap_stats.found_64bit++; - bswap_tmp = bswap_src; + bswap_tmp = bswap_src; - /* Convert the src expression if necessary. */ - if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp), bswap_type)) - { - gimple convert_stmt; + /* Convert the src expression if necessary. */ + if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp), + bswap_type)) + { + gimple convert_stmt; - bswap_tmp = create_tmp_var (bswap_type, "bswapsrc"); - add_referenced_var (bswap_tmp); - bswap_tmp = make_ssa_name (bswap_tmp, NULL); - - convert_stmt = gimple_build_assign_with_ops ( - CONVERT_EXPR, bswap_tmp, bswap_src, NULL); - gsi_insert_before (&gsi, convert_stmt, GSI_SAME_STMT); - } + bswap_tmp = create_tmp_var (bswap_type, "bswapsrc"); + add_referenced_var (bswap_tmp); + bswap_tmp = make_ssa_name (bswap_tmp, NULL); + + convert_stmt = gimple_build_assign_with_ops ( + CONVERT_EXPR, bswap_tmp, bswap_src, NULL); + gsi_insert_before (&gsi, convert_stmt, GSI_SAME_STMT); + } - call = gimple_build_call (fndecl, 1, bswap_tmp); + call = gimple_build_call (fndecl, 1, bswap_tmp); - bswap_tmp = gimple_assign_lhs (stmt); + bswap_tmp = gimple_assign_lhs (stmt); - /* Convert the result if necessary. */ - if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp), bswap_type)) - { - gimple convert_stmt; + /* Convert the result if necessary. */ + if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp), + bswap_type)) + { + gimple convert_stmt; - bswap_tmp = create_tmp_var (bswap_type, "bswapdst"); - add_referenced_var (bswap_tmp); - bswap_tmp = make_ssa_name (bswap_tmp, NULL); - convert_stmt = gimple_build_assign_with_ops ( - CONVERT_EXPR, gimple_assign_lhs (stmt), bswap_tmp, NULL); - gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT); - } + bswap_tmp = create_tmp_var (bswap_type, "bswapdst"); + add_referenced_var (bswap_tmp); + bswap_tmp = make_ssa_name (bswap_tmp, NULL); + convert_stmt = gimple_build_assign_with_ops ( + CONVERT_EXPR, gimple_assign_lhs (stmt), + bswap_tmp, NULL); + gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT); + } - gimple_call_set_lhs (call, bswap_tmp); + gimple_call_set_lhs (call, bswap_tmp); - if (dump_file) - { - fprintf (dump_file, "%d bit bswap implementation found at: ", - (int)type_size); - print_gimple_stmt (dump_file, stmt, 0, 0); - } + if (dump_file) + { + fprintf (dump_file, "%d bit bswap implementation found at: ", + (int) type_size); + print_gimple_stmt (dump_file, stmt, 0, 0); + } - gsi_insert_after (&gsi, call, GSI_SAME_STMT); - gsi_remove (&gsi, true); + gsi_insert_after (&gsi, call, GSI_SAME_STMT); + gsi_remove (&gsi, true); + } } } - statistics_counter_event (cfun, "32-bit bswap implementations found", bswap_stats.found_32bit); statistics_counter_event (cfun, "64-bit bswap implementations found",