diff options
author | J"orn Rennecke <joern.rennecke@st.com> | 2006-09-01 20:25:34 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2006-09-01 20:25:34 +0000 |
commit | 537b8a357cd1c24042180937b030bce255042d23 (patch) | |
tree | 73e61e20e7b99a9069c8edce11782f70fa49d2da /gcc/builtins.c | |
parent | cd709ec369752db0a7c8f9109e8faf2bc87f6c72 (diff) | |
download | gcc-537b8a357cd1c24042180937b030bce255042d23.tar.gz |
re PR middle-end/27226 (Compiler looses track of alignment for emit_block_move)
2006-09-01 J"orn Rennecke <joern.rennecke@st.com>
Richard Guenther <rguenther@suse.de>
Adam Nemet <anemet@caviumnetworks.com>
PR middle-end/27226
* builtins.c (get_pointer_alignment): Handle more forms
of base addresses that can be used to derive more precise
information about alignment.
* gcc.target/mips/memcpy-1.c: New testcase.
* gcc.dg/pr27226.c: Likewise.
Co-Authored-By: Adam Nemet <anemet@caviumnetworks.com>
Co-Authored-By: Richard Guenther <rguenther@suse.de>
From-SVN: r116641
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 47c61cdb133..4aff7d09809 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -275,16 +275,44 @@ get_pointer_alignment (tree exp, unsigned int max_align) /* See what we are pointing at and look at its alignment. */ exp = TREE_OPERAND (exp, 0); inner = max_align; - while (handled_component_p (exp)) + if (handled_component_p (exp)) { - /* Fields in a structure can be packed, honor DECL_ALIGN - of the FIELD_DECL. For all other references the conservative - alignment is the element type alignment. */ - if (TREE_CODE (exp) == COMPONENT_REF) - inner = MIN (inner, DECL_ALIGN (TREE_OPERAND (exp, 1))); - else - inner = MIN (inner, TYPE_ALIGN (TREE_TYPE (exp))); - exp = TREE_OPERAND (exp, 0); + HOST_WIDE_INT bitsize, bitpos; + tree offset; + enum machine_mode mode; + int unsignedp, volatilep; + + exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, + &mode, &unsignedp, &volatilep, true); + if (bitpos) + inner = MIN (inner, (unsigned) (bitpos & -bitpos)); + if (offset && TREE_CODE (offset) == PLUS_EXPR + && host_integerp (TREE_OPERAND (offset, 1), 1)) + { + /* Any overflow in calculating offset_bits won't change + the alignment. */ + unsigned offset_bits + = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1) + * BITS_PER_UNIT); + + if (offset_bits) + inner = MIN (inner, (offset_bits & -offset_bits)); + offset = TREE_OPERAND (offset, 0); + } + if (offset && TREE_CODE (offset) == MULT_EXPR + && host_integerp (TREE_OPERAND (offset, 1), 1)) + { + /* Any overflow in calculating offset_factor won't change + the alignment. */ + unsigned offset_factor + = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1) + * BITS_PER_UNIT); + + if (offset_factor) + inner = MIN (inner, (offset_factor & -offset_factor)); + } + else if (offset) + inner = MIN (inner, BITS_PER_UNIT); } if (TREE_CODE (exp) == FUNCTION_DECL) align = FUNCTION_BOUNDARY; @@ -294,6 +322,9 @@ get_pointer_alignment (tree exp, unsigned int max_align) else if (CONSTANT_CLASS_P (exp)) align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align)); #endif + else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR + || TREE_CODE (exp) == INDIRECT_REF) + align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner); else align = MIN (align, inner); return MIN (align, max_align); |