From: Kugan Vivekanandarajah Date: Sat, 20 Aug 2016 01:18:09 +0000 (+0000) Subject: re PR tree-optimization/61839 (More optimize opportunity for VRP) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=22d12455eaf2e4c64ef8c778358087d999d2ccd8;p=gcc.git re PR tree-optimization/61839 (More optimize opportunity for VRP) gcc/testsuite/ChangeLog: 2016-08-20 Kugan Vivekanandarajah PR tree-optimization/61839 * gcc.dg/tree-ssa/pr61839_1.c: New test. * gcc.dg/tree-ssa/pr61839_2.c: New test. * gcc.dg/tree-ssa/pr61839_3.c: New test. * gcc.dg/tree-ssa/pr61839_4.c: New test. gcc/ChangeLog: 2016-08-20 Kugan Vivekanandarajah PR tree-optimization/61839 * tree-vrp.c (two_valued_val_range_p): New. (simplify_stmt_using_ranges): Convert CST BINOP VAR where VAR is two-valued to VAR == VAL1 ? (CST BINOP VAL1) : (CST BINOP VAL2). Also Convert VAR BINOP CST where VAR is two-valued to VAR == VAL1 ? (VAL1 BINOP CST) : (VAL2 BINOP CST). From-SVN: r239637 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 02c85f893f8..a9946a9134b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2016-08-20 Kugan Vivekanandarajah + + PR tree-optimization/61839 + * tree-vrp.c (two_valued_val_range_p): New. + (simplify_stmt_using_ranges): Convert CST BINOP VAR where VAR is + two-valued to VAR == VAL1 ? (CST BINOP VAL1) : (CST BINOP VAL2). + Also Convert VAR BINOP CST where VAR is two-valued to + VAR == VAL1 ? (VAL1 BINOP CST) : (VAL2 BINOP CST). + 2016-08-19 David Malcolm * diagnostic-show-locus.c diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 91ea2788d4c..6201e0cf82d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2016-08-20 Kugan Vivekanandarajah + + PR tree-optimization/61839 + * gcc.dg/tree-ssa/pr61839_1.c: New test. + * gcc.dg/tree-ssa/pr61839_2.c: New test. + * gcc.dg/tree-ssa/pr61839_3.c: New test. + * gcc.dg/tree-ssa/pr61839_4.c: New test. + 2016-08-19 Joseph Myers PR c/32187 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c new file mode 100644 index 00000000000..9f8168a81f2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c @@ -0,0 +1,44 @@ +/* PR tree-optimization/61839. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized" } */ +/* { dg-require-effective-target int32plus } */ + +__attribute__ ((noinline)) +int foo () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195718) >> (1LU <= b); + if (c == 486097858) + ; + else + __builtin_abort (); + return 0; +} + +__attribute__ ((noinline)) +int bar () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195718) >> (b ? 2 : 3); + if (c == 243048929) + ; + else + __builtin_abort (); + return 0; +} + +int main () +{ + foo (); + bar (); +} + +/* Scan for c = 972195717) >> [0, 1] in function foo. */ +/* { dg-final { scan-tree-dump-times "486097858 : 972195717" 1 "vrp1" } } */ +/* Scan for c = 972195717) >> [2, 3] in function bar. */ +/* { dg-final { scan-tree-dump-times "243048929 : 121524464" 2 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "486097858" 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c new file mode 100644 index 00000000000..ffa00a7e674 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c @@ -0,0 +1,54 @@ +/* PR tree-optimization/61839. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ +/* { dg-require-effective-target int32plus } */ + +__attribute__ ((noinline)) +int foo () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195718) / (b ? 1 : 0); + if (c == 972195717) + ; + else + __builtin_abort (); + return 0; +} + +__attribute__ ((noinline)) +int bar () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195718) % (b ? 1 : 0); + if (c == 972195717) + ; + else + __builtin_abort (); + return 0; +} + +__attribute__ ((noinline)) +int bar2 () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195716) % (b ? 1 : 2); + if (c == 972195715) + ; + else + __builtin_abort (); + return 0; +} + + +/* Dont optimize 972195717 / 0 in function foo. */ +/* { dg-final { scan-tree-dump-times "972195717 / _" 1 "vrp1" } } */ +/* Dont optimize 972195717 % 0 in function bar. */ +/* { dg-final { scan-tree-dump-times "972195717 % _" 1 "vrp1" } } */ +/* Optimize in function bar2. */ +/* { dg-final { scan-tree-dump-times "972195715 % _" 0 "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c new file mode 100644 index 00000000000..5ceb0738bde --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c @@ -0,0 +1,26 @@ +/* PR tree-optimization/61839. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized" } */ + +__attribute__ ((noinline)) +int foo (int a, unsigned b) +{ + int c = 1; + b = a ? 12 : 13; + c = b << 8; + if (c == 3072) + ; + else + __builtin_abort (); + return 0; +} + +int main () +{ + volatile unsigned b = 1U; + foo (-1, b); +} + +/* Scan for c [12, 13] << 8 in function foo. */ +/* { dg-final { scan-tree-dump-times "3072 : 3328" 2 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "3072" 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c new file mode 100644 index 00000000000..5c026c89c7d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c @@ -0,0 +1,28 @@ +/* PR tree-optimization/61839. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized" } */ +/* { dg-require-effective-target int32plus } */ + +__attribute__ ((noinline)) +int foo (int a, unsigned b) +{ + unsigned c = 1; + if (b >= 1 && b <= ((unsigned)(-1) - 1)) + return 0; + c = b >> 4; + if (c == 268435455) + ; + else + __builtin_abort (); + return 0; +} + +int main () +{ + volatile unsigned b = (unsigned)(-1); + foo (-1, b); +} + +/* Scan for ~[1, 4294967294] >> 4 in function foo. */ +/* { dg-final { scan-tree-dump-times "0 : 268435455" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "268435455" 0 "optimized" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index a8810134b31..d350a86c50c 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -10036,6 +10036,40 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) return true; } +/* Return true if VAR is a two-valued variable. Set a and b with the + two-values when it is true. Return false otherwise. */ + +static bool +two_valued_val_range_p (tree var, tree *a, tree *b) +{ + value_range *vr = get_value_range (var); + if ((vr->type != VR_RANGE + && vr->type != VR_ANTI_RANGE) + || TREE_CODE (vr->min) != INTEGER_CST + || TREE_CODE (vr->max) != INTEGER_CST) + return false; + + if (vr->type == VR_RANGE + && wi::sub (vr->max, vr->min) == 1) + { + *a = vr->min; + *b = vr->max; + return true; + } + + /* ~[TYPE_MIN + 1, TYPE_MAX - 1] */ + if (vr->type == VR_ANTI_RANGE + && wi::sub (vr->min, vrp_val_min (TREE_TYPE (var))) == 1 + && wi::sub (vrp_val_max (TREE_TYPE (var)), vr->max) == 1) + { + *a = vrp_val_min (TREE_TYPE (var)); + *b = vrp_val_max (TREE_TYPE (var)); + return true; + } + + return false; +} + /* Simplify STMT using ranges if possible. */ static bool @@ -10046,6 +10080,68 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) { enum tree_code rhs_code = gimple_assign_rhs_code (stmt); tree rhs1 = gimple_assign_rhs1 (stmt); + tree rhs2 = gimple_assign_rhs2 (stmt); + tree lhs = gimple_assign_lhs (stmt); + tree val1 = NULL_TREE, val2 = NULL_TREE; + use_operand_p use_p; + gimple *use_stmt; + + /* Convert: + LHS = CST BINOP VAR + Where VAR is two-valued and LHS is used in GIMPLE_COND only + To: + LHS = VAR == VAL1 ? (CST BINOP VAL1) : (CST BINOP VAL2) + + Also handles: + LHS = VAR BINOP CST + Where VAR is two-valued and LHS is used in GIMPLE_COND only + To: + LHS = VAR == VAL1 ? (VAL1 BINOP CST) : (VAL2 BINOP CST) */ + + if (TREE_CODE_CLASS (rhs_code) == tcc_binary + && INTEGRAL_TYPE_P (TREE_TYPE (lhs)) + && ((TREE_CODE (rhs1) == INTEGER_CST + && TREE_CODE (rhs2) == SSA_NAME) + || (TREE_CODE (rhs2) == INTEGER_CST + && TREE_CODE (rhs1) == SSA_NAME)) + && single_imm_use (lhs, &use_p, &use_stmt) + && gimple_code (use_stmt) == GIMPLE_COND) + + { + tree new_rhs1 = NULL_TREE; + tree new_rhs2 = NULL_TREE; + tree cmp_var = NULL_TREE; + + if (TREE_CODE (rhs2) == SSA_NAME + && two_valued_val_range_p (rhs2, &val1, &val2)) + { + /* Optimize RHS1 OP [VAL1, VAL2]. */ + new_rhs1 = int_const_binop (rhs_code, rhs1, val1); + new_rhs2 = int_const_binop (rhs_code, rhs1, val2); + cmp_var = rhs2; + } + else if (TREE_CODE (rhs1) == SSA_NAME + && two_valued_val_range_p (rhs1, &val1, &val2)) + { + /* Optimize [VAL1, VAL2] OP RHS2. */ + new_rhs1 = int_const_binop (rhs_code, val1, rhs2); + new_rhs2 = int_const_binop (rhs_code, val2, rhs2); + cmp_var = rhs1; + } + + /* If we could not find two-vals or the optimzation is invalid as + in divide by zero, new_rhs1 / new_rhs will be NULL_TREE. */ + if (new_rhs1 && new_rhs2) + { + tree cond = build2 (EQ_EXPR, TREE_TYPE (cmp_var), cmp_var, val1); + gimple_assign_set_rhs_with_ops (gsi, + COND_EXPR, cond, + new_rhs1, + new_rhs2); + update_stmt (gsi_stmt (*gsi)); + return true; + } + } switch (rhs_code) {