Message ID | 20150220051647.GB21632@kam.mff.cuni.cz |
---|---|
State | New |
Headers | show |
Hi, On Fri, Feb 20, 2015 at 06:16:47AM +0100, Jan Hubicka wrote: > > ... > > This is followup patch that also fixes ;; issue. > It makes the alignment propagation to do proper lattice operations instead > of requiring perfect match and dropping everything to bottom otherwise. > Martin, does it look OK? as I wrote in bugzilla, it is certainly an improvement which I like but I suspect there are two bugs (and a small mistake in changelog): > > * ipa-cp.c (ipcp_verify_propagated_values): Verify that there > are no bottoms in alignment. no TOPs > (decrease_alignment, increase_alignment): New functions. > (propagate_alignment_accross_jump_function): Use proper lattice > operations > * ipa-cp-1.c: New testcase. > * ipa-cp-2.c: New testcase. > Index: ipa-cp.c > =================================================================== > --- ipa-cp.c (revision 220826) > +++ ipa-cp.c (working copy) > @@ -1041,10 +1041,14 @@ ipcp_verify_propagated_values (void) > for (i = 0; i < count; i++) > { > ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i); > + struct ipcp_param_lattices *plats; > + plats = ipa_get_parm_lattices (info, i); > > - if (!lat->bottom > - && !lat->contains_variable > - && lat->values_count == 0) > + if ((!lat->bottom > + && !lat->contains_variable > + && lat->values_count == 0) > + || (!plats->alignment.known > + && opt_for_fn (node->decl, flag_ipa_cp_alignment))) > { > if (dump_file) > { > @@ -1409,6 +1413,60 @@ propagate_context_accross_jump_function > return ret; > } > > +/* Decrease alignment info DEST to be at most CUR. */ > + > +static bool > +decrease_alignment (ipa_alignment *dest, ipa_alignment cur) > +{ > + bool changed = false; > + > + if (!cur.known) > + return false; I really think this should be return set_alignment_to_bottom (dest); If some known alignment has been already propagated to DEST along a different edge and now along the current edge an unknown alignment is coming in, then the result value of the lattice must be BOTTOM and not the previous alignment this code leaves in place. > + if (!dest->known) > + { > + *dest = cur; > + return true; > + } > + if (dest->align == cur.align > + && dest->misalign == cur.misalign) > + return false; > + > + if (dest->align > cur.align) > + { > + dest->align = cur.align; > + if (cur.align) > + dest->misalign > + = dest->misalign % cur.align; > + changed = true; > + } > + if (dest->align && (dest->misalign != (cur.misalign % dest->align))) > + { > + int diff = abs (dest->misalign > + - (cur.misalign % dest->align)); > + dest->align = MIN (dest->align, (unsigned)diff & - diff); > + if (dest->align) > + dest->misalign > + = dest->misalign % dest->align; > + changed = true; > + } > + return changed; > +} > + > +/* Increase alignment info DEST to be at least CUR. */ > + > +static bool > +increase_alignment (ipa_alignment *dest, ipa_alignment cur) > +{ > + if (!dest->known) > + return false; I think this condition always exits. DEST is caller's CUR which was read from jfunc->alignment which is always going to be unknown for PASS_THROUGH and ANCESTOR jump functions at the moment. Perhaps you meant if (!cur.known) ? > + if (!cur.known || dest->align < cur.align) > + { again here, I think you meant !des->.known. Apart from that, I am fine with the patch. Thanks, Martin
> > +/* Decrease alignment info DEST to be at most CUR. */ > > + > > +static bool > > +decrease_alignment (ipa_alignment *dest, ipa_alignment cur) > > +{ > > + bool changed = false; > > + > > + if (!cur.known) > > + return false; > > I really think this should be return set_alignment_to_bottom (dest); > > If some known alignment has been already propagated to DEST along a > different edge and now along the current edge an unknown alignment is > coming in, then the result value of the lattice must be BOTTOM and not > the previous alignment this code leaves in place. Well, because this is an optimisitic propagation now, !cur.known means TOP that is "as good alginment as you can thunk of". You have one known alignment in DEST and TOP in other, result is TOP. > > +/* Increase alignment info DEST to be at least CUR. */ > > + > > +static bool > > +increase_alignment (ipa_alignment *dest, ipa_alignment cur) > > +{ > > + if (!dest->known) > > + return false; > > I think this condition always exits. DEST is caller's CUR which was > read from jfunc->alignment which is always going to be unknown for > PASS_THROUGH and ANCESTOR jump functions at the moment. Perhaps you > meant if (!cur.known) ? Again, it is just lattice operation. If dest is TOP, there is no way to get it better. I assumed that jfunc->alignment.known is meaningful even for PASSTHROUGH (for example for parameters passed by invisible reference) and I turn all !jfunc->alignment.known to BOTTOM in the conditional at beggining of propagate_alignment_accross_jump_function. If we never have useful alginment info on passthrough and ancestor, I suppose we can just drop increase_alignment for now and always go with CUR. > > > + if (!cur.known || dest->align < cur.align) > > + { > > again here, I think you meant !des->.known. Well, if CUR is TOP, you want to return CUR :) Honza > > Apart from that, I am fine with the patch. > Thanks, > > Martin
Index: ipa-cp.c =================================================================== --- ipa-cp.c (revision 220826) +++ ipa-cp.c (working copy) @@ -1041,10 +1041,14 @@ ipcp_verify_propagated_values (void) for (i = 0; i < count; i++) { ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i); + struct ipcp_param_lattices *plats; + plats = ipa_get_parm_lattices (info, i); - if (!lat->bottom - && !lat->contains_variable - && lat->values_count == 0) + if ((!lat->bottom + && !lat->contains_variable + && lat->values_count == 0) + || (!plats->alignment.known + && opt_for_fn (node->decl, flag_ipa_cp_alignment))) { if (dump_file) { @@ -1409,6 +1413,60 @@ propagate_context_accross_jump_function return ret; } +/* Decrease alignment info DEST to be at most CUR. */ + +static bool +decrease_alignment (ipa_alignment *dest, ipa_alignment cur) +{ + bool changed = false; + + if (!cur.known) + return false; + if (!dest->known) + { + *dest = cur; + return true; + } + if (dest->align == cur.align + && dest->misalign == cur.misalign) + return false; + + if (dest->align > cur.align) + { + dest->align = cur.align; + if (cur.align) + dest->misalign + = dest->misalign % cur.align; + changed = true; + } + if (dest->align && (dest->misalign != (cur.misalign % dest->align))) + { + int diff = abs (dest->misalign + - (cur.misalign % dest->align)); + dest->align = MIN (dest->align, (unsigned)diff & - diff); + if (dest->align) + dest->misalign + = dest->misalign % dest->align; + changed = true; + } + return changed; +} + +/* Increase alignment info DEST to be at least CUR. */ + +static bool +increase_alignment (ipa_alignment *dest, ipa_alignment cur) +{ + if (!dest->known) + return false; + if (!cur.known || dest->align < cur.align) + { + *dest = cur; + return true; + } + return false; +} + /* Propagate alignments across jump function JFUNC that is associated with edge CS and update DEST_LAT accordingly. */ @@ -1420,17 +1478,25 @@ propagate_alignment_accross_jump_functio 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) + ipa_alignment cur = jfunc->alignment; + + /* For some reason UNKNOWN jump function gets alignment to be TOP + instead of BOTTOM. */ + if (!cur.known) + { + cur.known = true; + cur.align = 0; + } + + 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; + ipa_alignment incomming_cur; + bool ok = true; if (jfunc->type == IPA_JF_PASS_THROUGH) { @@ -1439,44 +1505,34 @@ propagate_alignment_accross_jump_functio { if (op != POINTER_PLUS_EXPR && op != PLUS_EXPR) - goto prop_fail; + ok = false; tree operand = ipa_get_jf_pass_through_operand (jfunc); if (!tree_fits_shwi_p (operand)) - goto prop_fail; - offset = tree_to_shwi (operand); + ok = false; + else + 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) / BITS_PER_UNIT;; + offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT; } - 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) + if (ok) { - dest_lat->alignment = cur; - return true; + src_lats = ipa_get_parm_lattices (caller_info, src_idx); + + incomming_cur = src_lats->alignment; + if (incomming_cur.known && incomming_cur.align) + incomming_cur.misalign = (incomming_cur.misalign + offset) + % incomming_cur.align; + increase_alignment (&cur, incomming_cur); } - else if (dest_lat->alignment.align == cur.align - && dest_lat->alignment.misalign == cur.misalign) - return false; } - prop_fail: - set_alignment_to_bottom (dest_lat); - return true; + return decrease_alignment (&dest_lat->alignment, cur); } /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches Index: testsuite/gcc.dg/ipa/ipa-cp-2.c =================================================================== --- testsuite/gcc.dg/ipa/ipa-cp-2.c (revision 0) +++ testsuite/gcc.dg/ipa/ipa-cp-2.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-cp" } */ +int n; + +static void +__attribute__ ((noinline)) +test(void *a) +{ + __builtin_memset (a,0,n); +} + +static __attribute__ ((aligned(16))) int aa[10]; + +int +main() +{ + test (&aa[1]); + test (&aa[3]); + return 0; +} +/* { dg-final { scan-ipa-dump "Alignment 8, misalignment 4" "cp" } } */ +/* { dg-final { cleanup-ipa-dump "cp" } } */ Index: testsuite/gcc.dg/ipa/ipa-cp-1.c =================================================================== --- testsuite/gcc.dg/ipa/ipa-cp-1.c (revision 0) +++ testsuite/gcc.dg/ipa/ipa-cp-1.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-cp" } */ +int n; + +static void +__attribute__ ((noinline)) +test(void *a) +{ + __builtin_memset (a,0,n); +} + +int +main() +{ + int aa; + short bb; + test (&aa); + test (&bb); + return 0; +} +/* { dg-final { scan-ipa-dump "Alignment 2" "cp" } } */ +/* { dg-final { cleanup-ipa-dump "cp" } } */