Hello, this patch tries to sink conversions for comparisons patterns: a) (type) X cmp (type) Y => x cmp y. b) (type) X cmp CST => x cmp ((type-x) CST). c) CST cmp (type) X => ((type-x) CST) cmp x.
This patch just allows type sinking for the case that type-precision of type is wider or equal to type-precision of type-x. Or if type and type-x have same signess and CST fits into type-x. For cmp operation is == or !=, we allow also that type and type-x have different signess, as long as CST fits into type-x without truncation. ChangeLog 2011-06-27 Kai Tietz <kti...@redhat.com> * tree-ssa-forwprop.c (forward_propagate_into_comparision): Sink types within comparison operands, if suitable. 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 @@ -432,11 +432,73 @@ forward_propagate_into_comparison_1 (loc /* If that wasn't successful either, try both operands. */ if (rhs0 != NULL_TREE && rhs1 != NULL_TREE) - tmp = combine_cond_expr_cond (loc, code, type, - rhs0, rhs1, - !(single_use0_p && single_use1_p)); - - return tmp; + { + tmp = combine_cond_expr_cond (loc, code, type, + rhs0, rhs1, + !(single_use0_p && single_use1_p)); + if (tmp) + return tmp; + } + /* Sink types of comparison, if (type) CMP (type) Y, if types + of X and Y are compatible. */ + if (rhs0 != NULL_TREE && rhs1 != NULL_TREE + && CONVERT_EXPR_CODE_P (TREE_CODE (rhs0)) + && CONVERT_EXPR_CODE_P (TREE_CODE (rhs1)) + && types_compatible_p (TREE_TYPE (TREE_OPERAND (rhs0, 0)), + TREE_TYPE (TREE_OPERAND (rhs1, 0))) + /* Make sure that the conversion widens the operands, or has same + precision. */ + && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (rhs0, 0))) + <= TYPE_PRECISION (TREE_TYPE (rhs0))) + && (code == EQ_EXPR || code == NE_EXPR + || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (rhs0, 0))) + == TYPE_UNSIGNED (TREE_TYPE (rhs0)))) + return fold_build2_loc (loc, code, type, TREE_OPERAND (rhs0, 0), + TREE_OPERAND (rhs1, 0)); + /* Check if (type) X cmp CST can be convered into + (type) (X cmp (type-x) CST). */ + if (rhs0 != NULL_TREE + && CONVERT_EXPR_CODE_P (TREE_CODE (rhs0)) + && TREE_CODE (op1) == INTEGER_CST + && INTEGRAL_TYPE_P (TREE_OPERAND (rhs0, 0)) + && INTEGRAL_TYPE_P (rhs0) + && (code == EQ_EXPR || code == NE_EXPR + || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (rhs0, 0))) + == TYPE_UNSIGNED (TREE_TYPE (rhs0)))) + { + tree folded_int = fold_convert_loc (loc, + TREE_TYPE (TREE_OPERAND (rhs0, 0)), + op1); + /* Is the back casted folded integer identical to original + integer? */ + if (operand_equal_p (op1, fold_convert_loc (loc, TREE_TYPE (op0), + folded_int), 0)) + return fold_build2_loc (loc, code, type, TREE_OPERAND (rhs0, 0), + folded_int); + } + + /* Check if CST op (type) X can be converted into + (type) ((type-x) CST op X). */ + if (rhs1 != NULL_TREE + && CONVERT_EXPR_CODE_P (TREE_CODE (rhs1)) + && TREE_CODE (op0) == INTEGER_CST + && INTEGRAL_TYPE_P (TREE_OPERAND (rhs1, 0)) + && INTEGRAL_TYPE_P (rhs1) + && (code == EQ_EXPR || code == NE_EXPR + || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (rhs1, 0))) + == TYPE_UNSIGNED (TREE_TYPE (rhs1)))) + { + tree folded_int = fold_convert_loc (loc, + TREE_TYPE (TREE_OPERAND (rhs1, 0)), + op0); + /* Is the back casted folded integer identical to original + integer? */ + if (operand_equal_p (op0, fold_convert_loc (loc, TREE_TYPE (op1), + folded_int), 0)) + return fold_build2_loc (loc, code, type, folded_int, + TREE_OPERAND (rhs1, 0)); + } + return NULL_TREE; } /* Propagate from the ssa name definition statements of the assignment