The following significantly brings down compile-time spent in VRP for the testcase.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2019-07-29 Richard Biener <rguent...@suse.de> PR tree-optimization/91257 * tree-vrp.c (operand_less_p): Avoid dispatching to fold for most cases, instead call compare_values which handles the symbolic ranges we handle specially. (compare_values_warnv): Do not call operand_less_p but open-code the effective fold calls. Avoid converting so much. Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 273792) +++ gcc/tree-vrp.c (working copy) @@ -909,22 +909,17 @@ operand_less_p (tree val, tree val2) /* LT is folded faster than GE and others. Inline the common case. */ if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST) return tree_int_cst_lt (val, val2); + else if (TREE_CODE (val) == SSA_NAME && TREE_CODE (val2) == SSA_NAME) + return val == val2 ? 0 : -2; else { - tree tcmp; - - fold_defer_overflow_warnings (); - - tcmp = fold_binary_to_constant (LT_EXPR, boolean_type_node, val, val2); - - fold_undefer_and_ignore_overflow_warnings (); - - if (!tcmp - || TREE_CODE (tcmp) != INTEGER_CST) - return -2; - - if (!integer_zerop (tcmp)) + int cmp = compare_values (val, val2); + if (cmp == -1) return 1; + else if (cmp == 0 || cmp == 1) + return 0; + else + return -2; } return 0; @@ -958,8 +953,8 @@ compare_values_warnv (tree val1, tree va /* Convert the two values into the same type. This is needed because sizetype causes sign extension even for unsigned types. */ - val2 = fold_convert (TREE_TYPE (val1), val2); - STRIP_USELESS_TYPE_CONVERSION (val2); + if (!useless_type_conversion_p (TREE_TYPE (val1), TREE_TYPE (val2))) + val2 = fold_convert (TREE_TYPE (val1), val2); const bool overflow_undefined = INTEGRAL_TYPE_P (TREE_TYPE (val1)) @@ -1067,32 +1062,43 @@ compare_values_warnv (tree val1, tree va } else { - tree t; + if (TREE_CODE (val1) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST) + { + /* We cannot compare overflowed values. */ + if (TREE_OVERFLOW (val1) || TREE_OVERFLOW (val2)) + return -2; + + return tree_int_cst_compare (val1, val2); + } /* First see if VAL1 and VAL2 are not the same. */ - if (val1 == val2 || operand_equal_p (val1, val2, 0)) + if (operand_equal_p (val1, val2, 0)) return 0; + fold_defer_overflow_warnings (); + /* If VAL1 is a lower address than VAL2, return -1. */ - if (operand_less_p (val1, val2) == 1) - return -1; + tree t = fold_binary_to_constant (LT_EXPR, boolean_type_node, val1, val2); + if (t && integer_onep (t)) + { + fold_undefer_and_ignore_overflow_warnings (); + return -1; + } /* If VAL1 is a higher address than VAL2, return +1. */ - if (operand_less_p (val2, val1) == 1) - return 1; - - /* If VAL1 is different than VAL2, return +2. - For integer constants we either have already returned -1 or 1 - or they are equivalent. We still might succeed in proving - something about non-trivial operands. */ - if (TREE_CODE (val1) != INTEGER_CST - || TREE_CODE (val2) != INTEGER_CST) + t = fold_binary_to_constant (LT_EXPR, boolean_type_node, val2, val1); + if (t && integer_onep (t)) { - t = fold_binary_to_constant (NE_EXPR, boolean_type_node, val1, val2); - if (t && integer_onep (t)) - return 2; + fold_undefer_and_ignore_overflow_warnings (); + return 1; } + /* If VAL1 is different than VAL2, return +2. */ + t = fold_binary_to_constant (NE_EXPR, boolean_type_node, val1, val2); + fold_undefer_and_ignore_overflow_warnings (); + if (t && integer_onep (t)) + return 2; + return -2; } }