Re: [PATCH] Make IPA-CP propagate alignment information of pointers
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
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
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
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
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-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
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
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
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
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