diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 8d18e19d6e4..1efb907ae5e 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -3247,6 +3247,42 @@ register_edge_assert_for_2 (tree name, edge e, } } } + + /* For things like (T)a CMP (T)b register asserts for a CMP b if possible. */ + if (TREE_CODE_CLASS (comp_code) == tcc_comparison + && TREE_CODE (val) == SSA_NAME + && (INTEGRAL_TYPE_P (TREE_TYPE (val)) + || POINTER_TYPE_P (TREE_TYPE (val)))) + { + gassign *def1 = dyn_cast (SSA_NAME_DEF_STMT (name)); + gassign *def2 = dyn_cast (SSA_NAME_DEF_STMT (val)); + if (def1 && def2 + && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def1)) + && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def2)) + && types_compatible_p (TREE_TYPE (gimple_assign_rhs1 (def1)), + TREE_TYPE (gimple_assign_rhs1 (def2))) + && (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def1))) + <= TYPE_PRECISION (TREE_TYPE (val))) + && (comp_code == EQ_EXPR + || comp_code == NE_EXPR + || (TYPE_SIGN (TREE_TYPE (val)) + == TYPE_SIGN (TREE_TYPE (gimple_assign_rhs1 (def1)))) + || (TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (def1))) + && (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def1))) + < TYPE_PRECISION (TREE_TYPE (val)))))) + { + tree op0 = gimple_assign_rhs1 (def1); + tree op1 = gimple_assign_rhs1 (def2); + enum tree_code alt_comp_code = comp_code; + if (TREE_CODE (op0) != SSA_NAME) + { + alt_comp_code = swap_tree_comparison (alt_comp_code); + std::swap (op0, op1); + } + if (TREE_CODE (op0) == SSA_NAME) + add_assert_info (asserts, op0, op0, alt_comp_code, op1); + } + } } /* OP is an operand of a truth value expression which is known to have