This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] for PR20625
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 1 Apr 2005 21:57:48 +0200
- Subject: [patch] for PR20625
Hello,
from
struct BS {
int i;
char c[46];
};
void foo(struct BS* p)
{
int i;
for (i = 1; p->c[i]; i++)
;
}
ivopts make
struct BS *ivtmp = p;
for (ivtmp = p; *(char *) (ivtmp + 5B); ivtmp += 1B)
;
The problem is that tree->rtl expansion assumes that pointers of
type struct BS * are always aligned (to at least 4 bytes, I do not
recall the precise value). This makes it to create a misaligned load,
and causes misscompilation leading to segfault on architectures where
misaligned loads are forbidden (alpha).
This patch forces the pointer induction variables (ivtmp) to have type
void * instead, thus fixing the problem.
Boostrapped & regtested on i686 and ppc, and reported to fix the problem
on alpha. I have also run spec benchmarks on i686 to verify that the possible
extra casts to void * do not cause regressions, and it does not seem to
be the case.
Zdenek
PR target/20625
* tree-ssa-loop-ivopts.c (generic_type_for): New function.
(add_candidate_1): Use generic_type_for instead of unsigned_type_for.
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.54
diff -c -3 -p -r2.54 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c 22 Mar 2005 22:08:53 -0000 2.54
--- tree-ssa-loop-ivopts.c 29 Mar 2005 21:07:33 -0000
*************** strip_offset (tree expr, bool inside_add
*** 1840,1845 ****
--- 1840,1861 ----
return fold_convert (orig_type, expr);
}
+ /* Returns variant of TYPE that can be used as base for different uses.
+ For integer types, we return unsigned variant of the type, which
+ avoids problems with overflows. For pointer types, we return void *. */
+
+ static tree
+ generic_type_for (tree type)
+ {
+ if (POINTER_TYPE_P (type))
+ return ptr_type_node;
+
+ if (TYPE_UNSIGNED (type))
+ return type;
+
+ return unsigned_type_for (type);
+ }
+
/* Adds a candidate BASE + STEP * i. Important field is set to IMPORTANT and
position to POS. If USE is not NULL, the candidate is set as related to
it. If both BASE and STEP are NULL, we add a pseudocandidate for the
*************** add_candidate_1 (struct ivopts_data *dat
*** 1852,1865 ****
{
unsigned i;
struct iv_cand *cand = NULL;
! tree type;
if (base)
{
! type = TREE_TYPE (base);
! if (!TYPE_UNSIGNED (type))
{
- type = unsigned_type_for (type);
base = fold_convert (type, base);
if (step)
step = fold_convert (type, step);
--- 1868,1881 ----
{
unsigned i;
struct iv_cand *cand = NULL;
! tree type, orig_type;
if (base)
{
! orig_type = TREE_TYPE (base);
! type = generic_type_for (orig_type);
! if (type != orig_type)
{
base = fold_convert (type, base);
if (step)
step = fold_convert (type, step);