public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch,loopiv] misaligned packed array memory access
@ 2008-01-28 21:38 Christian BRUEL
  2008-01-30 16:30 ` Christian BRUEL
  2008-02-13 16:07 ` [PING][patch,loopiv] " Christian BRUEL
  0 siblings, 2 replies; 13+ messages in thread
From: Christian BRUEL @ 2008-01-28 21:38 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 991 bytes --]

The attached test case reduces a misaligned field access from an array 
of packed structs. In this example compiled with -O2 the field 
wMaxPacketSize is accessed (on sh4) with a mov.w instruction although it 
is byte aligned.

The tree-ssa-loop ivopts did not check packed struct offsets indexed by 
an induction variable. Thus if the struct size is not aligned, the field 
  becomes unaligned after the first iteration even if it was aligned 
from the base of this structure.

This patch solves this problem by expanding may_be_unaligned_p to check 
that a loop carried offset is a multiple of the desired alignment.

This bug impacted STRICT_ALIGNMENT targets. I regtested on sh-superh-elf 
and sh4-linux-gnu.

Also bootstraped for i686-pc-linux-gnu.

Thanks you for any feedback and trunk approval if ok.

-c

2008-01-28  Christian Bruel  <christian.bruel@st.com>

	* tree-ssa-loop-ivopts.c (may_be_unaligned_p): check loop carried offset.
	* (loop_offset_multiple_of): new function.




[-- Attachment #2: packed_align.trunk.patch --]
[-- Type: text/plain, Size: 3124 bytes --]

Index: tree-ssa-loop-ivopts.c
===================================================================
--- tree-ssa-loop-ivopts.c	(revision 131825)
+++ tree-ssa-loop-ivopts.c	(working copy)
@@ -1378,10 +1378,13 @@
   return true;
 }
 
+static bool
+loop_offset_multiple_of (struct ivopts_data *, tree , tree);
+
 /* Returns true if memory reference REF may be unaligned.  */
 
 static bool
-may_be_unaligned_p (tree ref)
+may_be_unaligned_p (struct ivopts_data *data, tree ref)
 {
   tree base;
   tree base_type;
@@ -1405,11 +1408,18 @@
   base_type = TREE_TYPE (base);
   base_align = TYPE_ALIGN (base_type);
 
-  if (mode != BLKmode
-      && (base_align < GET_MODE_ALIGNMENT (mode)
+  if (mode != BLKmode) {
+      if (base_align < GET_MODE_ALIGNMENT (mode)
 	  || bitpos % GET_MODE_ALIGNMENT (mode) != 0
-	  || bitpos % BITS_PER_UNIT != 0))
-    return true;
+	  || bitpos % BITS_PER_UNIT != 0) 
+	return true;
+      
+      if (toffset && contains_packed_reference (ref)) {
+	tree al = build_int_cst (NULL_TREE, GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT);
+	if (!loop_offset_multiple_of (data, toffset, al))
+	  return true;
+      } 
+  }
 
   return false;
 }
@@ -1467,7 +1477,7 @@
     goto fail;
 
   if (STRICT_ALIGNMENT
-      && may_be_unaligned_p (base))
+      && may_be_unaligned_p (data, base))
     goto fail;
 
   base = unshare_expr (base);
@@ -2566,6 +2576,63 @@
     }
 }
 
+/* Returns true if OFFSET is always a multiple of alignment AL
+   even if loop carried.  */
+
+static bool
+loop_offset_multiple_of (struct ivopts_data *data, tree offset, tree al)
+{
+  double_int mul;
+
+  STRIP_NOPS (offset);
+
+  if (TREE_CODE (offset) == SSA_NAME) {
+    struct iv *civ = get_iv (data, offset);
+    if (!civ || constant_multiple_of (offset, al, &mul))
+      return true;
+  }
+
+  if (TREE_CODE (offset) == MULT_EXPR) {
+    tree op0 = TREE_OPERAND (offset, 0);
+    tree op1 = TREE_OPERAND (offset, 1);
+    STRIP_NOPS (op0);
+    STRIP_NOPS (op1);
+
+    if (TREE_CODE (op1) != INTEGER_CST)
+      return false;
+      
+    if (TREE_CODE (op0) == SSA_NAME) {
+      struct iv *civ = get_iv (data, op0);
+      tree type = TREE_TYPE (op1);
+      if (!civ)
+	return true;
+
+      tree val = fold_build2 (PLUS_EXPR, type, civ->base, 
+			      fold_build2 (MULT_EXPR, type, civ->step, op1));
+
+      if (constant_multiple_of (val, al, &mul))
+	return true;
+    }
+    else if (loop_offset_multiple_of (data, op0, al))
+      return true;
+  }
+
+  else if (TREE_CODE (offset) == PLUS_EXPR
+	   || TREE_CODE (offset) == MINUS_EXPR) {
+    tree op0 = TREE_OPERAND (offset, 0);
+    tree op1 = TREE_OPERAND (offset, 1);
+    if (loop_offset_multiple_of (data, op0, al) &&
+	loop_offset_multiple_of (data, op1, al))
+      return true;
+  }
+
+  else if (TREE_CODE (offset) == INTEGER_CST) {
+    return constant_multiple_of (offset, al, &mul);
+  }
+
+  return false;
+}
+
 /* If A is (TYPE) BA and B is (TYPE) BB, and the types of BA and BB have the
    same precision that is at least as wide as the precision of TYPE, stores
    BA to A and BB to B, and returns the type of BA.  Otherwise, returns the

[-- Attachment #3: example.bad.c --]
[-- Type: text/x-c, Size: 354 bytes --]

struct usb_interface_descriptor {
 unsigned short wMaxPacketSize;
  char e;
} __attribute__ ((packed));

struct usb_device {
 int devnum;
 struct usb_interface_descriptor if_desc[2];
};

extern void foo (unsigned short);

void usb_set_maxpacket(struct usb_device *dev, int n)
{
  int i;

  for(i=0; i<n;i++)
    foo(dev->if_desc[i].wMaxPacketSize);
}




^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2008-05-01 16:08 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-01-28 21:38 [patch,loopiv] misaligned packed array memory access Christian BRUEL
2008-01-30 16:30 ` Christian BRUEL
2008-02-13 16:07 ` [PING][patch,loopiv] " Christian BRUEL
2008-02-13 20:26   ` Zdenek Dvorak
2008-02-14  9:26     ` Christian BRUEL
2008-02-14 16:44       ` Zdenek Dvorak
2008-02-15  9:03         ` Christian BRUEL
2008-02-15 14:11           ` Zdenek Dvorak
2008-02-15 15:08             ` Christian BRUEL
2008-02-15 15:19               ` Zdenek Dvorak
2008-02-18 13:46                 ` Christian BRUEL
2008-02-18 15:19                   ` Zdenek Dvorak
2008-05-01 16:08                     ` Maxim Kuvyrkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).