diff mbox

Fix alignment propagation

Message ID 20150220051647.GB21632@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Feb. 20, 2015, 5:16 a.m. UTC
> On Fri, Feb 20, 2015 at 12:39:29AM +0100, Jan Hubicka wrote:
> > Hi,
> > this patch fixes alignment propagation that causes wrong code on solex and firefox.
> > Patch is by Martin, I just added the obvous MINUS_EXPR fix (the offset would be wrong,
> > but I see no reason for MINUX_ExPR appearing there with constant parameter), went
> > ahead and commited the fix.
> > 
> > Tested on x86_64-linux.
> 
> Two nits:
> 
> > Index: ChangeLog
> > ===================================================================
> > --- ChangeLog	(revision 220825)
> > +++ ChangeLog	(working copy)
> > @@ -1,3 +1,10 @@
> > +2015-02-19  Martin Jambor  <mjmabor@suse.cz>
> 
> Typo in the e-mail address.
> 
> 
> Two ;'s at the end of the line.

Oops, looks like celebrations of lunar new year was bit too devastating.
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?

	* ipa-cp.c (ipcp_verify_propagated_values): Verify that there
	are no bottoms in alignment.
	(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.

Comments

Martin Jambor Feb. 20, 2015, 2:08 p.m. UTC | #1
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
Jan Hubicka Feb. 20, 2015, 6:22 p.m. UTC | #2
> > +/* 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
diff mbox

Patch

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" } } */