From da7db2ced2f26dc763e69176e850e8175945bc46 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 12 Aug 2015 13:08:23 +0000 Subject: [PATCH] tree-vrp.c (simplify_min_or_max_using_ranges): New. * tree-vrp.c (simplify_min_or_max_using_ranges): New. (simplify_stmt_using_ranges): Simplify MIN and MAX exprs. testsuite/ * gcc.dg/vrp-min-max-1.c: New. * gcc.dg/vrp-min-max-2.c: New. From-SVN: r226809 --- gcc/ChangeLog | 5 +++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/vrp-min-max-1.c | 27 ++++++++++++++ gcc/testsuite/gcc.dg/vrp-min-max-2.c | 17 +++++++++ gcc/tree-vrp.c | 56 +++++++++++++++++++++++++++- 5 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/vrp-min-max-1.c create mode 100644 gcc/testsuite/gcc.dg/vrp-min-max-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2e94a8d43df..3869f671cd3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2015-08-12 Nathan Sidwell + + * tree-vrp.c (simplify_min_or_max_using_ranges): New. + (simplify_stmt_using_ranges): Simplify MIN and MAX exprs. + 2015-08-12 Simon Dardis * config/mips/mips.c (mips_store_data_bypass_p): Bring code into diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7bb63a5f4ac..b712e5f0e8b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-08-12 Nathan Sidwell + + * gcc.dg/vrp-min-max-1.c: New. + * gcc.dg/vrp-min-max-2.c: New. + 2015-08-12 Richard Biener * gcc.dg/tree-ssa/ssa-fre-43.c: Adjust. diff --git a/gcc/testsuite/gcc.dg/vrp-min-max-1.c b/gcc/testsuite/gcc.dg/vrp-min-max-1.c new file mode 100644 index 00000000000..270f2bbb436 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vrp-min-max-1.c @@ -0,0 +1,27 @@ +/* { 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" } } */ diff --git a/gcc/testsuite/gcc.dg/vrp-min-max-2.c b/gcc/testsuite/gcc.dg/vrp-min-max-2.c new file mode 100644 index 00000000000..a3ccc6644bf --- /dev/null +++ b/gcc/testsuite/gcc.dg/vrp-min-max-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp2" } */ + +int Foo (int X) +{ + if (X < 0) + X = 0; + if (X > 191) + X = 191; + + return X << 23; +} + +/* We expect this min/max pair to survive. */ + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "vrp2" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "vrp2" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index d51acaa52fc..0439272b97d 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -7466,7 +7466,8 @@ compare_names (enum tree_code comp, tree n1, tree n2, 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, @@ -9145,6 +9146,54 @@ simplify_div_or_mod_using_ranges (gimple stmt) 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 % to % or %"); + } + + /* 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. */ @@ -9987,6 +10036,11 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) 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; } -- 2.30.2