This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]