On Thu, Jan 14, 2016 at 8:38 AM, Jeff Law <l...@redhat.com> wrote: > > As noted in the BZ, DOM does not exploit VRP information to create > additional equivalences in the arms of conditionals. > > This can cause DOM to miss relatively simple optimizations that show up in > the adpcm benchmark as well as within GCC itself. > > The fix is quite simple -- we just need to extend the code which used the > implicit range of booleans to propagate on both sides of equality > conditionals to use VRP information as well. > > Once done we also need to make sure to convert the true/false value we're > propagating to the right type. Again, trivial. > > The testcase is derived from the adpcm benchmark. It checks that we > optimize away the bit-xor on both arms of the conditional and that in turn > allows other values to be discovered as constants. > > Bootstrapped and regression tested on x86_64. Installed on the trunk. > > > > Jeff > > commit e9d42e91d1e88ece5be38dbde81843e516b327e0 > Author: Jeff Law <l...@redhat.com> > Date: Thu Jan 14 00:37:37 2016 -0700 > > [PATCH][PR tree-optimization/69270] Exploit VRP information in DOM > > PR tree-optimization/69270 > * tree-ssa-dom.c (ssa_name_has_boolean_range): New function. > (record_edge_info): Use it. Convert boolean_{true,false}_node > to the type of op0. > > PR tree-optimization/69270 > * gcc.dg/tree-ssa/pr69270.c: New test. > > diff --git a/gcc/ChangeLog b/gcc/ChangeLog > index dc13621..40e3dfb 100644 > --- a/gcc/ChangeLog > +++ b/gcc/ChangeLog > @@ -1,3 +1,10 @@ > +2016-01-14 Jeff Law <l...@redhat.com> > + > + PR tree-optimization/69270 > + * tree-ssa-dom.c (ssa_name_has_boolean_range): New function. > + (record_edge_info): Use it. Convert boolean_{true,false}_node > + to the type of op0. > + > 2016-01-13 Jan Hubicka <hubi...@ucw.cz> > > PR ipa/66487 > diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog > index f393e25..63976ea 100644 > --- a/gcc/testsuite/ChangeLog > +++ b/gcc/testsuite/ChangeLog > @@ -1,3 +1,8 @@ > +2016-01-14 Jeff Law <l...@redhat.com> > + > + PR tree-optimization/69270 > + * gcc.dg/tree-ssa/pr69270.c: New test. > + > 2016-01-13 Bernd Schmidt <bschm...@redhat.com> > > PR c/66208 > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c > b/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c > new file mode 100644 > index 0000000..529b521 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c > @@ -0,0 +1,42 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fsplit-paths -fdump-tree-dom3-details" } */ > + > +/* There should be two references to bufferstep that turn into > + constants. */ > +/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. with > constant .0." 1 "dom3"} } */ > +/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. with > constant .1." 1 "dom3"} } */ > + > +/* And some assignments ought to fold down to constants. */ > +/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 1;" 2 "dom3"} > } */ > +/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 0;" 2 "dom3"} > } */ > + > +/* The XOR operations should have been optimized to constants. */ > +/* { dg-final { scan-tree-dump-not "bit_xor" "dom3"} } */ > + > + > +extern int *stepsizeTable; > + > +void > +adpcm_coder (signed char *outdata, int len) > +{ > + signed char *outp; > + int delta; > + int outputbuffer; > + int bufferstep = 0; > + outp = (signed char *) outdata; > + int step = 0; > + int index = 0; > + int diff = 0; > + for (; len > 0; len--) > + { > + delta = 0; > + if (diff >= step) > + delta = 4; > + step = stepsizeTable[index]; > + if (bufferstep) > + outputbuffer = (delta << 4) & 0xf0; > + else > + *outp++ = (delta & 0x0f) | outputbuffer; > + bufferstep = !bufferstep; > + } > +} > diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c > index 9d2e189..a9abed9 100644 > --- a/gcc/tree-ssa-dom.c > +++ b/gcc/tree-ssa-dom.c > @@ -316,6 +316,38 @@ record_conditions (struct edge_info *edge_info, tree > cond, tree inverted) > edge_info->cond_equivalences.safe_push (c); > } > > +/* Return TRUE is OP, an SSA_NAME has a range of values [0..1], false > + otherwise. > + > + This can be because it is a boolean type, any type with > + a single bit of precision, or has known range of values > + it might old of [0..1] via VRP analysis. */ > + > +static bool > +ssa_name_has_boolean_range (tree op) > +{ > + /* Boolean types always have a range [0..1]. */ > + if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE) > + return true; > + > + /* An integral type with a single bit of precision. */ > + if (INTEGRAL_TYPE_P (TREE_TYPE (op)) > + && TYPE_PRECISION (TREE_TYPE (op)) == 1) > + return true; > + > + /* An integral type with more precision, but the object > + only takes on values [0..1] as determined by VRP > + analysis. */ > + wide_int min, max; > + if (INTEGRAL_TYPE_P (TREE_TYPE (op)) > + && get_range_info (op, &min, &max) == VR_RANGE > + && wi::eq_p (min, 0) > + && wi::eq_p (max, 1)) > + return true; > + > + return false; > +} > + > /* We have finished optimizing BB, record any information implied by > taking a specific outgoing edge from BB. */ > > @@ -390,36 +422,32 @@ record_edge_info (basic_block bb) > can record an equivalence for OP0 rather than COND. */ > if ((code == EQ_EXPR || code == NE_EXPR) > && TREE_CODE (op0) == SSA_NAME > - && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE > + && ssa_name_has_boolean_range (op0) > && is_gimple_min_invariant (op1)) > { > + tree true_val = fold_convert (TREE_TYPE (op0), > + boolean_true_node); > + tree false_val = fold_convert (TREE_TYPE (op0), > + boolean_false_node);
Apart from what Jakub said we have constant_boolean_node for this, true_val = constant_boolean_node (true, TREE_TYPE (op0)); ... > if (code == EQ_EXPR) > { > edge_info = allocate_edge_info (true_edge); > edge_info->lhs = op0; > - edge_info->rhs = (integer_zerop (op1) > - ? boolean_false_node > - : boolean_true_node); > + edge_info->rhs = (integer_zerop (op1) ? false_val : > true_val); > > edge_info = allocate_edge_info (false_edge); > edge_info->lhs = op0; > - edge_info->rhs = (integer_zerop (op1) > - ? boolean_true_node > - : boolean_false_node); > + edge_info->rhs = (integer_zerop (op1) ? true_val : > false_val); > } > else > { > edge_info = allocate_edge_info (true_edge); > edge_info->lhs = op0; > - edge_info->rhs = (integer_zerop (op1) > - ? boolean_true_node > - : boolean_false_node); > + edge_info->rhs = (integer_zerop (op1) ? true_val : > false_val); > > edge_info = allocate_edge_info (false_edge); > edge_info->lhs = op0; > - edge_info->rhs = (integer_zerop (op1) > - ? boolean_false_node > - : boolean_true_node); > + edge_info->rhs = (integer_zerop (op1) ? false_val : > true_val); > } > } > else if (is_gimple_min_invariant (op0) >