Re: [PATCH] Make IPA-CP propagate alignment information of pointers

2014-12-05 Thread Jay Foad
On 3 December 2014 at 14:36, Martin Jambor mjam...@suse.cz wrote:
 On Wed, Dec 03, 2014 at 10:53:54AM +, Jay Foad wrote:
  Index: src/gcc/ipa-prop.h
  ===
  --- src.orig/gcc/ipa-prop.h
  +++ src/gcc/ipa-prop.h
  @@ -144,6 +144,17 @@ struct GTY(()) ipa_agg_jump_function
 
   typedef struct ipa_agg_jump_function *ipa_agg_jump_function_p;
 
  +/* Info about poiner alignments. */

 pointer

  +struct GTY(()) ipa_alignment
  +{
  +  /* The data fields below are valid only if known is true.  */
  +  bool known;

 Just curious: why is the known flag necessary? The comments for
 ptr_info_def say that align=0 means unknown.

 It is necessary.  In IPA-CP, when know is false, this means the
 lattice is in TOP state (i.e. once we learn something about the
 parameter, let's overwrite this), whereas when it is true and
 alignment is 0, it means it is in BOTTOM state (i.e. we know we cannot
 rely on this and never will be able to).

Can't you use align=1, misalign=0 for TOP ? This means that we don't
know anything useful about the pointer yet, just that it's a multiple
of 1 (which is trivially true for all pointers, isn't it?).

When you have vectors of these struct they will pack MUCH more nicely
without the bool known field.

Thanks,
Jay.


Re: [PATCH] Make IPA-CP propagate alignment information of pointers

2014-12-03 Thread Jay Foad
 Index: src/gcc/ipa-cp.c
 ===
 --- src.orig/gcc/ipa-cp.c
 +++ src/gcc/ipa-cp.c
 @@ -262,6 +262,9 @@ public:
ipcp_latticeipa_polymorphic_call_context ctxlat;
/* Lattices describing aggregate parts.  */
ipcp_agg_lattice *aggs;
 +  /* Alignment information.  Very basic one value lattice where !known means
 + TOP and zero alignment bottom.  */
 +  ipa_alignment alignment;
/* Number of aggregate lattices */
int aggs_count;
/* True if aggregate data were passed by reference (as opposed to by
 @@ -444,6 +447,13 @@ print_all_lattices (FILE * f, bool dump_
   plats-itself.print (f, dump_sources, dump_benefits);
   fprintf (f,  ctxs: );
   plats-ctxlat.print (f, dump_sources, dump_benefits);
 + if (plats-alignment.known  plats-alignment.align  0)
 +   fprintf (f,  Alignment %u, misaglignment %u\n,

misalignment

 +plats-alignment.align, plats-alignment.misalign);
 + else if (plats-alignment.known)
 +   fprintf (f,  Alignment unusable\n);
 + else
 +   fprintf (f,  Alignment unknown\n);
   if (plats-virt_call)
 fprintf (f, virt_call flag set\n);

 @@ -761,6 +771,27 @@ set_agg_lats_contain_variable (struct ip
return ret;
  }

 +/* Return true if alignemnt informatin in PLATS is known to be unusable.  */

alignment, information

 +
 +static inline bool
 +alignment_bottom_p (ipcp_param_lattices *plats)
 +{
 +  return plats-alignment.known  (plats-alignment.align == 0);
 +}
 +
 +/* Set alignment information in PLATS to unusable.  Return true if it
 +   previously was usable or unknown.  */
 +
 +static inline bool
 +set_alignment_to_bottom (ipcp_param_lattices *plats)
 +{
 +  if (alignment_bottom_p (plats))
 +return false;
 +  plats-alignment.known = true;
 +  plats-alignment.align = 0;
 +  return true;
 +}
 +
  /* Mark bot aggregate and scalar lattices as containing an unknown variable,
 return true is any of them has not been marked as such so far.  */

 @@ -771,6 +802,7 @@ set_all_contains_variable (struct ipcp_p
ret = plats-itself.set_contains_variable ();
ret |= plats-ctxlat.set_contains_variable ();
ret |= set_agg_lats_contain_variable (plats);
 +  ret |= set_alignment_to_bottom (plats);
return ret;
  }

 @@ -807,6 +839,7 @@ initialize_node_lattices (struct cgraph_
   plats-itself.set_to_bottom ();
   plats-ctxlat.set_to_bottom ();
   set_agg_lats_to_bottom (plats);
 + set_alignment_to_bottom (plats);
 }
   else
 set_all_contains_variable (plats);
 @@ -1369,6 +1402,77 @@ propagate_context_accross_jump_function
return ret;
  }

 +/* Propagate alignments accross jump function JFUNC that is associated with

across

 +   edge CS and update DEST_LAT accordingly.  */
 +
 +static bool
 +propagate_alignment_accross_jump_function (struct cgraph_edge *cs,
 +  struct ipa_jump_func *jfunc,
 +  struct ipcp_param_lattices 
 *dest_lat)
 +{
 +  if (alignment_bottom_p (dest_lat))
 +return false;
 +
 +  ipa_alignment cur;
 +  cur.known = false;
 +  if (jfunc-alignment.known)
 +cur = jfunc-alignment;
 +  else if (jfunc-type == IPA_JF_PASS_THROUGH
 +  || jfunc-type == IPA_JF_ANCESTOR)
 +{
 +  struct ipa_node_params *caller_info = IPA_NODE_REF (cs-caller);
 +  struct ipcp_param_lattices *src_lats;
 +  HOST_WIDE_INT offset = 0;
 +  int src_idx;
 +
 +  if (jfunc-type == IPA_JF_PASS_THROUGH)
 +   {
 + enum tree_code op = ipa_get_jf_pass_through_operation (jfunc);
 + if (op != NOP_EXPR)
 +   {
 + if (op != POINTER_PLUS_EXPR
 +  op != PLUS_EXPR
 +  op != MINUS_EXPR)
 +   goto prop_fail;
 + tree operand = ipa_get_jf_pass_through_operand (jfunc);
 + if (!tree_fits_shwi_p (operand))
 +   goto prop_fail;
 + offset = tree_to_shwi (operand);
 +   }
 + src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
 +   }
 +  else
 +   {
 + src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
 + offset = ipa_get_jf_ancestor_offset (jfunc);
 +   }
 +
 +  src_lats = ipa_get_parm_lattices (caller_info, src_idx);
 +  if (!src_lats-alignment.known
 + || alignment_bottom_p (src_lats))
 +   goto prop_fail;
 +
 +  cur = src_lats-alignment;
 +  cur.misalign = (cur.misalign + offset) % cur.align;
 +}
 +
 +  if (cur.known)
 +{
 +  if (!dest_lat-alignment.known)
 +   {
 + dest_lat-alignment = cur;
 + return true;
 +   }
 +  else if (dest_lat-alignment.align == cur.align
 +   dest_lat-alignment.misalign == cur.misalign)
 +   return false;
 +}
 +
 

Re: [PATCH] Make IPA-CP propagate alignment information of pointers

2014-12-03 Thread Martin Jambor
Hi,

thank you very much for pointing out all the spelling mistakes.  I
suppose you could tell I was writing this in a hurry :-)  Nevertheless
I should probably make a habit of spell checking stuff before
sending it out.

As far as  your question is concerned:

On Wed, Dec 03, 2014 at 10:53:54AM +, Jay Foad wrote:
  Index: src/gcc/ipa-prop.h
  ===
  --- src.orig/gcc/ipa-prop.h
  +++ src/gcc/ipa-prop.h
  @@ -144,6 +144,17 @@ struct GTY(()) ipa_agg_jump_function
 
   typedef struct ipa_agg_jump_function *ipa_agg_jump_function_p;
 
  +/* Info about poiner alignments. */
 
 pointer
 
  +struct GTY(()) ipa_alignment
  +{
  +  /* The data fields below are valid only if known is true.  */
  +  bool known;
 
 Just curious: why is the known flag necessary? The comments for
 ptr_info_def say that align=0 means unknown.

It is necessary.  In IPA-CP, when know is false, this means the
lattice is in TOP state (i.e. once we learn something about the
parameter, let's overwrite this), whereas when it is true and
alignment is 0, it means it is in BOTTOM state (i.e. we know we cannot
rely on this and never will be able to).

Thanks,

Martin



Re: [PATCH] Make IPA-CP propagate alignment information of pointers

2014-12-02 Thread Martin Jambor
Hi,

thanks for the comments.

On Mon, Dec 01, 2014 at 11:40:59PM +0100, Jan Hubicka wrote:
   2014-11-19  Martin Jambor  mjam...@suse.cz
   
 * ipa-prop.h (ipa_alignment): New type.
 (ipa_jump_func): New field alignment.
 (ipcp_transformation_summary) New type.
 (ipcp_grow_transformations_if_necessary): Declare.
 (ipa_node_agg_replacements): Removed.
 (ipcp_transformations): Declare.
 (ipcp_get_transformation_summary): New function.
 (ipa_get_agg_replacements_for_node): Use it.
 * ipa-cp.c (ipcp_param_lattices): New field alignment.
 (print_all_lattices): Also print alignment.
 (alignment_bottom_p): New function.
 (set_alignment_to_bottom): Likewise.
 (set_all_contains_variable): Also set alignment to bottom.
 (initialize_node_lattices): Likewise.
 (propagate_alignment_accross_jump_function): New function.
 (propagate_constants_accross_call): Call it.
 (ipcp_store_alignment_results): New function.
 (ipcp_driver): Call it.
 * ipa-prop.c (ipa_node_agg_replacements): Removed.
 (ipcp_transformations): New.
 (ipa_print_node_jump_functions_for_edge): Also print alignment.
 (ipa_set_jf_unknown): New function.
 (detect_type_change_from_memory_writes): Use ipa_set_jf_unknown.
 (ipa_compute_jump_functions_for_edge): Also calculate alignment.
 (update_jump_functions_after_inlining): Use ipa_set_jf_unknown.
 (ipcp_grow_transformations_if_necessary): New function.
 (ipa_set_node_agg_value_chain): Use ipcp_transformations.
 (ipa_node_removal_hook): Likewise.
 (ipa_node_duplication_hook): Also duplicate alignment results.
 (ipa_write_jump_function): Also stream alignments.
 (ipa_read_jump_function): Use ipa_set_jf_unknown, also stream
 alignments.
 (write_agg_replacement_chain): Renamed to
 write_ipcp_transformation_info, also stream alignments.
 (read_agg_replacement_chain): Renamed to
 read_ipcp_transformation_info, also stream alignments.
 (ipa_prop_write_all_agg_replacement): Renamed to
 ipcp_write_transformation_summaries. Stream always.
 (ipa_prop_read_all_agg_replacement): Renamed to
 ipcp_read_transformation_summaries.
 (ipcp_update_alignments): New function.
 (ipcp_transform_function): Call it, free also alignments.
 
 In longer term I think we should just propagate value range and known to be 
 zero/nonzero
 bits.  This is stronger and more universal than inventing propagation for 
 subproblems
 (like non-NULL would be useful).
 I think it would be also good excuse to do (simplified) early VRP to populate 
 the vlaue
 ranges locally.  This seems to make quite some difference on C++.

Well, it would essentially need some sort of early VRP.  So yes,
hopefully in the next major version we can do that.

 
 But for 5.0 it seems like resonable thing to do.
 
 Since ipa-prop itself is built as propaation engine for multiple types of 
 values
 (scalars, aggregates, contexts and now value ranges).

I believe that if we start propagating value ranges, this would make
propagating scalars redundant?  Also it would need some rethinking of
the ipa-cp propagation heuristics.

 I wonder if the code can not be
 organized by type of propagated value and perhaps split into multiple file to 
 make
 it more readable.

Splitting off of some part to extra files might help but first it is
necessary to figure out how to reorganize the contents of the file in
general.  Jump functions should probably be re-thought a little bit,
especially once we add information like reference mapping from my
aggregate propagation patches.

It would also be beneficial to do some analysis together with
generating the inline summaries and tweak ipa-analysis summary
conditions so that they can tell which value ranges would lead to the
same results.  And so on and so forth.

 
 I think the way we split polymorphic-call-context lattice operations into 
 separate
 file quite works but more of code separation would be nice.
 
 Well, a bit like df.c infrastructure is done.
   +  else if (jfunc-type == IPA_JF_PASS_THROUGH
   +|| jfunc-type == IPA_JF_ANCESTOR)
   +{
   +  struct ipa_node_params *caller_info = IPA_NODE_REF (cs-caller);
   +  struct ipcp_param_lattices *src_lats;
   +  HOST_WIDE_INT offset = 0;
   +  int src_idx;
   +
 
 We probably chould avoid new places that rely on tree_fits_shwi_p and use 
 wide_int
 instead.

On IRC we agreed that this making change here alone is of very limited
benefit, unlike using wide_int more in IPA data structures overall,
something which should be done in 6.0.

   +  if (POINTER_TYPE_P (TREE_TYPE(arg)))
   + {
   +   unsigned HOST_WIDE_INT hwi_bitpos;
   +   unsigned align;
   +
   +   if (get_pointer_alignment_1 (arg, align, hwi_bitpos)
   +align  BITS_PER_UNIT)
 
 OK, so here we get the nonzero/zero bits propagation from CCP used, right?
 
   +  ipcp_transformation_summary *ts = ipcp_get_transformation_summary 
   

Re: [PATCH] Make IPA-CP propagate alignment information of pointers

2014-12-01 Thread Martin Jambor
Ping (this is a new feature submitted in stage1 so I'd really
appreciate a review before it is going to be deemed too late).

Thanks,

Martin


On Wed, Nov 19, 2014 at 12:32:53AM +0100, Martin Jambor wrote:
 Hi,
 

...

 
 2014-11-19  Martin Jambor  mjam...@suse.cz
 
   * ipa-prop.h (ipa_alignment): New type.
   (ipa_jump_func): New field alignment.
   (ipcp_transformation_summary) New type.
   (ipcp_grow_transformations_if_necessary): Declare.
   (ipa_node_agg_replacements): Removed.
   (ipcp_transformations): Declare.
   (ipcp_get_transformation_summary): New function.
   (ipa_get_agg_replacements_for_node): Use it.
   * ipa-cp.c (ipcp_param_lattices): New field alignment.
   (print_all_lattices): Also print alignment.
   (alignment_bottom_p): New function.
   (set_alignment_to_bottom): Likewise.
   (set_all_contains_variable): Also set alignment to bottom.
   (initialize_node_lattices): Likewise.
   (propagate_alignment_accross_jump_function): New function.
   (propagate_constants_accross_call): Call it.
   (ipcp_store_alignment_results): New function.
   (ipcp_driver): Call it.
   * ipa-prop.c (ipa_node_agg_replacements): Removed.
   (ipcp_transformations): New.
   (ipa_print_node_jump_functions_for_edge): Also print alignment.
   (ipa_set_jf_unknown): New function.
   (detect_type_change_from_memory_writes): Use ipa_set_jf_unknown.
   (ipa_compute_jump_functions_for_edge): Also calculate alignment.
   (update_jump_functions_after_inlining): Use ipa_set_jf_unknown.
   (ipcp_grow_transformations_if_necessary): New function.
   (ipa_set_node_agg_value_chain): Use ipcp_transformations.
   (ipa_node_removal_hook): Likewise.
   (ipa_node_duplication_hook): Also duplicate alignment results.
   (ipa_write_jump_function): Also stream alignments.
   (ipa_read_jump_function): Use ipa_set_jf_unknown, also stream
   alignments.
   (write_agg_replacement_chain): Renamed to
   write_ipcp_transformation_info, also stream alignments.
   (read_agg_replacement_chain): Renamed to
   read_ipcp_transformation_info, also stream alignments.
   (ipa_prop_write_all_agg_replacement): Renamed to
   ipcp_write_transformation_summaries. Stream always.
   (ipa_prop_read_all_agg_replacement): Renamed to
   ipcp_read_transformation_summaries.
   (ipcp_update_alignments): New function.
   (ipcp_transform_function): Call it, free also alignments.
 
 testsuite/
   * gcc.dg/ipa/propalign-1.c: New test.
   * gcc.dg/ipa/propalign-2.c: Likewise.
 
 Index: src/gcc/ipa-cp.c
 ===
 --- src.orig/gcc/ipa-cp.c 2014-11-18 22:53:01.886689227 +0100
 +++ src/gcc/ipa-cp.c  2014-11-19 00:15:08.890876993 +0100
 @@ -262,6 +262,9 @@ public:
ipcp_latticeipa_polymorphic_call_context ctxlat;
/* Lattices describing aggregate parts.  */
ipcp_agg_lattice *aggs;
 +  /* Alignment information.  Very basic one value lattice where !known means
 + TOP and zero alignment bottom.  */
 +  ipa_alignment alignment;
/* Number of aggregate lattices */
int aggs_count;
/* True if aggregate data were passed by reference (as opposed to by
 @@ -444,6 +447,13 @@ print_all_lattices (FILE * f, bool dump_
 plats-itself.print (f, dump_sources, dump_benefits);
 fprintf (f,  ctxs: );
 plats-ctxlat.print (f, dump_sources, dump_benefits);
 +   if (plats-alignment.known  plats-alignment.align  0)
 + fprintf (f,  Alignment %u, misaglignment %u\n,
 +  plats-alignment.align, plats-alignment.misalign);
 +   else if (plats-alignment.known)
 + fprintf (f,  Alignment unusable\n);
 +   else
 + fprintf (f,  Alignment unknown\n);
 if (plats-virt_call)
   fprintf (f, virt_call flag set\n);
  
 @@ -761,6 +771,27 @@ set_agg_lats_contain_variable (struct ip
return ret;
  }
  
 +/* Return true if alignemnt informatin in PLATS is known to be unusable.  */
 +
 +static inline bool
 +alignment_bottom_p (ipcp_param_lattices *plats)
 +{
 +  return plats-alignment.known  (plats-alignment.align == 0);
 +}
 +
 +/* Set alignment information in PLATS to unusable.  Return true if it
 +   previously was usable or unknown.  */
 +
 +static inline bool
 +set_alignment_to_bottom (ipcp_param_lattices *plats)
 +{
 +  if (alignment_bottom_p (plats))
 +return false;
 +  plats-alignment.known = true;
 +  plats-alignment.align = 0;
 +  return true;
 +}
 +
  /* Mark bot aggregate and scalar lattices as containing an unknown variable,
 return true is any of them has not been marked as such so far.  */
  
 @@ -771,6 +802,7 @@ set_all_contains_variable (struct ipcp_p
ret = plats-itself.set_contains_variable ();
ret |= plats-ctxlat.set_contains_variable ();
ret |= set_agg_lats_contain_variable (plats);
 +  ret 

Re: [PATCH] Make IPA-CP propagate alignment information of pointers

2014-12-01 Thread Jan Hubicka
  2014-11-19  Martin Jambor  mjam...@suse.cz
  
  * ipa-prop.h (ipa_alignment): New type.
  (ipa_jump_func): New field alignment.
  (ipcp_transformation_summary) New type.
  (ipcp_grow_transformations_if_necessary): Declare.
  (ipa_node_agg_replacements): Removed.
  (ipcp_transformations): Declare.
  (ipcp_get_transformation_summary): New function.
  (ipa_get_agg_replacements_for_node): Use it.
  * ipa-cp.c (ipcp_param_lattices): New field alignment.
  (print_all_lattices): Also print alignment.
  (alignment_bottom_p): New function.
  (set_alignment_to_bottom): Likewise.
  (set_all_contains_variable): Also set alignment to bottom.
  (initialize_node_lattices): Likewise.
  (propagate_alignment_accross_jump_function): New function.
  (propagate_constants_accross_call): Call it.
  (ipcp_store_alignment_results): New function.
  (ipcp_driver): Call it.
  * ipa-prop.c (ipa_node_agg_replacements): Removed.
  (ipcp_transformations): New.
  (ipa_print_node_jump_functions_for_edge): Also print alignment.
  (ipa_set_jf_unknown): New function.
  (detect_type_change_from_memory_writes): Use ipa_set_jf_unknown.
  (ipa_compute_jump_functions_for_edge): Also calculate alignment.
  (update_jump_functions_after_inlining): Use ipa_set_jf_unknown.
  (ipcp_grow_transformations_if_necessary): New function.
  (ipa_set_node_agg_value_chain): Use ipcp_transformations.
  (ipa_node_removal_hook): Likewise.
  (ipa_node_duplication_hook): Also duplicate alignment results.
  (ipa_write_jump_function): Also stream alignments.
  (ipa_read_jump_function): Use ipa_set_jf_unknown, also stream
  alignments.
  (write_agg_replacement_chain): Renamed to
  write_ipcp_transformation_info, also stream alignments.
  (read_agg_replacement_chain): Renamed to
  read_ipcp_transformation_info, also stream alignments.
  (ipa_prop_write_all_agg_replacement): Renamed to
  ipcp_write_transformation_summaries. Stream always.
  (ipa_prop_read_all_agg_replacement): Renamed to
  ipcp_read_transformation_summaries.
  (ipcp_update_alignments): New function.
  (ipcp_transform_function): Call it, free also alignments.

In longer term I think we should just propagate value range and known to be 
zero/nonzero
bits.  This is stronger and more universal than inventing propagation for 
subproblems
(like non-NULL would be useful).
I think it would be also good excuse to do (simplified) early VRP to populate 
the vlaue
ranges locally.  This seems to make quite some difference on C++.

But for 5.0 it seems like resonable thing to do.

Since ipa-prop itself is built as propaation engine for multiple types of values
(scalars, aggregates, contexts and now value ranges). I wonder if the code can 
not be
organized by type of propagated value and perhaps split into multiple file to 
make
it more readable.

I think the way we split polymorphic-call-context lattice operations into 
separate
file quite works but more of code separation would be nice.

Well, a bit like df.c infrastructure is done.
  +  else if (jfunc-type == IPA_JF_PASS_THROUGH
  +  || jfunc-type == IPA_JF_ANCESTOR)
  +{
  +  struct ipa_node_params *caller_info = IPA_NODE_REF (cs-caller);
  +  struct ipcp_param_lattices *src_lats;
  +  HOST_WIDE_INT offset = 0;
  +  int src_idx;
  +

We probably chould avoid new places that rely on tree_fits_shwi_p and use 
wide_int
instead.
  +  if (POINTER_TYPE_P (TREE_TYPE(arg)))
  +   {
  + unsigned HOST_WIDE_INT hwi_bitpos;
  + unsigned align;
  +
  + if (get_pointer_alignment_1 (arg, align, hwi_bitpos)
  +  align  BITS_PER_UNIT)

OK, so here we get the nonzero/zero bits propagation from CCP used, right?

  +  ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
  +  if (ts  vec_safe_length (ts-alignments)  0)
  +{
  +  count = ts-alignments-length ();
  +
  +  streamer_write_uhwi (ob, count);
  +  for (unsigned i = 0; i  count; ++i)
  +   {
  + ipa_alignment *parm_al = (*ts-alignments)[i];
  +
  + struct bitpack_d bp;
  + bp = bitpack_create (ob-main_stream);
  + bp_pack_value (bp, parm_al-known, 1);
  + streamer_write_bitpack (bp);
  + if (parm_al-known)
  +   {
  + streamer_write_uhwi (ob, parm_al-align);
  + streamer_write_uhwi (ob, parm_al-misalign);

What about using streamer_write_hwi_in_range for misalign (as it is in range 
0...align)
to get tiny bit of extra sanity check  code size saving?
We probably also get sane range for -align. 

Honza


Re: [PATCH] Make IPA-CP propagate alignment information of pointers

2014-11-18 Thread Martin Jambor
Hi,

On Mon, Nov 17, 2014 at 01:05:23PM +0100, Richard Biener wrote:
 On Sat, Nov 15, 2014 at 2:04 AM, Martin Jambor mjam...@suse.cz wrote:
  Hi,
 
  this patch adds very simple propagation of alignment of pointers to
  IPA-CP.  Because I have not attempted to estimate profitability of
  such propagation in any way, it does not do any cloning, just
  propagation when the alignment is known and the same in all contexts.
 
  I have seen this shrinking code in a few vectorization testcases in
  our testsuite, especially if run with LTO.
 
  The patch is slightly bigger because the streaming of transformation
  summaries had to be modified (and many parts renamed) a little bit to
  also hold the resultant alignment information.
 
  In the future we may replace this by a more fancy VRP-based IPA-CP but
  I think it is worth having this simple addition in 5.0.  Bootstrapped
  and tested on x86_64-linux.  OK for trunk?
 

Apart from changes suggested by Richi (more on that below), I have
renamed the field bitpos of ipa_alignment to misalign, which is how it
is called in ptr_info_def in tree-ssanames.h, because it is really the
offset in bytes, not bits.

  Index: src/gcc/ipa-cp.c
  ===
  --- src.orig/gcc/ipa-cp.c   2014-11-14 22:06:06.240031030 +0100
  +++ src/gcc/ipa-cp.c2014-11-15 01:40:38.260521577 +0100
  @@ -1372,6 +1405,80 @@ propagate_context_accross_jump_function
 return ret;
   }
 
  +/* Propagate alignments accross jump function JFUNC that is associated with
  +   edge CS and update DEST_LAT accordingly.  */
  +
  +static bool
  +propagate_alignment_accross_jump_function (struct cgraph_edge *cs,
  +  struct ipa_jump_func *jfunc,
  +  struct ipcp_param_lattices 
  *dest_lat)
  +{
  +  if (alignment_bottom_p (dest_lat))
  +return false;
  +
  +  ipa_alignment cur;
  +  cur.known = false;
  +  if (jfunc-alignment.known)
  +cur = jfunc-alignment;
  +  else if (jfunc-type == IPA_JF_PASS_THROUGH
  +  || jfunc-type == IPA_JF_ANCESTOR)
  +{
  +  struct ipa_node_params *caller_info = IPA_NODE_REF (cs-caller);
  +  struct ipcp_param_lattices *src_lats;
  +  HOST_WIDE_INT offset = 0;
  +  int src_idx;
  +
  +  if (jfunc-type == IPA_JF_PASS_THROUGH)
  +   {
  + enum tree_code op = ipa_get_jf_pass_through_operation (jfunc);
  + if (op != NOP_EXPR)
  +   {
  + if (op != POINTER_PLUS_EXPR
  +  op != PLUS_EXPR
  +  op != MINUS_EXPR)
  +   goto prop_fail;
  + tree operand = ipa_get_jf_pass_through_operand (jfunc);
  + if (!tree_fits_shwi_p (operand))
  +   goto prop_fail;
  + offset = tree_to_shwi (operand);
  +   }
  + src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
  +   }
  +  else
  +   {
  + src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
  + offset = ipa_get_jf_ancestor_offset (jfunc);
  +   }
  +
  +  src_lats = ipa_get_parm_lattices (caller_info, src_idx);
  +  if (!src_lats-alignment.known
  + || alignment_bottom_p (src_lats))
  +   goto prop_fail;
  +
  +  cur = src_lats-alignment;
  +
  +  if (offset != 0
  +  (offset % cur.align != 0))
  +   goto prop_fail;
 
 why fail?  shouldn't you simply add offset to cur.bitpos?
 

Right, I have changed this whole condition to simple

  cur.misalign = (cur.misalign + offset) % cur.align;

  +}
  +
  +  if (cur.known)
  +{
  +  if (!dest_lat-alignment.known)
  +   {
  + dest_lat-alignment = cur;
  + return true;
  +   }
  +  else if (dest_lat-alignment.align == cur.align
  +   dest_lat-alignment.bitpos == cur.bitpos)
  +   return false;
  +}
  +
  + prop_fail:
  +  set_alignment_to_bottom (dest_lat);
  +  return true;
  +}
  +
   /* If DEST_PLATS already has aggregate items, check that aggs_by_ref 
  matches
  NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true 
  (in all
  other cases, return false).  If there are no aggregate items, set
  Index: src/gcc/ipa-prop.c
  ===
  --- src.orig/gcc/ipa-prop.c 2014-11-14 22:06:06.240031030 +0100
  +++ src/gcc/ipa-prop.c  2014-11-15 01:40:05.564520331 +0100
  @@ -1716,6 +1734,24 @@ ipa_compute_jump_functions_for_edge (str
  useful_context = true;
  }
 
  +  if (POINTER_TYPE_P (TREE_TYPE(arg)))
  +   {
  + unsigned HOST_WIDE_INT hwi_bitpos;
  + unsigned align;
  +
  + if (get_pointer_alignment_1 (arg, align, hwi_bitpos)
  +  (hwi_bitpos / BITS_PER_UNIT)  UINT_MAX)
 
 hwi_bitpos is never = align.  A better thing to check here is
 align  BITS_PER_UNIT.  It's not useful to propagate unaligned, no?

OK.


Re: [PATCH] Make IPA-CP propagate alignment information of pointers

2014-11-17 Thread Richard Biener
On Sat, Nov 15, 2014 at 2:04 AM, Martin Jambor mjam...@suse.cz wrote:
 Hi,

 this patch adds very simple propagation of alignment of pointers to
 IPA-CP.  Because I have not attempted to estimate profitability of
 such propagation in any way, it does not do any cloning, just
 propagation when the alignment is known and the same in all contexts.

 I have seen this shrinking code in a few vectorization testcases in
 our testsuite, especially if run with LTO.

 The patch is slightly bigger because the streaming of transformation
 summaries had to be modified (and many parts renamed) a little bit to
 also hold the resultant alignment information.

 In the future we may replace this by a more fancy VRP-based IPA-CP but
 I think it is worth having this simple addition in 5.0.  Bootstrapped
 and tested on x86_64-linux.  OK for trunk?

 Thanks,

 Martin


 2014-11-15  Martin Jambor  mjam...@suse.cz

 * ipa-prop.h (ipa_alignment): New type.
 (ipa_jump_func): New field alignment.
 (ipcp_transformation_summary) New type.
 (ipcp_grow_transformations_if_necessary): Declare.
 (ipa_node_agg_replacements): Removed.
 (ipcp_transformations): Declare.
 (ipcp_get_transformation_summary): New function.
 (ipa_get_agg_replacements_for_node): Use it.
 * ipa-cp.c (ipcp_param_lattices): New field alignment.
 (print_all_lattices): Also print alignment.
 (alignment_bottom_p): New function.
 (set_alignment_to_bottom): Likewise.
 (set_all_contains_variable): Also set alignment to bottom.
 (initialize_node_lattices): Likewise.
 (propagate_alignment_accross_jump_function): New function.
 (propagate_constants_accross_call): Call it.
 (ipcp_store_alignment_results): New function.
 (ipcp_driver): Call it.
 * ipa-prop.c (ipa_node_agg_replacements): Removed.
 (ipcp_transformations): New.
 (ipa_print_node_jump_functions_for_edge): Also print alignment.
 (ipa_set_jf_unknown): New function.
 (detect_type_change_from_memory_writes): Use ipa_set_jf_unknown.
 (ipa_compute_jump_functions_for_edge): Also calculate alignment.
 (update_jump_functions_after_inlining): Use ipa_set_jf_unknown.
 (ipcp_grow_transformations_if_necessary): New function.
 (ipa_set_node_agg_value_chain): Use ipcp_transformations.
 (ipa_node_removal_hook): Likewise.
 (ipa_node_duplication_hook): Also duplicate alignment results.
 (ipa_write_jump_function): Also stream alignments.
 (ipa_read_jump_function): Use ipa_set_jf_unknown, also stream
 alignments.
 (write_agg_replacement_chain): Renamed to
 write_ipcp_transformation_info, also stream alignments.
 (read_agg_replacement_chain): Renamed to
 read_ipcp_transformation_info, also stream alignments.
 (ipa_prop_write_all_agg_replacement): Renamed to
 ipcp_write_transformation_summaries. Stream always.
 (ipa_prop_read_all_agg_replacement): Renamed to
 ipcp_read_transformation_summaries.
 (ipcp_update_alignments): New function.
 (ipcp_transform_function): Call it, free also alignments.

 testsuite/
 * gcc.dg/ipa/propalign-1.c: New test.
 * gcc.dg/ipa/propalign-2.c: Likewise.

 Index: src/gcc/ipa-cp.c
 ===
 --- src.orig/gcc/ipa-cp.c   2014-11-14 22:06:06.240031030 +0100
 +++ src/gcc/ipa-cp.c2014-11-15 01:40:38.260521577 +0100
 @@ -262,6 +262,9 @@ public:
ipcp_latticeipa_polymorphic_call_context ctxlat;
/* Lattices describing aggregate parts.  */
ipcp_agg_lattice *aggs;
 +  /* Alignment information.  Very basic one value lattice where !known means
 + TOP and zero alignment bottom.  */
 +  ipa_alignment alignment;
/* Number of aggregate lattices */
int aggs_count;
/* True if aggregate data were passed by reference (as opposed to by
 @@ -444,6 +447,13 @@ print_all_lattices (FILE * f, bool dump_
   plats-itself.print (f, dump_sources, dump_benefits);
   fprintf (f,  ctxs: );
   plats-ctxlat.print (f, dump_sources, dump_benefits);
 + if (plats-alignment.known  plats-alignment.align  0)
 +   fprintf (f,  Alignment %u, misaglignment %u\n,
 +plats-alignment.align, plats-alignment.bitpos);
 + else if (plats-alignment.known)
 +   fprintf (f,  Alignment unusable\n);
 + else
 +   fprintf (f,  Alignment unknown\n);
   if (plats-virt_call)
 fprintf (f, virt_call flag set\n);

 @@ -761,6 +771,27 @@ set_agg_lats_contain_variable (struct ip
return ret;
  }

 +/* Return true if alignemnt informatin in PLATS is known to be unusable.  */
 +
 +static inline bool
 +alignment_bottom_p (ipcp_param_lattices *plats)
 +{
 +  return plats-alignment.known  

Re: [PATCH] Make IPA-CP propagate alignment information of pointers

2014-11-16 Thread Toon Moene

On 11/15/2014 02:04 AM, Martin Jambor wrote:


Hi,

this patch adds very simple propagation of alignment of pointers to
IPA-CP.  Because I have not attempted to estimate profitability of
such propagation in any way, it does not do any cloning, just
propagation when the alignment is known and the same in all contexts.


Thanks for this improvement !

From the Fortran side, arrays can be created in the following ways:

1. Statically in the main program.

2. As a subroutine-temporary automatic array.

3. By allocating an allocatable array.

Arrays under 1. are aligned properly by the compiler.

Arrays under 2. are aligned properly because of the proper alignment of 
the stack nowadays.


Arrays under 3. are aligned properly because Fortran ALLOCATE 
ultimately calls malloc.


So Fortran arrays are always suitably aligned (the exception being an 
array actual argument passed as CALL SUB(.., A(2:), ..), which is 
extremely rare).


So this propagation of alignment information will result in basically 
removing all alignment peeling for Fortran code.


Thanks !

--
Toon Moene - e-mail: t...@moene.org - phone: +31 346 214290
Saturnushof 14, 3738 XG  Maartensdijk, The Netherlands
At home: http://moene.org/~toon/; weather: http://moene.org/~hirlam/
Progress of GNU Fortran: http://gcc.gnu.org/wiki/GFortran#news


[PATCH] Make IPA-CP propagate alignment information of pointers

2014-11-14 Thread Martin Jambor
Hi,

this patch adds very simple propagation of alignment of pointers to
IPA-CP.  Because I have not attempted to estimate profitability of
such propagation in any way, it does not do any cloning, just
propagation when the alignment is known and the same in all contexts.

I have seen this shrinking code in a few vectorization testcases in
our testsuite, especially if run with LTO.

The patch is slightly bigger because the streaming of transformation
summaries had to be modified (and many parts renamed) a little bit to
also hold the resultant alignment information.  

In the future we may replace this by a more fancy VRP-based IPA-CP but
I think it is worth having this simple addition in 5.0.  Bootstrapped
and tested on x86_64-linux.  OK for trunk?

Thanks,

Martin


2014-11-15  Martin Jambor  mjam...@suse.cz

* ipa-prop.h (ipa_alignment): New type.
(ipa_jump_func): New field alignment.
(ipcp_transformation_summary) New type.
(ipcp_grow_transformations_if_necessary): Declare.
(ipa_node_agg_replacements): Removed.
(ipcp_transformations): Declare.
(ipcp_get_transformation_summary): New function.
(ipa_get_agg_replacements_for_node): Use it.
* ipa-cp.c (ipcp_param_lattices): New field alignment.
(print_all_lattices): Also print alignment.
(alignment_bottom_p): New function.
(set_alignment_to_bottom): Likewise.
(set_all_contains_variable): Also set alignment to bottom.
(initialize_node_lattices): Likewise.
(propagate_alignment_accross_jump_function): New function.
(propagate_constants_accross_call): Call it.
(ipcp_store_alignment_results): New function.
(ipcp_driver): Call it.
* ipa-prop.c (ipa_node_agg_replacements): Removed.
(ipcp_transformations): New.
(ipa_print_node_jump_functions_for_edge): Also print alignment.
(ipa_set_jf_unknown): New function.
(detect_type_change_from_memory_writes): Use ipa_set_jf_unknown.
(ipa_compute_jump_functions_for_edge): Also calculate alignment.
(update_jump_functions_after_inlining): Use ipa_set_jf_unknown.
(ipcp_grow_transformations_if_necessary): New function.
(ipa_set_node_agg_value_chain): Use ipcp_transformations.
(ipa_node_removal_hook): Likewise.
(ipa_node_duplication_hook): Also duplicate alignment results.
(ipa_write_jump_function): Also stream alignments.
(ipa_read_jump_function): Use ipa_set_jf_unknown, also stream
alignments.
(write_agg_replacement_chain): Renamed to
write_ipcp_transformation_info, also stream alignments.
(read_agg_replacement_chain): Renamed to
read_ipcp_transformation_info, also stream alignments.
(ipa_prop_write_all_agg_replacement): Renamed to
ipcp_write_transformation_summaries. Stream always.
(ipa_prop_read_all_agg_replacement): Renamed to
ipcp_read_transformation_summaries.
(ipcp_update_alignments): New function.
(ipcp_transform_function): Call it, free also alignments.

testsuite/
* gcc.dg/ipa/propalign-1.c: New test.
* gcc.dg/ipa/propalign-2.c: Likewise.

Index: src/gcc/ipa-cp.c
===
--- src.orig/gcc/ipa-cp.c   2014-11-14 22:06:06.240031030 +0100
+++ src/gcc/ipa-cp.c2014-11-15 01:40:38.260521577 +0100
@@ -262,6 +262,9 @@ public:
   ipcp_latticeipa_polymorphic_call_context ctxlat;
   /* Lattices describing aggregate parts.  */
   ipcp_agg_lattice *aggs;
+  /* Alignment information.  Very basic one value lattice where !known means
+ TOP and zero alignment bottom.  */
+  ipa_alignment alignment;
   /* Number of aggregate lattices */
   int aggs_count;
   /* True if aggregate data were passed by reference (as opposed to by
@@ -444,6 +447,13 @@ print_all_lattices (FILE * f, bool dump_
  plats-itself.print (f, dump_sources, dump_benefits);
  fprintf (f,  ctxs: );
  plats-ctxlat.print (f, dump_sources, dump_benefits);
+ if (plats-alignment.known  plats-alignment.align  0)
+   fprintf (f,  Alignment %u, misaglignment %u\n,
+plats-alignment.align, plats-alignment.bitpos);
+ else if (plats-alignment.known)
+   fprintf (f,  Alignment unusable\n);
+ else
+   fprintf (f,  Alignment unknown\n);
  if (plats-virt_call)
fprintf (f, virt_call flag set\n);
 
@@ -761,6 +771,27 @@ set_agg_lats_contain_variable (struct ip
   return ret;
 }
 
+/* Return true if alignemnt informatin in PLATS is known to be unusable.  */
+
+static inline bool
+alignment_bottom_p (ipcp_param_lattices *plats)
+{
+  return plats-alignment.known  (plats-alignment.align == 0);
+}
+
+/* Set alignment information in PLATS to unusable.  Return true if it
+   previously was usable or unknown.  */
+
+static inline bool