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 a good schedule and makes fixing it
>>> impossible if the remaining statements are not if-convertible.
>>>
>>> Thus, I'd rather make this transformation only if in the end the conditional
>>> can be completely if-converted.
>>>
>>> I realize that we already do unbound and very aggressive if-conversion
>>> in tree-ifcvt.c regardless of whether the loop will be vectorized or not
>>> (including leaking the if-converted loops to the various loop versions
>>> we create during vectorization, causing only code-size bloat).  But it's
>>> not a good reason to continue down this road ;)
>>>
>>> I suppose a simple maximum on the number of stores to sink
>>> controllable by a param should do, eventually disabling this
>>> extended transformation when vectorization is disabled?
>>
>> I added a param, and it's set to 0 if either vectorization or if-conversion
>> is disabled.
>>
>>>
>>> Otherwise the implementation looks good.
>>
>> Bootstrapped and tested on powerpc64-suse-linux.
>> OK to apply?
>>
>> Thanks,
>> Ira
>>
>> ChangeLog:
>>
>>     * doc/invoke.texi (max-stores-to-sink): Document.
>>     * params.h (MAX_STORES_TO_SINK): Define.
>>     * opts.c (finish_options): Set MAX_STORES_TO_SINK to 0
>>     if either vectorization or if-conversion is disabled.
>>     * 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.
>>     (find_data_references_in_bb): Remove static.
>>     * tree-data-ref.h (find_data_references_in_bb): Declare.
>>     (dr_equal_offsets_p): Likewise.
>>     * 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.
>>     * params.def (PARAM_MAX_STORES_TO_SINK): Define.
>>
>> testsuite/ChangeLog:
>>
>>     * gcc.dg/vect/vect-cselim-1.c: New test.
>>     * gcc.dg/vect/vect-cselim-2.c: New test.
>>
>
> This caused:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48270

Yep, I see

FAIL: gcc.c-torture/execute/builtins/strlen-2.c compilation,  -O3 -fomit-frame-p
ointer  (internal compiler error)

on x86_64-linux with

#0  0x0000000001f53253 in gimple_uid (g=0x0)
    at /space/rguenther/src/svn/trunk/gcc/gimple.h:1297
1297      return g->gsbase.uid;
(gdb)
Bottom (innermost) frame selected; you cannot go down.
(gdb) up
#1  0x0000000001f7753d in cond_if_else_store_replacement (
    then_bb=0x7ffff533abc8, else_bb=0x7ffff533ac30, join_bb=0x7ffff533ac98)
    at /space/rguenther/src/svn/trunk/gcc/tree-ssa-phiopt.c:1511
1511          if (DDR_ARE_DEPENDENT (ddr) != chrec_known

DR_STMT of dra is NULL.  No idea how that can happen.

Richard.

Reply via email to