Re: [patch] Enhance conditional store sinking

2011-03-24 Thread Richard Guenther
On Thu, Mar 24, 2011 at 11:03 AM, H.J. Lu hjl.to...@gmail.com wrote:
 On Tue, Mar 22, 2011 at 6:28 AM, Ira Rosen ira.ro...@linaro.org wrote:
 On 17 March 2011 16:48, Richard Guenther richard.guent...@gmail.com wrote:

 +  then_datarefs = VEC_alloc (data_reference_p, heap, 1);
 +  else_datarefs = VEC_alloc (data_reference_p, heap, 1);
 +  then_ddrs = VEC_alloc (ddr_p, heap, 1);
 +  else_ddrs = VEC_alloc (ddr_p, heap, 1);
 +  if (!compute_data_dependences_for_bb (then_bb, false, then_datarefs,
 +                                        then_ddrs)

 Can we avoid computing dependencies if the other BB would have no
 data-refs?  Thus, split collecting datarefs and computing dependences?

 Done.


 +      || !compute_data_dependences_for_bb (else_bb, false, else_datarefs,
 +                                           else_ddrs)
 +      || !VEC_length (data_reference_p, then_datarefs)
 +      || !VEC_length (data_reference_p, else_datarefs))
 +    {
 +      free_data_refs (then_datarefs);
 +      free_data_refs (else_datarefs);
 +      free_dependence_relations (then_ddrs);
 +      free_dependence_relations (else_ddrs);
 +      return false;
 +    }
 +
 +  /* Check that there are no read-after-write or write-after-write 
 dependencies
 +     in THEN_BB.  */
 +  FOR_EACH_VEC_ELT (ddr_p, then_ddrs, i, ddr)
 +    {
 +      struct data_reference *dra = DDR_A (ddr);
 +      struct data_reference *drb = DDR_B (ddr);
 +
 +      if (DDR_ARE_DEPENDENT (ddr) != chrec_known
 +           ((DR_IS_READ (dra)  DR_IS_WRITE (drb)
 +                gimple_uid (DR_STMT (dra))  gimple_uid (DR_STMT (drb)))
 +              || (DR_IS_READ (drb)  DR_IS_WRITE (dra)
 +                   gimple_uid (DR_STMT (drb))  gimple_uid (DR_STMT 
 (dra)))
 +              || (DR_IS_WRITE (dra)  DR_IS_WRITE (drb

 The gimple_uids are not initialized here, you need to make sure to
 call renumber_gimple_stmt_uids () before starting.  Note that phiopt
 incrementally changes the IL, so I'm not sure those uids will stay
 valid as stmts are moved across blocks.

 I added a call to renumber_gimple_stmt_uids_in_blocks() before data
 dependence checks, and there are no code changes between that and the
 checks, so, I think, it should be OK.


 +        {
 +          free_data_refs (then_datarefs);
 +          free_data_refs (else_datarefs);
 +          free_dependence_relations (then_ddrs);
 +          free_dependence_relations (else_ddrs);
 +          return false;
 +        }
 +    }
 +
 +  /* Check that there are no read-after-write or write-after-write 
 dependencies
 +     in ELSE_BB.  */
 +  FOR_EACH_VEC_ELT (ddr_p, else_ddrs, i, ddr)
 +    {
 +      struct data_reference *dra = DDR_A (ddr);
 +      struct data_reference *drb = DDR_B (ddr);
 +
 +      if (DDR_ARE_DEPENDENT (ddr) != chrec_known
 +           ((DR_IS_READ (dra)  DR_IS_WRITE (drb)
 +                gimple_uid (DR_STMT (dra))  gimple_uid (DR_STMT (drb)))
 +              || (DR_IS_READ (drb)  DR_IS_WRITE (dra)
 +                   gimple_uid (DR_STMT (drb))  gimple_uid (DR_STMT 
 (dra)))
 +              || (DR_IS_WRITE (dra)  DR_IS_WRITE (drb
 +        {
 +          free_data_refs (then_datarefs);
 +          free_data_refs (else_datarefs);
 +          free_dependence_relations (then_ddrs);
 +          free_dependence_relations (else_ddrs);
 +          return false;
 +        }
 +    }
 +
 +  /* Found pairs of stores with equal LHS.  */
 +  FOR_EACH_VEC_ELT (data_reference_p, then_datarefs, i, then_dr)
 +    {
 +      if (DR_IS_READ (then_dr))
 +        continue;
 +
 +      then_store = DR_STMT (then_dr);
 +      then_lhs = gimple_assign_lhs (then_store);
 +      found = false;
 +
 +      FOR_EACH_VEC_ELT (data_reference_p, else_datarefs, j, else_dr)
 +        {
 +          if (DR_IS_READ (else_dr))
 +            continue;
 +
 +          else_store = DR_STMT (else_dr);
 +          else_lhs = gimple_assign_lhs (else_store);
 +
 +          if (operand_equal_p (then_lhs, else_lhs, 0))
 +            {
 +              found = true;
 +              break;
 +            }
 +        }
 +
 +      if (!found)
 +        continue;
 +
 +      res = cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
 +                                              then_store, else_store);

 So you are executing if-else store replacement for common data reference
 pairs only.  I think it's cheaper to collect those pairs before computing
 dependences and only if there is at least one pair perform the optimization.

 OK, I changed the order.


 You basically perform store sinking, creating a PHI node for each store
 you sink (that's then probably if-converted by if-conversion later, 
 eventually
 redundant with -ftree-loop-if-convert-stores?)

 I am concerned that having no bound on the number of stores sunk will
 increase register pressure and does not allow scheduling of the stores
 in an optimal way.  Consider two BBs similar to

  t = a + b;
  *p = t;
  t = c + d;
  *q = t;

 where the transformation undoes 

Re: [patch] Enhance conditional store sinking

2011-03-24 Thread Richard Guenther
On Thu, Mar 24, 2011 at 1:39 PM, Richard Guenther
richard.guent...@gmail.com wrote:
 On Thu, Mar 24, 2011 at 11:03 AM, H.J. Lu hjl.to...@gmail.com wrote:
 On Tue, Mar 22, 2011 at 6:28 AM, Ira Rosen ira.ro...@linaro.org wrote:
 On 17 March 2011 16:48, Richard Guenther richard.guent...@gmail.com wrote:

 +  then_datarefs = VEC_alloc (data_reference_p, heap, 1);
 +  else_datarefs = VEC_alloc (data_reference_p, heap, 1);
 +  then_ddrs = VEC_alloc (ddr_p, heap, 1);
 +  else_ddrs = VEC_alloc (ddr_p, heap, 1);
 +  if (!compute_data_dependences_for_bb (then_bb, false, then_datarefs,
 +                                        then_ddrs)

 Can we avoid computing dependencies if the other BB would have no
 data-refs?  Thus, split collecting datarefs and computing dependences?

 Done.


 +      || !compute_data_dependences_for_bb (else_bb, false, 
 else_datarefs,
 +                                           else_ddrs)
 +      || !VEC_length (data_reference_p, then_datarefs)
 +      || !VEC_length (data_reference_p, else_datarefs))
 +    {
 +      free_data_refs (then_datarefs);
 +      free_data_refs (else_datarefs);
 +      free_dependence_relations (then_ddrs);
 +      free_dependence_relations (else_ddrs);
 +      return false;
 +    }
 +
 +  /* Check that there are no read-after-write or write-after-write 
 dependencies
 +     in THEN_BB.  */
 +  FOR_EACH_VEC_ELT (ddr_p, then_ddrs, i, ddr)
 +    {
 +      struct data_reference *dra = DDR_A (ddr);
 +      struct data_reference *drb = DDR_B (ddr);
 +
 +      if (DDR_ARE_DEPENDENT (ddr) != chrec_known
 +           ((DR_IS_READ (dra)  DR_IS_WRITE (drb)
 +                gimple_uid (DR_STMT (dra))  gimple_uid (DR_STMT 
 (drb)))
 +              || (DR_IS_READ (drb)  DR_IS_WRITE (dra)
 +                   gimple_uid (DR_STMT (drb))  gimple_uid (DR_STMT 
 (dra)))
 +              || (DR_IS_WRITE (dra)  DR_IS_WRITE (drb

 The gimple_uids are not initialized here, you need to make sure to
 call renumber_gimple_stmt_uids () before starting.  Note that phiopt
 incrementally changes the IL, so I'm not sure those uids will stay
 valid as stmts are moved across blocks.

 I added a call to renumber_gimple_stmt_uids_in_blocks() before data
 dependence checks, and there are no code changes between that and the
 checks, so, I think, it should be OK.


 +        {
 +          free_data_refs (then_datarefs);
 +          free_data_refs (else_datarefs);
 +          free_dependence_relations (then_ddrs);
 +          free_dependence_relations (else_ddrs);
 +          return false;
 +        }
 +    }
 +
 +  /* Check that there are no read-after-write or write-after-write 
 dependencies
 +     in ELSE_BB.  */
 +  FOR_EACH_VEC_ELT (ddr_p, else_ddrs, i, ddr)
 +    {
 +      struct data_reference *dra = DDR_A (ddr);
 +      struct data_reference *drb = DDR_B (ddr);
 +
 +      if (DDR_ARE_DEPENDENT (ddr) != chrec_known
 +           ((DR_IS_READ (dra)  DR_IS_WRITE (drb)
 +                gimple_uid (DR_STMT (dra))  gimple_uid (DR_STMT 
 (drb)))
 +              || (DR_IS_READ (drb)  DR_IS_WRITE (dra)
 +                   gimple_uid (DR_STMT (drb))  gimple_uid (DR_STMT 
 (dra)))
 +              || (DR_IS_WRITE (dra)  DR_IS_WRITE (drb
 +        {
 +          free_data_refs (then_datarefs);
 +          free_data_refs (else_datarefs);
 +          free_dependence_relations (then_ddrs);
 +          free_dependence_relations (else_ddrs);
 +          return false;
 +        }
 +    }
 +
 +  /* Found pairs of stores with equal LHS.  */
 +  FOR_EACH_VEC_ELT (data_reference_p, then_datarefs, i, then_dr)
 +    {
 +      if (DR_IS_READ (then_dr))
 +        continue;
 +
 +      then_store = DR_STMT (then_dr);
 +      then_lhs = gimple_assign_lhs (then_store);
 +      found = false;
 +
 +      FOR_EACH_VEC_ELT (data_reference_p, else_datarefs, j, else_dr)
 +        {
 +          if (DR_IS_READ (else_dr))
 +            continue;
 +
 +          else_store = DR_STMT (else_dr);
 +          else_lhs = gimple_assign_lhs (else_store);
 +
 +          if (operand_equal_p (then_lhs, else_lhs, 0))
 +            {
 +              found = true;
 +              break;
 +            }
 +        }
 +
 +      if (!found)
 +        continue;
 +
 +      res = cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
 +                                              then_store, else_store);

 So you are executing if-else store replacement for common data reference
 pairs only.  I think it's cheaper to collect those pairs before computing
 dependences and only if there is at least one pair perform the 
 optimization.

 OK, I changed the order.


 You basically perform store sinking, creating a PHI node for each store
 you sink (that's then probably if-converted by if-conversion later, 
 eventually
 redundant with -ftree-loop-if-convert-stores?)

 I am concerned that having no bound on the number of stores sunk will
 increase register pressure and does not allow scheduling of the stores
 in an optimal way.  Consider two BBs 

Re: [patch] Enhance conditional store sinking

2011-03-23 Thread Richard Guenther
On Tue, Mar 22, 2011 at 2:28 PM, Ira Rosen ira.ro...@linaro.org wrote:
 On 17 March 2011 16:48, Richard Guenther richard.guent...@gmail.com wrote:

 +  then_datarefs = VEC_alloc (data_reference_p, heap, 1);
 +  else_datarefs = VEC_alloc (data_reference_p, heap, 1);
 +  then_ddrs = VEC_alloc (ddr_p, heap, 1);
 +  else_ddrs = VEC_alloc (ddr_p, heap, 1);
 +  if (!compute_data_dependences_for_bb (then_bb, false, then_datarefs,
 +                                        then_ddrs)

 Can we avoid computing dependencies if the other BB would have no
 data-refs?  Thus, split collecting datarefs and computing dependences?

 Done.


 +      || !compute_data_dependences_for_bb (else_bb, false, else_datarefs,
 +                                           else_ddrs)
 +      || !VEC_length (data_reference_p, then_datarefs)
 +      || !VEC_length (data_reference_p, else_datarefs))
 +    {
 +      free_data_refs (then_datarefs);
 +      free_data_refs (else_datarefs);
 +      free_dependence_relations (then_ddrs);
 +      free_dependence_relations (else_ddrs);
 +      return false;
 +    }
 +
 +  /* Check that there are no read-after-write or write-after-write 
 dependencies
 +     in THEN_BB.  */
 +  FOR_EACH_VEC_ELT (ddr_p, then_ddrs, i, ddr)
 +    {
 +      struct data_reference *dra = DDR_A (ddr);
 +      struct data_reference *drb = DDR_B (ddr);
 +
 +      if (DDR_ARE_DEPENDENT (ddr) != chrec_known
 +           ((DR_IS_READ (dra)  DR_IS_WRITE (drb)
 +                gimple_uid (DR_STMT (dra))  gimple_uid (DR_STMT (drb)))
 +              || (DR_IS_READ (drb)  DR_IS_WRITE (dra)
 +                   gimple_uid (DR_STMT (drb))  gimple_uid (DR_STMT 
 (dra)))
 +              || (DR_IS_WRITE (dra)  DR_IS_WRITE (drb

 The gimple_uids are not initialized here, you need to make sure to
 call renumber_gimple_stmt_uids () before starting.  Note that phiopt
 incrementally changes the IL, so I'm not sure those uids will stay
 valid as stmts are moved across blocks.

 I added a call to renumber_gimple_stmt_uids_in_blocks() before data
 dependence checks, and there are no code changes between that and the
 checks, so, I think, it should be OK.


 +        {
 +          free_data_refs (then_datarefs);
 +          free_data_refs (else_datarefs);
 +          free_dependence_relations (then_ddrs);
 +          free_dependence_relations (else_ddrs);
 +          return false;
 +        }
 +    }
 +
 +  /* Check that there are no read-after-write or write-after-write 
 dependencies
 +     in ELSE_BB.  */
 +  FOR_EACH_VEC_ELT (ddr_p, else_ddrs, i, ddr)
 +    {
 +      struct data_reference *dra = DDR_A (ddr);
 +      struct data_reference *drb = DDR_B (ddr);
 +
 +      if (DDR_ARE_DEPENDENT (ddr) != chrec_known
 +           ((DR_IS_READ (dra)  DR_IS_WRITE (drb)
 +                gimple_uid (DR_STMT (dra))  gimple_uid (DR_STMT (drb)))
 +              || (DR_IS_READ (drb)  DR_IS_WRITE (dra)
 +                   gimple_uid (DR_STMT (drb))  gimple_uid (DR_STMT 
 (dra)))
 +              || (DR_IS_WRITE (dra)  DR_IS_WRITE (drb
 +        {
 +          free_data_refs (then_datarefs);
 +          free_data_refs (else_datarefs);
 +          free_dependence_relations (then_ddrs);
 +          free_dependence_relations (else_ddrs);
 +          return false;
 +        }
 +    }
 +
 +  /* Found pairs of stores with equal LHS.  */
 +  FOR_EACH_VEC_ELT (data_reference_p, then_datarefs, i, then_dr)
 +    {
 +      if (DR_IS_READ (then_dr))
 +        continue;
 +
 +      then_store = DR_STMT (then_dr);
 +      then_lhs = gimple_assign_lhs (then_store);
 +      found = false;
 +
 +      FOR_EACH_VEC_ELT (data_reference_p, else_datarefs, j, else_dr)
 +        {
 +          if (DR_IS_READ (else_dr))
 +            continue;
 +
 +          else_store = DR_STMT (else_dr);
 +          else_lhs = gimple_assign_lhs (else_store);
 +
 +          if (operand_equal_p (then_lhs, else_lhs, 0))
 +            {
 +              found = true;
 +              break;
 +            }
 +        }
 +
 +      if (!found)
 +        continue;
 +
 +      res = cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
 +                                              then_store, else_store);

 So you are executing if-else store replacement for common data reference
 pairs only.  I think it's cheaper to collect those pairs before computing
 dependences and only if there is at least one pair perform the optimization.

 OK, I changed the order.


 You basically perform store sinking, creating a PHI node for each store
 you sink (that's then probably if-converted by if-conversion later, 
 eventually
 redundant with -ftree-loop-if-convert-stores?)

 I am concerned that having no bound on the number of stores sunk will
 increase register pressure and does not allow scheduling of the stores
 in an optimal way.  Consider two BBs similar to

  t = a + b;
  *p = t;
  t = c + d;
  *q = t;

 where the transformation undoes a good schedule and makes fixing it
 impossible if the remaining 

Re: [patch] Enhance conditional store sinking

2011-03-17 Thread Richard Guenther
On Wed, Mar 16, 2011 at 12:47 PM, Ira Rosen ira.ro...@linaro.org wrote:
 On 16 March 2011 12:29, Richard Guenther richard.guent...@gmail.com wrote:
 On Wed, Mar 16, 2011 at 7:49 AM, Ira Rosen ira.ro...@linaro.org wrote:
 Hi,

 This patch adds a support of conditional store sinking for cases with
 multiple data references in then and else basic blocks. The
 correctness of the transformation is checked by verifying that there
 are no read-after-write and write-after-write dependencies.

 Bootstrapped and tested on powerpc64-suse-linux.
 OK for trunk?

 I will look at the patch later, but can you add a testcase that we don't sink

  if (..)
   {
      *a = i;
      *b = j;
   }
  else
   {
      *b = j;
      *a = i;
   }

 if *a and *b may alias?

 Done.

Comments inline

 Thanks,
 Ira

 ChangeLog:

    * tree-data-ref.c (dr_equal_offsets_p1): Moved and renamed from
    tree-vect-data-refs.c vect_equal_offsets.
    (dr_equal_offsets_p): New function.
    * tree-data-ref.h (dr_equal_offsets_p): Declare.
    * tree-vect-data-refs.c (vect_equal_offsets): Move to tree-data-ref.c.
    (vect_drs_dependent_in_basic_block): Update calls to vect_equal_offsets.
    (vect_check_interleaving): Likewise.
    * tree-ssa-phiopt.c: Include cfgloop.h and tree-data-ref.h.
    (cond_if_else_store_replacement): Rename to...
    (cond_if_else_store_replacement_1): ... this. Change arguments and
    documentation.
    (cond_if_else_store_replacement): New function.
    * Makefile.in (tree-ssa-phiopt.o): Adjust dependencies.

 testsuite/ChangeLog:

    * gcc.dg/vect/vect-cselim-1.c: New test.
    * gcc.dg/vect/vect-cselim-2.c: New test.


 Index: tree-data-ref.c
 ===
 --- tree-data-ref.c     (revision 170712)
 +++ tree-data-ref.c     (working copy)
 @@ -991,6 +991,48 @@ create_data_ref (loop_p nest, loop_p loop, tree me
   return dr;
  }

 +/* Check if OFFSET1 and OFFSET2 (DR_OFFSETs of some data-refs) are identical
 +   expressions.  */
 +static bool
 +dr_equal_offsets_p1 (tree offset1, tree offset2)
 +{
 +  bool res;
 +
 +  STRIP_NOPS (offset1);
 +  STRIP_NOPS (offset2);
 +
 +  if (offset1 == offset2)
 +    return true;
 +
 +  if (TREE_CODE (offset1) != TREE_CODE (offset2)
 +      || (!BINARY_CLASS_P (offset1)  !UNARY_CLASS_P (offset1)))
 +    return false;
 +
 +  res = dr_equal_offsets_p1 (TREE_OPERAND (offset1, 0),
 +                             TREE_OPERAND (offset2, 0));
 +
 +  if (!res || !BINARY_CLASS_P (offset1))
 +    return res;
 +
 +  res = dr_equal_offsets_p1 (TREE_OPERAND (offset1, 1),
 +                             TREE_OPERAND (offset2, 1));
 +
 +  return res;
 +}
 +
 +/* Check if DRA and DRB have equal offsets.  */
 +bool
 +dr_equal_offsets_p (struct data_reference *dra,
 +                    struct data_reference *drb)
 +{
 +  tree offset1, offset2;
 +
 +  offset1 = DR_OFFSET (dra);
 +  offset2 = DR_OFFSET (drb);
 +
 +  return dr_equal_offsets_p1 (offset1, offset2);
 +}
 +
  /* Returns true if FNA == FNB.  */

  static bool
 Index: tree-data-ref.h
 ===
 --- tree-data-ref.h     (revision 170712)
 +++ tree-data-ref.h     (working copy)
 @@ -430,6 +430,8 @@ extern void compute_all_dependences (VEC (data_ref
  extern void create_rdg_vertices (struct graph *, VEC (gimple, heap) *);
  extern bool dr_may_alias_p (const struct data_reference *,
                            const struct data_reference *);
 +extern bool dr_equal_offsets_p (struct data_reference *,
 +                                struct data_reference *);


  /* Return true when the base objects of data references A and B are
 Index: tree-vect-data-refs.c
 ===
 --- tree-vect-data-refs.c       (revision 170712)
 +++ tree-vect-data-refs.c       (working copy)
 @@ -289,39 +289,6 @@ vect_update_interleaving_chain (struct data_refere
     }
  }

 -
 -/* Function vect_equal_offsets.
 -
 -   Check if OFFSET1 and OFFSET2 are identical expressions.  */
 -
 -static bool
 -vect_equal_offsets (tree offset1, tree offset2)
 -{
 -  bool res;
 -
 -  STRIP_NOPS (offset1);
 -  STRIP_NOPS (offset2);
 -
 -  if (offset1 == offset2)
 -    return true;
 -
 -  if (TREE_CODE (offset1) != TREE_CODE (offset2)
 -      || (!BINARY_CLASS_P (offset1)  !UNARY_CLASS_P (offset1)))
 -    return false;
 -
 -  res = vect_equal_offsets (TREE_OPERAND (offset1, 0),
 -                           TREE_OPERAND (offset2, 0));
 -
 -  if (!res || !BINARY_CLASS_P (offset1))
 -    return res;
 -
 -  res = vect_equal_offsets (TREE_OPERAND (offset1, 1),
 -                           TREE_OPERAND (offset2, 1));
 -
 -  return res;
 -}
 -
 -
  /* Check dependence between DRA and DRB for basic block vectorization.
    If the accesses share same bases and offsets, we can compare their initial
    constant offsets to decide whether they differ or not.  In case of a read-
 @@ -352,7 +319,7 @@ 

Re: [patch] Enhance conditional store sinking

2011-03-17 Thread Richard Guenther
On Thu, Mar 17, 2011 at 3:53 PM, Jeff Law l...@redhat.com wrote:
 -BEGIN PGP SIGNED MESSAGE-
 Hash: SHA1

 On 03/17/11 08:48, Richard Guenther wrote:

 The gimple_uids are not initialized here, you need to make sure to
 call renumber_gimple_stmt_uids () before starting.  Note that phiopt
 incrementally changes the IL, so I'm not sure those uids will stay
 valid as stmts are moved across blocks.
 BTW, it's probably worth noting that renumber_gimple_stmt_uids doesn't
 assign UIDs for PHI nodes.  Worse yet, someone might have called
 renumber_gimple_stmt_uids_in_blocks which *does* assign UIDs to PHIs.
 The net result is you can have a PHI with a UID that conflicts with a
 statement's UID or a PHI with no UID.

 It may not matter for this code, but having been recently bitten by
 this, I thought I'd mention it.

Yep ;)  It's worth fixing this inconsistency btw.

Richard.



 jeff
 -BEGIN PGP SIGNATURE-
 Version: GnuPG v1.4.11 (GNU/Linux)
 Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

 iQEcBAEBAgAGBQJNgiBoAAoJEBRtltQi2kC7dLMH+QEhaTqTxoqDnOeMFTb0OLLi
 31BT3yDcSD0gEkFCZQB5qWo7RBBaepnRMtDpOxmGKcY8VlCvWdRDz6aFLlzDphzC
 XWD/M4i01Of0tjIlCJqDVsUZklD2dvPOz0pwQpX5fteoGNedNGp5Xwq72Wq5YRKW
 IcgpsRN/xbFA4HDk8ZfW5dkb+eQQptGHz5zj9KUz0pQbjqGS6e0oFIHCygwVW7u/
 zhGuD16OhtNS6Z5gkVs9j1POZOSAb7GawB0p5W0lJigzqRfLPIYLuOjtgZrLdgXQ
 3oK6uMX4WwZJK3PBT7Lo8MNTTnxjJZc4iL0SLArtd+U11QnxnsSIqKX9FBtX25A=
 =d7Vy
 -END PGP SIGNATURE-



Re: [patch] Enhance conditional store sinking

2011-03-16 Thread Ira Rosen
On 16 March 2011 12:29, Richard Guenther richard.guent...@gmail.com wrote:
 On Wed, Mar 16, 2011 at 7:49 AM, Ira Rosen ira.ro...@linaro.org wrote:
 Hi,

 This patch adds a support of conditional store sinking for cases with
 multiple data references in then and else basic blocks. The
 correctness of the transformation is checked by verifying that there
 are no read-after-write and write-after-write dependencies.

 Bootstrapped and tested on powerpc64-suse-linux.
 OK for trunk?

 I will look at the patch later, but can you add a testcase that we don't sink

  if (..)
   {
      *a = i;
      *b = j;
   }
  else
   {
      *b = j;
      *a = i;
   }

 if *a and *b may alias?

Done.

Thanks,
Ira

ChangeLog:

* tree-data-ref.c (dr_equal_offsets_p1): Moved and renamed from
tree-vect-data-refs.c vect_equal_offsets.
(dr_equal_offsets_p): New function.
* tree-data-ref.h (dr_equal_offsets_p): Declare.
* tree-vect-data-refs.c (vect_equal_offsets): Move to tree-data-ref.c.
(vect_drs_dependent_in_basic_block): Update calls to vect_equal_offsets.
(vect_check_interleaving): Likewise.
* tree-ssa-phiopt.c: Include cfgloop.h and tree-data-ref.h.
(cond_if_else_store_replacement): Rename to...
(cond_if_else_store_replacement_1): ... this. Change arguments and
documentation.
(cond_if_else_store_replacement): New function.
* Makefile.in (tree-ssa-phiopt.o): Adjust dependencies.

testsuite/ChangeLog:

* gcc.dg/vect/vect-cselim-1.c: New test.
* gcc.dg/vect/vect-cselim-2.c: New test.


Index: tree-data-ref.c
===
--- tree-data-ref.c (revision 170712)
+++ tree-data-ref.c (working copy)
@@ -991,6 +991,48 @@ create_data_ref (loop_p nest, loop_p loop, tree me
   return dr;
 }

+/* Check if OFFSET1 and OFFSET2 (DR_OFFSETs of some data-refs) are identical
+   expressions.  */
+static bool
+dr_equal_offsets_p1 (tree offset1, tree offset2)
+{
+  bool res;
+
+  STRIP_NOPS (offset1);
+  STRIP_NOPS (offset2);
+
+  if (offset1 == offset2)
+return true;
+
+  if (TREE_CODE (offset1) != TREE_CODE (offset2)
+  || (!BINARY_CLASS_P (offset1)  !UNARY_CLASS_P (offset1)))
+return false;
+
+  res = dr_equal_offsets_p1 (TREE_OPERAND (offset1, 0),
+ TREE_OPERAND (offset2, 0));
+
+  if (!res || !BINARY_CLASS_P (offset1))
+return res;
+
+  res = dr_equal_offsets_p1 (TREE_OPERAND (offset1, 1),
+ TREE_OPERAND (offset2, 1));
+
+  return res;
+}
+
+/* Check if DRA and DRB have equal offsets.  */
+bool
+dr_equal_offsets_p (struct data_reference *dra,
+struct data_reference *drb)
+{
+  tree offset1, offset2;
+
+  offset1 = DR_OFFSET (dra);
+  offset2 = DR_OFFSET (drb);
+
+  return dr_equal_offsets_p1 (offset1, offset2);
+}
+
 /* Returns true if FNA == FNB.  */

 static bool
Index: tree-data-ref.h
===
--- tree-data-ref.h (revision 170712)
+++ tree-data-ref.h (working copy)
@@ -430,6 +430,8 @@ extern void compute_all_dependences (VEC (data_ref
 extern void create_rdg_vertices (struct graph *, VEC (gimple, heap) *);
 extern bool dr_may_alias_p (const struct data_reference *,
const struct data_reference *);
+extern bool dr_equal_offsets_p (struct data_reference *,
+struct data_reference *);


 /* Return true when the base objects of data references A and B are
Index: tree-vect-data-refs.c
===
--- tree-vect-data-refs.c   (revision 170712)
+++ tree-vect-data-refs.c   (working copy)
@@ -289,39 +289,6 @@ vect_update_interleaving_chain (struct data_refere
 }
 }

-
-/* Function vect_equal_offsets.
-
-   Check if OFFSET1 and OFFSET2 are identical expressions.  */
-
-static bool
-vect_equal_offsets (tree offset1, tree offset2)
-{
-  bool res;
-
-  STRIP_NOPS (offset1);
-  STRIP_NOPS (offset2);
-
-  if (offset1 == offset2)
-return true;
-
-  if (TREE_CODE (offset1) != TREE_CODE (offset2)
-  || (!BINARY_CLASS_P (offset1)  !UNARY_CLASS_P (offset1)))
-return false;
-
-  res = vect_equal_offsets (TREE_OPERAND (offset1, 0),
-   TREE_OPERAND (offset2, 0));
-
-  if (!res || !BINARY_CLASS_P (offset1))
-return res;
-
-  res = vect_equal_offsets (TREE_OPERAND (offset1, 1),
-   TREE_OPERAND (offset2, 1));
-
-  return res;
-}
-
-
 /* Check dependence between DRA and DRB for basic block vectorization.
If the accesses share same bases and offsets, we can compare their initial
constant offsets to decide whether they differ or not.  In case of a read-
@@ -352,7 +319,7 @@ vect_drs_dependent_in_basic_block (struct data_ref
|| TREE_CODE (DR_BASE_ADDRESS (drb)) != ADDR_EXPR
|| TREE_OPERAND (DR_BASE_ADDRESS (dra), 0)
!= TREE_OPERAND (DR_BASE_ADDRESS (drb),0)))
-