diff mbox

[RFC,V2] : RE: [RFC] [Patch] Relax tree-if-conv.c trap assumptions.

Message ID CY1PR1201MB10980D2DAAC082241FDE10788F1F0@CY1PR1201MB1098.namprd12.prod.outlook.com
State New
Headers show

Commit Message

Kumar, Venkataramanan Nov. 15, 2015, 11:14 a.m. UTC
Hi Richard  and Bernhard.

> -----Original Message-----

> From: Richard Biener [mailto:richard.guenther@gmail.com]

> Sent: Tuesday, November 10, 2015 5:33 PM

> To: Kumar, Venkataramanan

> Cc: Andrew Pinski; gcc-patches@gcc.gnu.org

> Subject: Re: [RFC] [PATCH V2]: RE: [RFC] [Patch] Relax tree-if-conv.c trap

> assumptions.

> 

> On Sat, Nov 7, 2015 at 12:41 PM, Kumar, Venkataramanan

> <Venkataramanan.Kumar@amd.com> wrote:

> > Hi Richard,

> >

> > I have now implemented storing of DR and references using hash maps.

> > Please find attached patch.

> >

> > As discussed, I am now storing the ref, DR  and baseref, DR pairs along with

> unconditional read/write information  in  hash tables while iterating over DR

> during its initialization.

> > Then during checking for possible traps for if-converting,  just check if the

> memory reference for a gimple statement is read/written unconditionally by

> querying the hash table instead of quadratic walk.

> >

> > Boot strapped and regression tested on x86_64.

> 

> @@ -592,137 +598,153 @@ struct ifc_dr {

> 

>    /* -1 when not initialized, 0 when false, 1 when true.  */

>    int rw_unconditionally;

> +

> +  tree ored_result;

> +

> 

> excess vertical space at the end.  A better name would be simply "predicate".

> 

> +  if (!exsist1)

> +    {

> +      if (is_true_predicate (ca))

> +       {

> +         DR_RW_UNCONDITIONALLY (a) = 1;

> +       }

> 

> -            while (TREE_CODE (ref_base_a) == COMPONENT_REF

> -                   || TREE_CODE (ref_base_a) == IMAGPART_EXPR

> -                   || TREE_CODE (ref_base_a) == REALPART_EXPR)

> -              ref_base_a = TREE_OPERAND (ref_base_a, 0);

> +      IFC_DR (a)->ored_result = ca;

> +      *master_dr = a;

> +     }

> +  else

> +    {

> +      IFC_DR (*master_dr)->ored_result

> +        = fold_or_predicates

> +               (EXPR_LOCATION (IFC_DR (*master_dr)->ored_result),

> +                ca, IFC_DR (*master_dr)->ored_result);

> 

> -            while (TREE_CODE (ref_base_b) == COMPONENT_REF

> -                   || TREE_CODE (ref_base_b) == IMAGPART_EXPR

> -                   || TREE_CODE (ref_base_b) == REALPART_EXPR)

> -              ref_base_b = TREE_OPERAND (ref_base_b, 0);

> +      if (is_true_predicate (ca)

> +         || is_true_predicate (IFC_DR (*master_dr)->ored_result))

> +       {

> +         DR_RW_UNCONDITIONALLY (*master_dr) = 1;

> +       }

> +      }

> 

> please common the predicate handling from both cases, that is, do

> 

>    if (is_true_predicate (IFC_DR (*master_dr)->ored_result))

>     DR_RW_...

> 

> after the if.  Note no {}s around single stmts.

> 

> Likewise for the base_master_dr code.

> 

> +      if (!found)

> +       {

> +         DR_WRITTEN_AT_LEAST_ONCE (a) =0;

> +         DR_RW_UNCONDITIONALLY (a) = 0;

> +         return false;

> 

> no need to update the flags on non-"master" DRs.

> 

> Please remove the 'found' variable and simply return 'true'

> whenever found.

> 

>  static bool

>  ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> refs)  {

> -  return write_memrefs_written_at_least_once (stmt, refs)

> -    && memrefs_read_or_written_unconditionally (stmt, refs);

> +  return memrefs_read_or_written_unconditionally (stmt, refs);

> 

> please simply inline memrefs_read_or_written_unconditionally here.

> 

> +  if (ref_DR_map)

> +    delete ref_DR_map;

> +  ref_DR_map = NULL;

> +

> +  if (baseref_DR_map)

> +    delete baseref_DR_map;

> + baseref_DR_map = NULL;

> 

> at this point the pointers will never be NULL.

> 

> Ok with those changes.


The attached patch addresses all the review comments and is rebased to current trunk.
GCC regression test and bootstrap passed.  

Wanted to check with you once before committing it to trunk.
Ok for trunk?

gcc/ChangeLog

2015-11-15  Venkataramanan  <Venkataramanan.Kumar@amd.com>
	* tree-if-conv.c  (ref_DR_map): Define.
	(baseref_DR_map): Like wise
    	(struct ifc_dr): Add new tree predicate field.
    	(hash_memrefs_baserefs_and_store_DRs_read_written_info): New function.
    	(memrefs_read_or_written_unconditionally):  Use hash maps to query 
	unconditional read/written information.
    	(write_memrefs_written_at_least_once): Remove.
	(ifcvt_memrefs_wont_trap): Remove call to 
	write_memrefs_written_at_least_once.
    	(if_convertible_loop_p_1):  Initialize hash maps and predicates
	before hashing data references.
	* tree-data-ref.h  (decl_binds_to_current_def_p): Declare .

gcc/testsuite/ChangeLog
2015-11-15  Venkataramanan  <Venkataramanan.Kumar@amd.com>
	* gcc.dg/tree-ssa/ifc-8.c:  Add new.


Regards,
Venkat.
 
> 

> Note the tree-hash-traits.h part is already committed.

> 

> 

> > gcc/ChangeLog

> >  2015-11-07  Venkataramanan  <Venkataramanan.Kumar@amd.com>

> >

> >         *tree-hash-traits.h (struct tree_operand_hash). Use compare_type

> and value_type.

> >           (equal_keys): Rename to equal and use compare_type and

> value_type.

> >         * tree-if-conv.c (ref_DR_map): Define.

> >            (baseref_DR_map): Like wise

> >            (struct ifc_dr):  New tree predicate field.

> >            (hash_memrefs_baserefs_and_store_DRs_read_written_info): New

> function.

> >            (memrefs_read_or_written_unconditionally):  Use hashmap to query

> unconditional read/written information.

> >           (write_memrefs_written_at_least_once) : Remove.

> >           (ifcvt_memrefs_wont_trap): Remove call to

> write_memrefs_written_at_least_once.

> >           (if_convertible_loop_p_1):  Initialize/delete hash maps an initialize

> predicates

> >           before  the call to

> hash_memrefs_baserefs_and_store_DRs_read_written_info.

> 

> Watch changelog formatting.

> 

> Thanks,

> Richard.

> 

> > gcc/testsuite/ChangeLog

> > 2015-11-07  Venkataramanan  <Venkataramanan.Kumar@amd.com>

> >        *gcc.dg/tree-ssa/ifc-8.c:  Add new.

> >

> > Ok for trunk?

> >

> > Regards,

> > Venkat.

> >>

> >> >> > +                 }

> >> >> > +             }

> >> >> > +    }

> >> >> > +  return found;

> >> >> > +}

> >> >> > +

> >> >> > /* Return true when the memory references of STMT won't trap in

> the

> >> >> >     if-converted code.  There are two things that we have to check for:

> >> >> >

> >> >> > @@ -748,8 +776,20 @@ write_memrefs_written_at_least_once

> >> (gimple

> >> >> > *stmt, static bool ifcvt_memrefs_wont_trap (gimple *stmt,

> >> >> > vec<data_reference_p> refs) {

> >> >> > -  return write_memrefs_written_at_least_once (stmt, refs)

> >> >> > -    && memrefs_read_or_written_unconditionally (stmt, refs);

> >> >> > +  bool memrefs_written_once,

> >> memrefs_read_written_unconditionally;

> >> >> > +  bool memrefs_safe_to_access;

> >> >> > +

> >> >> > +  memrefs_written_once

> >> >> > +             = write_memrefs_written_at_least_once (stmt,

> >> >> > + refs);

> >> >> > +

> >> >> > +  memrefs_read_written_unconditionally

> >> >> > +             =  memrefs_read_or_written_unconditionally (stmt,

> >> >> > + refs);

> >> >> > +

> >> >> > +  memrefs_safe_to_access

> >> >> > +             = write_memrefs_safe_to_access_unconditionally

> >> >> > + (stmt, refs);

> >> >> > +

> >> >> > +  return ((memrefs_written_once || memrefs_safe_to_access)

> >> >> > +                && memrefs_read_written_unconditionally);

> >> >> > }

> >> >> >

> >> >> >  /* Wrapper around gimple_could_trap_p refined for the needs of

> >> >> > the

> >> >> >

> >> >> >

> >> >> > do I need this function write_memrefs_written_at_least_once

> >> anymore?

> >> >> > Please suggest if there a better way to do this.

> >> >> >

> >> >> > Bootstrapped and regression  tested on x86_64.

> >> >> > I am not  adding change log and comments now, as I  wanted to

> >> >> > check

> >> >> approach first.

> >> >> >

> >> >> > Regards,

> >> >> > Venkat.

> >> >> >

> >> >> >

> >

Comments

Richard Biener Nov. 16, 2015, 9:58 a.m. UTC | #1
On Sun, Nov 15, 2015 at 12:14 PM, Kumar, Venkataramanan
<Venkataramanan.Kumar@amd.com> wrote:
> Hi Richard  and Bernhard.
>
>> -----Original Message-----
>> From: Richard Biener [mailto:richard.guenther@gmail.com]
>> Sent: Tuesday, November 10, 2015 5:33 PM
>> To: Kumar, Venkataramanan
>> Cc: Andrew Pinski; gcc-patches@gcc.gnu.org
>> Subject: Re: [RFC] [PATCH V2]: RE: [RFC] [Patch] Relax tree-if-conv.c trap
>> assumptions.
>>
>> On Sat, Nov 7, 2015 at 12:41 PM, Kumar, Venkataramanan
>> <Venkataramanan.Kumar@amd.com> wrote:
>> > Hi Richard,
>> >
>> > I have now implemented storing of DR and references using hash maps.
>> > Please find attached patch.
>> >
>> > As discussed, I am now storing the ref, DR  and baseref, DR pairs along with
>> unconditional read/write information  in  hash tables while iterating over DR
>> during its initialization.
>> > Then during checking for possible traps for if-converting,  just check if the
>> memory reference for a gimple statement is read/written unconditionally by
>> querying the hash table instead of quadratic walk.
>> >
>> > Boot strapped and regression tested on x86_64.
>>
>> @@ -592,137 +598,153 @@ struct ifc_dr {
>>
>>    /* -1 when not initialized, 0 when false, 1 when true.  */
>>    int rw_unconditionally;
>> +
>> +  tree ored_result;
>> +
>>
>> excess vertical space at the end.  A better name would be simply "predicate".
>>
>> +  if (!exsist1)
>> +    {
>> +      if (is_true_predicate (ca))
>> +       {
>> +         DR_RW_UNCONDITIONALLY (a) = 1;
>> +       }
>>
>> -            while (TREE_CODE (ref_base_a) == COMPONENT_REF
>> -                   || TREE_CODE (ref_base_a) == IMAGPART_EXPR
>> -                   || TREE_CODE (ref_base_a) == REALPART_EXPR)
>> -              ref_base_a = TREE_OPERAND (ref_base_a, 0);
>> +      IFC_DR (a)->ored_result = ca;
>> +      *master_dr = a;
>> +     }
>> +  else
>> +    {
>> +      IFC_DR (*master_dr)->ored_result
>> +        = fold_or_predicates
>> +               (EXPR_LOCATION (IFC_DR (*master_dr)->ored_result),
>> +                ca, IFC_DR (*master_dr)->ored_result);
>>
>> -            while (TREE_CODE (ref_base_b) == COMPONENT_REF
>> -                   || TREE_CODE (ref_base_b) == IMAGPART_EXPR
>> -                   || TREE_CODE (ref_base_b) == REALPART_EXPR)
>> -              ref_base_b = TREE_OPERAND (ref_base_b, 0);
>> +      if (is_true_predicate (ca)
>> +         || is_true_predicate (IFC_DR (*master_dr)->ored_result))
>> +       {
>> +         DR_RW_UNCONDITIONALLY (*master_dr) = 1;
>> +       }
>> +      }
>>
>> please common the predicate handling from both cases, that is, do
>>
>>    if (is_true_predicate (IFC_DR (*master_dr)->ored_result))
>>     DR_RW_...
>>
>> after the if.  Note no {}s around single stmts.
>>
>> Likewise for the base_master_dr code.
>>
>> +      if (!found)
>> +       {
>> +         DR_WRITTEN_AT_LEAST_ONCE (a) =0;
>> +         DR_RW_UNCONDITIONALLY (a) = 0;
>> +         return false;
>>
>> no need to update the flags on non-"master" DRs.
>>
>> Please remove the 'found' variable and simply return 'true'
>> whenever found.
>>
>>  static bool
>>  ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> refs)  {
>> -  return write_memrefs_written_at_least_once (stmt, refs)
>> -    && memrefs_read_or_written_unconditionally (stmt, refs);
>> +  return memrefs_read_or_written_unconditionally (stmt, refs);
>>
>> please simply inline memrefs_read_or_written_unconditionally here.
>>
>> +  if (ref_DR_map)
>> +    delete ref_DR_map;
>> +  ref_DR_map = NULL;
>> +
>> +  if (baseref_DR_map)
>> +    delete baseref_DR_map;
>> + baseref_DR_map = NULL;
>>
>> at this point the pointers will never be NULL.
>>
>> Ok with those changes.
>
> The attached patch addresses all the review comments and is rebased to current trunk.
> GCC regression test and bootstrap passed.
>
> Wanted to check with you once before committing it to trunk.
> Ok for trunk?
>
> gcc/ChangeLog
>
> 2015-11-15  Venkataramanan  <Venkataramanan.Kumar@amd.com>
>         * tree-if-conv.c  (ref_DR_map): Define.
>         (baseref_DR_map): Like wise
>         (struct ifc_dr): Add new tree predicate field.
>         (hash_memrefs_baserefs_and_store_DRs_read_written_info): New function.
>         (memrefs_read_or_written_unconditionally):  Use hash maps to query
>         unconditional read/written information.
>         (write_memrefs_written_at_least_once): Remove.
>         (ifcvt_memrefs_wont_trap): Remove call to
>         write_memrefs_written_at_least_once.
>         (if_convertible_loop_p_1):  Initialize hash maps and predicates
>         before hashing data references.
>         * tree-data-ref.h  (decl_binds_to_current_def_p): Declare .

It's already declared in varasm.h which you need to include.

You are correct in that we don't handle multiple data references in a
single stmt
in ifcvt_memrefs_wont_trap but that's a situation that cannot not happen.

So it would be nice to make this clearer by changing the function to
not loop over
all DRs but instead just do

  data_reference_p a = drs[gimple_uid (stmt) - 1];
  gcc_assert (DR_STMT (a) == stmt);

instead of the for() loop.

Ok with that change.

Thanks,
Richard.

>
> gcc/testsuite/ChangeLog
> 2015-11-15  Venkataramanan  <Venkataramanan.Kumar@amd.com>
>         * gcc.dg/tree-ssa/ifc-8.c:  Add new.
>
>
> Regards,
> Venkat.
>
>>
>> Note the tree-hash-traits.h part is already committed.
>>
>>
>> > gcc/ChangeLog
>> >  2015-11-07  Venkataramanan  <Venkataramanan.Kumar@amd.com>
>> >
>> >         *tree-hash-traits.h (struct tree_operand_hash). Use compare_type
>> and value_type.
>> >           (equal_keys): Rename to equal and use compare_type and
>> value_type.
>> >         * tree-if-conv.c (ref_DR_map): Define.
>> >            (baseref_DR_map): Like wise
>> >            (struct ifc_dr):  New tree predicate field.
>> >            (hash_memrefs_baserefs_and_store_DRs_read_written_info): New
>> function.
>> >            (memrefs_read_or_written_unconditionally):  Use hashmap to query
>> unconditional read/written information.
>> >           (write_memrefs_written_at_least_once) : Remove.
>> >           (ifcvt_memrefs_wont_trap): Remove call to
>> write_memrefs_written_at_least_once.
>> >           (if_convertible_loop_p_1):  Initialize/delete hash maps an initialize
>> predicates
>> >           before  the call to
>> hash_memrefs_baserefs_and_store_DRs_read_written_info.
>>
>> Watch changelog formatting.
>>
>> Thanks,
>> Richard.
>>
>> > gcc/testsuite/ChangeLog
>> > 2015-11-07  Venkataramanan  <Venkataramanan.Kumar@amd.com>
>> >        *gcc.dg/tree-ssa/ifc-8.c:  Add new.
>> >
>> > Ok for trunk?
>> >
>> > Regards,
>> > Venkat.
>> >>
>> >> >> > +                 }
>> >> >> > +             }
>> >> >> > +    }
>> >> >> > +  return found;
>> >> >> > +}
>> >> >> > +
>> >> >> > /* Return true when the memory references of STMT won't trap in
>> the
>> >> >> >     if-converted code.  There are two things that we have to check for:
>> >> >> >
>> >> >> > @@ -748,8 +776,20 @@ write_memrefs_written_at_least_once
>> >> (gimple
>> >> >> > *stmt, static bool ifcvt_memrefs_wont_trap (gimple *stmt,
>> >> >> > vec<data_reference_p> refs) {
>> >> >> > -  return write_memrefs_written_at_least_once (stmt, refs)
>> >> >> > -    && memrefs_read_or_written_unconditionally (stmt, refs);
>> >> >> > +  bool memrefs_written_once,
>> >> memrefs_read_written_unconditionally;
>> >> >> > +  bool memrefs_safe_to_access;
>> >> >> > +
>> >> >> > +  memrefs_written_once
>> >> >> > +             = write_memrefs_written_at_least_once (stmt,
>> >> >> > + refs);
>> >> >> > +
>> >> >> > +  memrefs_read_written_unconditionally
>> >> >> > +             =  memrefs_read_or_written_unconditionally (stmt,
>> >> >> > + refs);
>> >> >> > +
>> >> >> > +  memrefs_safe_to_access
>> >> >> > +             = write_memrefs_safe_to_access_unconditionally
>> >> >> > + (stmt, refs);
>> >> >> > +
>> >> >> > +  return ((memrefs_written_once || memrefs_safe_to_access)
>> >> >> > +                && memrefs_read_written_unconditionally);
>> >> >> > }
>> >> >> >
>> >> >> >  /* Wrapper around gimple_could_trap_p refined for the needs of
>> >> >> > the
>> >> >> >
>> >> >> >
>> >> >> > do I need this function write_memrefs_written_at_least_once
>> >> anymore?
>> >> >> > Please suggest if there a better way to do this.
>> >> >> >
>> >> >> > Bootstrapped and regression  tested on x86_64.
>> >> >> > I am not  adding change log and comments now, as I  wanted to
>> >> >> > check
>> >> >> approach first.
>> >> >> >
>> >> >> > Regards,
>> >> >> > Venkat.
>> >> >> >
>> >> >> >
>> >
Kumar, Venkataramanan Nov. 17, 2015, 7:48 a.m. UTC | #2
Hi Richard,


> -----Original Message-----

> From: Richard Biener [mailto:richard.guenther@gmail.com]

> Sent: Monday, November 16, 2015 3:28 PM

> To: Kumar, Venkataramanan

> Cc: Bernhard Reutner-Fischer; Andrew Pinski; gcc-patches@gcc.gnu.org

> Subject: Re: [RFC] [PATCH V2]: RE: [RFC] [Patch] Relax tree-if-conv.c trap

> assumptions.

> 

> On Sun, Nov 15, 2015 at 12:14 PM, Kumar, Venkataramanan

> <Venkataramanan.Kumar@amd.com> wrote:

> > Hi Richard  and Bernhard.

> >

> >> -----Original Message-----

> >> From: Richard Biener [mailto:richard.guenther@gmail.com]

> >> Sent: Tuesday, November 10, 2015 5:33 PM

> >> To: Kumar, Venkataramanan

> >> Cc: Andrew Pinski; gcc-patches@gcc.gnu.org

> >> Subject: Re: [RFC] [PATCH V2]: RE: [RFC] [Patch] Relax tree-if-conv.c

> >> trap assumptions.

> >>

> >> On Sat, Nov 7, 2015 at 12:41 PM, Kumar, Venkataramanan

> >> <Venkataramanan.Kumar@amd.com> wrote:

> >> > Hi Richard,

> >> >

> >> > I have now implemented storing of DR and references using hash maps.

> >> > Please find attached patch.

> >> >

> >> > As discussed, I am now storing the ref, DR  and baseref, DR pairs

> >> > along with

> >> unconditional read/write information  in  hash tables while iterating

> >> over DR during its initialization.

> >> > Then during checking for possible traps for if-converting,  just

> >> > check if the

> >> memory reference for a gimple statement is read/written

> >> unconditionally by querying the hash table instead of quadratic walk.

> >> >

> >> > Boot strapped and regression tested on x86_64.

> >>

> >> @@ -592,137 +598,153 @@ struct ifc_dr {

> >>

> >>    /* -1 when not initialized, 0 when false, 1 when true.  */

> >>    int rw_unconditionally;

> >> +

> >> +  tree ored_result;

> >> +

> >>

> >> excess vertical space at the end.  A better name would be simply

> "predicate".

> >>

> >> +  if (!exsist1)

> >> +    {

> >> +      if (is_true_predicate (ca))

> >> +       {

> >> +         DR_RW_UNCONDITIONALLY (a) = 1;

> >> +       }

> >>

> >> -            while (TREE_CODE (ref_base_a) == COMPONENT_REF

> >> -                   || TREE_CODE (ref_base_a) == IMAGPART_EXPR

> >> -                   || TREE_CODE (ref_base_a) == REALPART_EXPR)

> >> -              ref_base_a = TREE_OPERAND (ref_base_a, 0);

> >> +      IFC_DR (a)->ored_result = ca;

> >> +      *master_dr = a;

> >> +     }

> >> +  else

> >> +    {

> >> +      IFC_DR (*master_dr)->ored_result

> >> +        = fold_or_predicates

> >> +               (EXPR_LOCATION (IFC_DR (*master_dr)->ored_result),

> >> +                ca, IFC_DR (*master_dr)->ored_result);

> >>

> >> -            while (TREE_CODE (ref_base_b) == COMPONENT_REF

> >> -                   || TREE_CODE (ref_base_b) == IMAGPART_EXPR

> >> -                   || TREE_CODE (ref_base_b) == REALPART_EXPR)

> >> -              ref_base_b = TREE_OPERAND (ref_base_b, 0);

> >> +      if (is_true_predicate (ca)

> >> +         || is_true_predicate (IFC_DR (*master_dr)->ored_result))

> >> +       {

> >> +         DR_RW_UNCONDITIONALLY (*master_dr) = 1;

> >> +       }

> >> +      }

> >>

> >> please common the predicate handling from both cases, that is, do

> >>

> >>    if (is_true_predicate (IFC_DR (*master_dr)->ored_result))

> >>     DR_RW_...

> >>

> >> after the if.  Note no {}s around single stmts.

> >>

> >> Likewise for the base_master_dr code.

> >>

> >> +      if (!found)

> >> +       {

> >> +         DR_WRITTEN_AT_LEAST_ONCE (a) =0;

> >> +         DR_RW_UNCONDITIONALLY (a) = 0;

> >> +         return false;

> >>

> >> no need to update the flags on non-"master" DRs.

> >>

> >> Please remove the 'found' variable and simply return 'true'

> >> whenever found.

> >>

> >>  static bool

> >>  ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> refs)

> >> {

> >> -  return write_memrefs_written_at_least_once (stmt, refs)

> >> -    && memrefs_read_or_written_unconditionally (stmt, refs);

> >> +  return memrefs_read_or_written_unconditionally (stmt, refs);

> >>

> >> please simply inline memrefs_read_or_written_unconditionally here.

> >>

> >> +  if (ref_DR_map)

> >> +    delete ref_DR_map;

> >> +  ref_DR_map = NULL;

> >> +

> >> +  if (baseref_DR_map)

> >> +    delete baseref_DR_map;

> >> + baseref_DR_map = NULL;

> >>

> >> at this point the pointers will never be NULL.

> >>

> >> Ok with those changes.

> >

> > The attached patch addresses all the review comments and is rebased to

> current trunk.

> > GCC regression test and bootstrap passed.

> >

> > Wanted to check with you once before committing it to trunk.

> > Ok for trunk?

> >

> > gcc/ChangeLog

> >

> > 2015-11-15  Venkataramanan  <Venkataramanan.Kumar@amd.com>

> >         * tree-if-conv.c  (ref_DR_map): Define.

> >         (baseref_DR_map): Like wise

> >         (struct ifc_dr): Add new tree predicate field.

> >         (hash_memrefs_baserefs_and_store_DRs_read_written_info): New

> function.

> >         (memrefs_read_or_written_unconditionally):  Use hash maps to query

> >         unconditional read/written information.

> >         (write_memrefs_written_at_least_once): Remove.

> >         (ifcvt_memrefs_wont_trap): Remove call to

> >         write_memrefs_written_at_least_once.

> >         (if_convertible_loop_p_1):  Initialize hash maps and predicates

> >         before hashing data references.

> >         * tree-data-ref.h  (decl_binds_to_current_def_p): Declare .

> 

> It's already declared in varasm.h which you need to include.

> 

> You are correct in that we don't handle multiple data references in a single

> stmt in ifcvt_memrefs_wont_trap but that's a situation that cannot not

> happen.

> 

> So it would be nice to make this clearer by changing the function to not loop

> over all DRs but instead just do

> 

>   data_reference_p a = drs[gimple_uid (stmt) - 1];

>   gcc_assert (DR_STMT (a) == stmt);

> 

> instead of the for() loop.

> 

> Ok with that change.


Up streamed  the changes after Boot strap and regression testing on X86_64 target. 

Ref: https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=230454

Regards,
Venkat.

> 

> Thanks,

> Richard.

> 

> >

> > gcc/testsuite/ChangeLog

> > 2015-11-15  Venkataramanan  <Venkataramanan.Kumar@amd.com>

> >         * gcc.dg/tree-ssa/ifc-8.c:  Add new.

> >

> >

> > Regards,

> > Venkat.

> >

> >>

> >> Note the tree-hash-traits.h part is already committed.

> >>

> >>

> >> > gcc/ChangeLog

> >> >  2015-11-07  Venkataramanan  <Venkataramanan.Kumar@amd.com>

> >> >

> >> >         *tree-hash-traits.h (struct tree_operand_hash). Use

> >> > compare_type

> >> and value_type.

> >> >           (equal_keys): Rename to equal and use compare_type and

> >> value_type.

> >> >         * tree-if-conv.c (ref_DR_map): Define.

> >> >            (baseref_DR_map): Like wise

> >> >            (struct ifc_dr):  New tree predicate field.

> >> >            (hash_memrefs_baserefs_and_store_DRs_read_written_info):

> >> > New

> >> function.

> >> >            (memrefs_read_or_written_unconditionally):  Use hashmap

> >> > to query

> >> unconditional read/written information.

> >> >           (write_memrefs_written_at_least_once) : Remove.

> >> >           (ifcvt_memrefs_wont_trap): Remove call to

> >> write_memrefs_written_at_least_once.

> >> >           (if_convertible_loop_p_1):  Initialize/delete hash maps

> >> > an initialize

> >> predicates

> >> >           before  the call to

> >> hash_memrefs_baserefs_and_store_DRs_read_written_info.

> >>

> >> Watch changelog formatting.

> >>

> >> Thanks,

> >> Richard.

> >>

> >> > gcc/testsuite/ChangeLog

> >> > 2015-11-07  Venkataramanan  <Venkataramanan.Kumar@amd.com>

> >> >        *gcc.dg/tree-ssa/ifc-8.c:  Add new.

> >> >

> >> > Ok for trunk?

> >> >

> >> > Regards,

> >> > Venkat.

> >> >>

> >> >> >> > +                 }

> >> >> >> > +             }

> >> >> >> > +    }

> >> >> >> > +  return found;

> >> >> >> > +}

> >> >> >> > +

> >> >> >> > /* Return true when the memory references of STMT won't trap

> >> >> >> > in

> >> the

> >> >> >> >     if-converted code.  There are two things that we have to check

> for:

> >> >> >> >

> >> >> >> > @@ -748,8 +776,20 @@ write_memrefs_written_at_least_once

> >> >> (gimple

> >> >> >> > *stmt, static bool ifcvt_memrefs_wont_trap (gimple *stmt,

> >> >> >> > vec<data_reference_p> refs) {

> >> >> >> > -  return write_memrefs_written_at_least_once (stmt, refs)

> >> >> >> > -    && memrefs_read_or_written_unconditionally (stmt, refs);

> >> >> >> > +  bool memrefs_written_once,

> >> >> memrefs_read_written_unconditionally;

> >> >> >> > +  bool memrefs_safe_to_access;

> >> >> >> > +

> >> >> >> > +  memrefs_written_once

> >> >> >> > +             = write_memrefs_written_at_least_once (stmt,

> >> >> >> > + refs);

> >> >> >> > +

> >> >> >> > +  memrefs_read_written_unconditionally

> >> >> >> > +             =  memrefs_read_or_written_unconditionally

> >> >> >> > + (stmt, refs);

> >> >> >> > +

> >> >> >> > +  memrefs_safe_to_access

> >> >> >> > +             = write_memrefs_safe_to_access_unconditionally

> >> >> >> > + (stmt, refs);

> >> >> >> > +

> >> >> >> > +  return ((memrefs_written_once || memrefs_safe_to_access)

> >> >> >> > +                && memrefs_read_written_unconditionally);

> >> >> >> > }

> >> >> >> >

> >> >> >> >  /* Wrapper around gimple_could_trap_p refined for the needs

> >> >> >> > of the

> >> >> >> >

> >> >> >> >

> >> >> >> > do I need this function write_memrefs_written_at_least_once

> >> >> anymore?

> >> >> >> > Please suggest if there a better way to do this.

> >> >> >> >

> >> >> >> > Bootstrapped and regression  tested on x86_64.

> >> >> >> > I am not  adding change log and comments now, as I  wanted to

> >> >> >> > check

> >> >> >> approach first.

> >> >> >> >

> >> >> >> > Regards,

> >> >> >> > Venkat.

> >> >> >> >

> >> >> >> >

> >> >
diff mbox

Patch

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c
new file mode 100644
index 0000000..89a3410
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c
@@ -0,0 +1,17 @@ 
+
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-ifcvt-details -fno-common -ftree-loop-if-convert-stores" } */
+
+#define LEN 4096
+ __attribute__((aligned (32))) float array[LEN];
+
+void test ()
+{
+  for (int i = 0; i < LEN; i++)
+    {
+      if (array[i] > (float)0.)
+	array[i] = 3;
+    }
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 4c9e357..d32dce8 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -340,6 +340,7 @@  extern bool dr_may_alias_p (const struct data_reference *,
 			    const struct data_reference *, bool);
 extern bool dr_equal_offsets_p (struct data_reference *,
                                 struct data_reference *);
+extern bool decl_binds_to_current_def_p (const_tree);
 
 /* Return true when the base objects of data references A and B are
    the same memory object.  */
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 88b6405..8f4be60 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -117,6 +117,12 @@  static basic_block *ifc_bbs;
 /* Apply more aggressive (extended) if-conversion if true.  */
 static bool aggressive_if_conv;
 
+/* Hash table to store references, DR pairs.  */
+static hash_map<tree_operand_hash, data_reference_p> *ref_DR_map;
+
+/* Hash table to store base reference, DR pairs.  */
+static hash_map<tree_operand_hash, data_reference_p> *baseref_DR_map;
+
 /* Structure used to predicate basic blocks.  This is attached to the
    ->aux field of the BBs in the loop to be if-converted.  */
 struct bb_predicate {
@@ -580,139 +586,71 @@  struct ifc_dr {
 
   /* -1 when not initialized, 0 when false, 1 when true.  */
   int rw_unconditionally;
+
+  tree predicate;
 };
 
 #define IFC_DR(DR) ((struct ifc_dr *) (DR)->aux)
 #define DR_WRITTEN_AT_LEAST_ONCE(DR) (IFC_DR (DR)->written_at_least_once)
 #define DR_RW_UNCONDITIONALLY(DR) (IFC_DR (DR)->rw_unconditionally)
 
-/* Returns true when the memory references of STMT are read or written
-   unconditionally.  In other words, this function returns true when
-   for every data reference A in STMT there exist other accesses to
-   a data reference with the same base with predicates that add up (OR-up) to
-   the true predicate: this ensures that the data reference A is touched
-   (read or written) on every iteration of the if-converted loop.  */
-
-static bool
-memrefs_read_or_written_unconditionally (gimple *stmt,
-					 vec<data_reference_p> drs)
-{
-  int i, j;
-  data_reference_p a, b;
-  tree ca = bb_predicate (gimple_bb (stmt));
-
-  for (i = 0; drs.iterate (i, &a); i++)
-    if (DR_STMT (a) == stmt)
-      {
-	bool found = false;
-	int x = DR_RW_UNCONDITIONALLY (a);
-
-	if (x == 0)
-	  return false;
-
-	if (x == 1)
-	  continue;
-
-	for (j = 0; drs.iterate (j, &b); j++)
-          {
-            tree ref_base_a = DR_REF (a);
-            tree ref_base_b = DR_REF (b);
-
-            if (DR_STMT (b) == stmt)
-              continue;
-
-            while (TREE_CODE (ref_base_a) == COMPONENT_REF
-                   || TREE_CODE (ref_base_a) == IMAGPART_EXPR
-                   || TREE_CODE (ref_base_a) == REALPART_EXPR)
-              ref_base_a = TREE_OPERAND (ref_base_a, 0);
-
-            while (TREE_CODE (ref_base_b) == COMPONENT_REF
-                   || TREE_CODE (ref_base_b) == IMAGPART_EXPR
-                   || TREE_CODE (ref_base_b) == REALPART_EXPR)
-              ref_base_b = TREE_OPERAND (ref_base_b, 0);
-
-  	    if (operand_equal_p (ref_base_a, ref_base_b, 0))
-	      {
-	        tree cb = bb_predicate (gimple_bb (DR_STMT (b)));
-
-	        if (DR_RW_UNCONDITIONALLY (b) == 1
-		    || is_true_predicate (cb)
-		    || is_true_predicate (ca
-                        = fold_or_predicates (EXPR_LOCATION (cb), ca, cb)))
-		  {
-		    DR_RW_UNCONDITIONALLY (a) = 1;
-  		    DR_RW_UNCONDITIONALLY (b) = 1;
-		    found = true;
-		    break;
-		  }
-               }
-	    }
-
-	if (!found)
-	  {
-	    DR_RW_UNCONDITIONALLY (a) = 0;
-	    return false;
-	  }
-      }
-
-  return true;
-}
-
-/* Returns true when the memory references of STMT are unconditionally
-   written.  In other words, this function returns true when for every
-   data reference A written in STMT, there exist other writes to the
-   same data reference with predicates that add up (OR-up) to the true
-   predicate: this ensures that the data reference A is written on
-   every iteration of the if-converted loop.  */
-
-static bool
-write_memrefs_written_at_least_once (gimple *stmt,
-				     vec<data_reference_p> drs)
+/* Iterates over DR's and stores refs, DR and base refs, DR pairs in
+   HASH tables.  While storing them in HASH table, it checks if the
+   reference is unconditionally read or written and stores that as a flag
+   information.  For base reference it checks if it is written atlest once
+   unconditionally and stores it as flag information along with DR.
+   In other words for every data reference A in STMT there exist other
+   accesses to a data reference with the same base with predicates that
+   add up (OR-up) to the true predicate: this ensures that the data
+   reference A is touched (read or written) on every iteration of the
+   if-converted loop.  */
+static void
+hash_memrefs_baserefs_and_store_DRs_read_written_info (data_reference_p a)
 {
-  int i, j;
-  data_reference_p a, b;
-  tree ca = bb_predicate (gimple_bb (stmt));
 
-  for (i = 0; drs.iterate (i, &a); i++)
-    if (DR_STMT (a) == stmt
-	&& DR_IS_WRITE (a))
-      {
-	bool found = false;
-	int x = DR_WRITTEN_AT_LEAST_ONCE (a);
+  data_reference_p *master_dr, *base_master_dr;
+  tree ref = DR_REF (a);
+  tree base_ref = DR_BASE_OBJECT (a);
+  tree ca = bb_predicate (gimple_bb (DR_STMT (a)));
+  bool exist1, exist2;
 
-	if (x == 0)
-	  return false;
+  while (TREE_CODE (ref) == COMPONENT_REF
+	 || TREE_CODE (ref) == IMAGPART_EXPR
+	 || TREE_CODE (ref) == REALPART_EXPR)
+    ref = TREE_OPERAND (ref, 0);
 
-	if (x == 1)
-	  continue;
+  master_dr = &ref_DR_map->get_or_insert (ref, &exist1);
 
-	for (j = 0; drs.iterate (j, &b); j++)
-	  if (DR_STMT (b) != stmt
-	      && DR_IS_WRITE (b)
-	      && same_data_refs_base_objects (a, b))
-	    {
-	      tree cb = bb_predicate (gimple_bb (DR_STMT (b)));
+  if (!exist1)
+    {
+      IFC_DR (a)->predicate = ca;
+      *master_dr = a;
+    }
+  else
+    IFC_DR (*master_dr)->predicate
+	= fold_or_predicates
+		(EXPR_LOCATION (IFC_DR (*master_dr)->predicate),
+		 ca, IFC_DR (*master_dr)->predicate);
 
-	      if (DR_WRITTEN_AT_LEAST_ONCE (b) == 1
-		  || is_true_predicate (cb)
-		  || is_true_predicate (ca = fold_or_predicates (EXPR_LOCATION (cb),
-								 ca, cb)))
-		{
-		  DR_WRITTEN_AT_LEAST_ONCE (a) = 1;
-		  DR_WRITTEN_AT_LEAST_ONCE (b) = 1;
-		  found = true;
-		  break;
-		}
-	    }
+  if (is_true_predicate (IFC_DR (*master_dr)->predicate))
+    DR_RW_UNCONDITIONALLY (*master_dr) = 1;
 
-	if (!found)
-	  {
-	    DR_WRITTEN_AT_LEAST_ONCE (a) = 0;
-	    return false;
-	  }
-      }
+  base_master_dr = &baseref_DR_map->get_or_insert (base_ref,&exist2);
 
-  return true;
+  if (!exist2)
+    {
+      IFC_DR (a)->predicate = ca;
+      *base_master_dr = a;
+    }
+  else
+    IFC_DR (*base_master_dr)->predicate
+	= fold_or_predicates
+		(EXPR_LOCATION (IFC_DR (*base_master_dr)->predicate),
+		 ca, IFC_DR (*base_master_dr)->predicate);
+
+  if (DR_IS_WRITE (a)
+      && (is_true_predicate (IFC_DR (*base_master_dr)->predicate)))
+    DR_WRITTEN_AT_LEAST_ONCE (*base_master_dr) = 1;
 }
 
 /* Return true when the memory references of STMT won't trap in the
@@ -731,13 +669,54 @@  write_memrefs_written_at_least_once (gimple *stmt,
    iteration.  To check that the memory accesses are correctly formed
    and that we are allowed to read and write in these locations, we
    check that the memory accesses to be if-converted occur at every
-   iteration unconditionally.  */
-
+   iteration unconditionally.
+
+   Returns true for the memory reference in STMT, same memory reference
+   is read or written unconditionally atleast once and the base memory
+   reference is written unconditionally once.  This is to check reference
+   will not write fault.  Also retuns true if the memory reference is
+   unconditionally read once then we are conditionally writing to memory
+   which is defined as read and write and is bound to the definition
+   we are seeing.  */
 static bool
-ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> refs)
+ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> drs)
 {
-  return write_memrefs_written_at_least_once (stmt, refs)
-    && memrefs_read_or_written_unconditionally (stmt, refs);
+  int i;
+  data_reference_p a, *master_dr, *base_master_dr;
+
+  for (i = gimple_uid (stmt) - 1; drs.iterate (i, &a); i++)
+    {
+      if (DR_STMT (a) != stmt)
+	break;
+
+      tree ref_base_a = DR_REF (a);
+      tree base = DR_BASE_OBJECT (a);
+
+      while (TREE_CODE (ref_base_a) == COMPONENT_REF
+	     || TREE_CODE (ref_base_a) == IMAGPART_EXPR
+	     || TREE_CODE (ref_base_a) == REALPART_EXPR)
+	ref_base_a = TREE_OPERAND (ref_base_a, 0);
+
+      master_dr = ref_DR_map->get (ref_base_a);
+      base_master_dr = baseref_DR_map->get (base);
+
+      gcc_assert (master_dr != NULL && base_master_dr != NULL);
+
+      if (DR_RW_UNCONDITIONALLY (*master_dr) == 1)
+	{
+	  if (DR_WRITTEN_AT_LEAST_ONCE (*base_master_dr) == 1)
+	    return true;
+	  else
+	    {
+	      tree base_tree = get_base_address (DR_REF (a));
+	      if (DECL_P (base_tree)
+		  && decl_binds_to_current_def_p (base_tree)
+		  && !TREE_READONLY (base_tree))
+		return true;
+	    }
+	}
+    }
+  return false;
 }
 
 /* Wrapper around gimple_could_trap_p refined for the needs of the
@@ -1280,6 +1259,7 @@  if_convertible_loop_p_1 (struct loop *loop,
 	  case GIMPLE_CALL:
 	  case GIMPLE_DEBUG:
 	  case GIMPLE_COND:
+	    gimple_set_uid (gsi_stmt (gsi), 0);
 	    break;
 	  default:
 	    return false;
@@ -1288,13 +1268,20 @@  if_convertible_loop_p_1 (struct loop *loop,
 
   data_reference_p dr;
 
+  ref_DR_map = new hash_map<tree_operand_hash, data_reference_p>;
+  baseref_DR_map = new hash_map<tree_operand_hash, data_reference_p>;
+
+  predicate_bbs (loop);
+
   for (i = 0; refs->iterate (i, &dr); i++)
     {
       dr->aux = XNEW (struct ifc_dr);
       DR_WRITTEN_AT_LEAST_ONCE (dr) = -1;
       DR_RW_UNCONDITIONALLY (dr) = -1;
+      if (gimple_uid (DR_STMT (dr)) == 0)
+	gimple_set_uid (DR_STMT (dr), i + 1);
+      hash_memrefs_baserefs_and_store_DRs_read_written_info (dr);
     }
-  predicate_bbs (loop);
 
   for (i = 0; i < loop->num_nodes; i++)
     {
@@ -1391,6 +1378,13 @@  if_convertible_loop_p (struct loop *loop, bool *any_mask_load_store)
 
   free_data_refs (refs);
   free_dependence_relations (ddrs);
+
+  delete ref_DR_map;
+  ref_DR_map = NULL;
+
+  delete baseref_DR_map;
+  baseref_DR_map = NULL;
+
   return res;
 }