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 <[email protected]>
* 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