This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PING][patch,loopiv] misaligned packed array memory access
Zdenek Dvorak wrote:
Hi,
ok, I see now what you meant, just that we also need to pass the
computed offset:
val1 = fold_build2 (MULT_EXPR, type, step, toffset);
this does not seem to be necessary (step is the step of the
address of the reference in bytes, no need to multiply it by anything).
val = fold_build2 (PLUS_EXPR, base_type, base, val1);
I am not sure what you mean by this? As far as I understand the
problem, we need to check that
1) the address is aligned in the first iteration -- which we do now, and
2) the step is a multiple of the alignment
Zdenek
yes you are right. in fact my original patch was developped against a
4.2 branch were `may_be_unaligned_p` was called before 'step' was computed.
Well, here is a revisited patch against the mainline using your
suggestion. I passed the testsuite for sh-superh-elf and bootstraped the
compiler for i686-pc-linux-gnu.
2008-01-28 Christian Bruel <christian.bruel@st.com>
Zdenek Dvorak <ook@ucw.cz>
* tree-ssa-loop-ivopts.c (may_be_unaligned_p): Check step
alignment.
2008-01-28 Christian Bruel <christian.bruel@st.com>
* gcc.dg/packed-array.c: New testcase.
thanks for your help,
Christian
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c (revision 132388)
+++ gcc/tree-ssa-loop-ivopts.c (working copy)
@@ -1391,11 +1391,76 @@
return true;
}
-/* Returns true if memory reference REF may be unaligned. */
+/* If we can prove that TOP = cst * BOT for some constant cst,
+ store cst to MUL and return true. Otherwise return false.
+ The returned value is always sign-extended, regardless of the
+ signedness of TOP and BOT. */
static bool
-may_be_unaligned_p (tree ref)
+constant_multiple_of (tree top, tree bot, double_int *mul)
{
+ tree mby;
+ enum tree_code code;
+ double_int res, p0, p1;
+ unsigned precision = TYPE_PRECISION (TREE_TYPE (top));
+
+ STRIP_NOPS (top);
+ STRIP_NOPS (bot);
+
+ if (operand_equal_p (top, bot, 0))
+ {
+ *mul = double_int_one;
+ return true;
+ }
+
+ code = TREE_CODE (top);
+ switch (code)
+ {
+ case MULT_EXPR:
+ mby = TREE_OPERAND (top, 1);
+ if (TREE_CODE (mby) != INTEGER_CST)
+ return false;
+
+ if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &res))
+ return false;
+
+ *mul = double_int_sext (double_int_mul (res, tree_to_double_int (mby)),
+ precision);
+ return true;
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &p0)
+ || !constant_multiple_of (TREE_OPERAND (top, 1), bot, &p1))
+ return false;
+
+ if (code == MINUS_EXPR)
+ p1 = double_int_neg (p1);
+ *mul = double_int_sext (double_int_add (p0, p1), precision);
+ return true;
+
+ case INTEGER_CST:
+ if (TREE_CODE (bot) != INTEGER_CST)
+ return false;
+
+ p0 = double_int_sext (tree_to_double_int (top), precision);
+ p1 = double_int_sext (tree_to_double_int (bot), precision);
+ if (double_int_zero_p (p1))
+ return false;
+ *mul = double_int_sext (double_int_sdivmod (p0, p1, FLOOR_DIV_EXPR, &res),
+ precision);
+ return double_int_zero_p (res);
+
+ default:
+ return false;
+ }
+}
+
+/* Returns true if memory reference REF with step STEP may be unaligned. */
+
+static bool
+may_be_unaligned_p (tree ref, tree step)
+{
tree base;
tree base_type;
HOST_WIDE_INT bitsize;
@@ -1418,12 +1483,20 @@
base_type = TREE_TYPE (base);
base_align = TYPE_ALIGN (base_type);
- if (mode != BLKmode
- && (base_align < GET_MODE_ALIGNMENT (mode)
- || bitpos % GET_MODE_ALIGNMENT (mode) != 0
- || bitpos % BITS_PER_UNIT != 0))
- return true;
+ if (mode != BLKmode) {
+ double_int mul;
+ tree al = build_int_cst (TREE_TYPE (step),
+ GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT);
+ if (base_align < GET_MODE_ALIGNMENT (mode)
+ || bitpos % GET_MODE_ALIGNMENT (mode) != 0
+ || bitpos % BITS_PER_UNIT != 0)
+ return true;
+
+ if (! constant_multiple_of (step, al, &mul))
+ return true;
+ }
+
return false;
}
@@ -1549,7 +1622,7 @@
/* Moreover, on strict alignment platforms, check that it is
sufficiently aligned. */
- if (STRICT_ALIGNMENT && may_be_unaligned_p (base))
+ if (STRICT_ALIGNMENT && may_be_unaligned_p (base, step))
goto fail;
base = build_fold_addr_expr (base);
@@ -2585,71 +2658,6 @@
return (w >> bitno) & 1;
}
-/* If we can prove that TOP = cst * BOT for some constant cst,
- store cst to MUL and return true. Otherwise return false.
- The returned value is always sign-extended, regardless of the
- signedness of TOP and BOT. */
-
-static bool
-constant_multiple_of (tree top, tree bot, double_int *mul)
-{
- tree mby;
- enum tree_code code;
- double_int res, p0, p1;
- unsigned precision = TYPE_PRECISION (TREE_TYPE (top));
-
- STRIP_NOPS (top);
- STRIP_NOPS (bot);
-
- if (operand_equal_p (top, bot, 0))
- {
- *mul = double_int_one;
- return true;
- }
-
- code = TREE_CODE (top);
- switch (code)
- {
- case MULT_EXPR:
- mby = TREE_OPERAND (top, 1);
- if (TREE_CODE (mby) != INTEGER_CST)
- return false;
-
- if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &res))
- return false;
-
- *mul = double_int_sext (double_int_mul (res, tree_to_double_int (mby)),
- precision);
- return true;
-
- case PLUS_EXPR:
- case MINUS_EXPR:
- if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &p0)
- || !constant_multiple_of (TREE_OPERAND (top, 1), bot, &p1))
- return false;
-
- if (code == MINUS_EXPR)
- p1 = double_int_neg (p1);
- *mul = double_int_sext (double_int_add (p0, p1), precision);
- return true;
-
- case INTEGER_CST:
- if (TREE_CODE (bot) != INTEGER_CST)
- return false;
-
- p0 = double_int_sext (tree_to_double_int (top), precision);
- p1 = double_int_sext (tree_to_double_int (bot), precision);
- if (double_int_zero_p (p1))
- return false;
- *mul = double_int_sext (double_int_sdivmod (p0, p1, FLOOR_DIV_EXPR, &res),
- precision);
- return double_int_zero_p (res);
-
- default:
- 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
/* { dg-do run } */
/* { dg-options "-O2 -fno-inline" } */
struct usb_interface_descriptor {
unsigned short wMaxPacketSize;
char e;
} __attribute__ ((packed));
struct usb_device {
int devnum;
struct usb_interface_descriptor if_desc[2];
};
int b;
void foo (unsigned short a)
{
b = a;
}
struct usb_device ndev;
void usb_set_maxpacket(int n)
{
int i;
for(i=0; i<n;i++)
foo((&ndev)->if_desc[i].wMaxPacketSize);
}
int
main()
{
usb_set_maxpacket(2);
return b;
}