--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-mergephi2" } */
+
+int bar (void);
+
+int foo1 (int x, int y)
+{
+ if (y < 10) return bar ();
+ if (x > 9) return bar ();
+
+ return x < y ? x : y;
+}
+
+int foo2 (int x, int y)
+{
+ if (y < 10) return bar ();
+ if (x > 9) return bar ();
+
+ return x > y ? x : y;
+}
+
+/* We expect to optimiz min/max in VRP*/
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "mergephi2" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "mergephi2" } } */
+/* { dg-final { scan-tree-dump-not "MIN_EXPR" "vrp1" } } */
+/* { dg-final { scan-tree-dump-not "MAX_EXPR" "vrp1" } } */
return NULL_TREE;
}
-/* Helper function for vrp_evaluate_conditional_warnv. */
+/* Helper function for vrp_evaluate_conditional_warnv & other
+ optimizers. */
static tree
vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code,
return false;
}
+/* Simplify a min or max if the ranges of the two operands are
+ disjoint. Return true if we do simplify. */
+
+static bool
+simplify_min_or_max_using_ranges (gimple stmt)
+{
+ tree op0 = gimple_assign_rhs1 (stmt);
+ tree op1 = gimple_assign_rhs2 (stmt);
+ bool sop = false;
+ tree val;
+
+ val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges
+ (LE_EXPR, op0, op1, &sop));
+ if (!val)
+ {
+ sop = false;
+ val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges
+ (LT_EXPR, op0, op1, &sop));
+ }
+
+ if (val)
+ {
+ if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
+ {
+ location_t location;
+
+ if (!gimple_has_location (stmt))
+ location = input_location;
+ else
+ location = gimple_location (stmt);
+ warning_at (location, OPT_Wstrict_overflow,
+ "assuming signed overflow does not occur when "
+ "simplifying %<min/max (X,Y)%> to %<X%> or %<Y%>");
+ }
+
+ /* VAL == TRUE -> OP0 < or <= op1
+ VAL == FALSE -> OP0 > or >= op1. */
+ tree res = ((gimple_assign_rhs_code (stmt) == MAX_EXPR)
+ == integer_zerop (val)) ? op0 : op1;
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ gimple_assign_set_rhs_from_tree (&gsi, res);
+ update_stmt (stmt);
+ return true;
+ }
+
+ return false;
+}
+
/* If the operand to an ABS_EXPR is >= 0, then eliminate the
ABS_EXPR. If the operand is <= 0, then simplify the
ABS_EXPR into a NEGATE_EXPR. */
return simplify_float_conversion_using_ranges (gsi, stmt);
break;
+ case MIN_EXPR:
+ case MAX_EXPR:
+ return simplify_min_or_max_using_ranges (stmt);
+ break;
+
default:
break;
}