re PR tree-optimization/61839 (More optimize opportunity for VRP)
gcc/testsuite/ChangeLog: 2016-08-20 Kugan Vivekanandarajah <kuganv@linaro.org> 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 <kuganv@linaro.org> 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
This commit is contained in:
parent
151d752b9e
commit
22d12455ea
@ -1,3 +1,12 @@
|
||||
2016-08-20 Kugan Vivekanandarajah <kuganv@linaro.org>
|
||||
|
||||
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 <dmalcolm@redhat.com>
|
||||
|
||||
* diagnostic-show-locus.c
|
||||
|
@ -1,3 +1,11 @@
|
||||
2016-08-20 Kugan Vivekanandarajah <kuganv@linaro.org>
|
||||
|
||||
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 <joseph@codesourcery.com>
|
||||
|
||||
PR c/32187
|
||||
|
44
gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c
Normal file
44
gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c
Normal file
@ -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" } } */
|
54
gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c
Normal file
54
gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c
Normal file
@ -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" } } */
|
26
gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c
Normal file
26
gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c
Normal file
@ -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" } } */
|
28
gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c
Normal file
28
gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c
Normal file
@ -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" } } */
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user