diff options
author | Nathan Sidwell <nathan@acm.org> | 2015-08-12 13:08:23 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2015-08-12 13:08:23 +0000 |
commit | da7db2ced2f26dc763e69176e850e8175945bc46 (patch) | |
tree | cc3b5adfb47fbb84706ba2a55f6f8b493af361a5 /gcc | |
parent | 191a6b94e688171a6e62f0ee3443011f0d1d1855 (diff) | |
download | gcc-da7db2ced2f26dc763e69176e850e8175945bc46.zip gcc-da7db2ced2f26dc763e69176e850e8175945bc46.tar.gz gcc-da7db2ced2f26dc763e69176e850e8175945bc46.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vrp-min-max-1.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vrp-min-max-2.c | 17 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 56 |
5 files changed, 109 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2e94a8d..3869f67 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2015-08-12 Nathan Sidwell <nathan@acm.org> + + * tree-vrp.c (simplify_min_or_max_using_ranges): New. + (simplify_stmt_using_ranges): Simplify MIN and MAX exprs. + 2015-08-12 Simon Dardis <simon.dardis@imgtec.com> * config/mips/mips.c (mips_store_data_bypass_p): Bring code into diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7bb63a5..b712e5f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-08-12 Nathan Sidwell <nathan@acm.org> + + * gcc.dg/vrp-min-max-1.c: New. + * gcc.dg/vrp-min-max-2.c: New. + 2015-08-12 Richard Biener <rguenther@suse.de> * 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 0000000..270f2bb --- /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 0000000..a3ccc66 --- /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 d51acaa..0439272 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 %<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. */ @@ -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; } |