Roger Sayle wrote:
> On Sun, 15 May 2005, Richard Guenther wrote:
> 
>>What can be done about this issues?  First, we can use VIEW_CONVERT_EXPR
>>unconditionally in fold_indirect_ref and only break some optimizations
>>(like temp1.C).  Second, we can declare fold_indirect_ref being unsafe
>>about types and deal with this in its callers where we possibly know
>>about if we're dealing with lvalues or rvalues, using either NOP_EXPRs
>>or VIEW_CONVERT_EXPRs as appropriate.  We could ease this with providing
>>wrappers around fold_indirect_ref (or a flag) - but checking if we're
>>(possibly) dealing with a lhs is not possible, so uses may remain
>>unsafe.
> 
> 
> Exactly which optimization do we miss by changing:
> 
>       /* *&p => p */
> -     if (lang_hooks.types_compatible_p (type, optype))
> +     if (type == optype)
>         return op;

I don't know - maybe stripping sign casts.  But if we use equality
comparison here we can as well use STRIP_TYPE_NOPS instead of
STRIP_NOPS - but the patch doing so caused some optimization regressions.

If we want to simplify fold_indirect_ref_1 this way and enforce
type before == type after I can prepare a patch to do so.  Meanwhile
a patch that survived some testing is attached for reference - it
does fix some type issues but leaves the fixing of the types to
fold_indirect_ref.  Note that similarly build_fold_indirect_ref is
used in many places that look like they do not deal with mismatched
types.

Thanks for the input,
Richard.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.580
diff -c -3 -p -r1.580 fold-const.c
*** fold-const.c        14 May 2005 15:42:01 -0000      1.580
--- fold-const.c        15 May 2005 15:30:37 -0000
*************** fold_indirect_ref_1 (tree t)
*** 11420,11437 ****
        return op;
        /* *(foo *)&fooarray => fooarray[0] */
        else if (TREE_CODE (optype) == ARRAY_TYPE
               && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
        {
          tree type_domain = TYPE_DOMAIN (optype);
          tree min_val = size_zero_node;
          if (type_domain && TYPE_MIN_VALUE (type_domain))
            min_val = TYPE_MIN_VALUE (type_domain);
!         return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
        }
      }
  
    /* *(foo *)fooarrptr => (*fooarrptr)[0] */
    if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
        && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE 
(subtype))))
      {
        tree type_domain;
--- 11427,11447 ----
        return op;
        /* *(foo *)&fooarray => fooarray[0] */
        else if (TREE_CODE (optype) == ARRAY_TYPE
+              /* FIXME unnecessary?  */
               && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
        {
          tree type_domain = TYPE_DOMAIN (optype);
          tree min_val = size_zero_node;
          if (type_domain && TYPE_MIN_VALUE (type_domain))
            min_val = TYPE_MIN_VALUE (type_domain);
!         return build4 (ARRAY_REF, TREE_TYPE (optype),
!                        op, min_val, NULL_TREE, NULL_TREE);
        }
      }
  
    /* *(foo *)fooarrptr => (*fooarrptr)[0] */
    if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
+       /* FIXME unnecessary?  */
        && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE 
(subtype))))
      {
        tree type_domain;
*************** fold_indirect_ref_1 (tree t)
*** 11440,11453 ****
        type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
        if (type_domain && TYPE_MIN_VALUE (type_domain))
        min_val = TYPE_MIN_VALUE (type_domain);
!       return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
      }
  
    return NULL_TREE;
  }
  
  /* Builds an expression for an indirection through T, simplifying some
!    cases.  */
  
  tree
  build_fold_indirect_ref (tree t)
--- 11450,11465 ----
        type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
        if (type_domain && TYPE_MIN_VALUE (type_domain))
        min_val = TYPE_MIN_VALUE (type_domain);
!       return build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (sub)),
!                    sub, min_val, NULL_TREE, NULL_TREE);
      }
  
    return NULL_TREE;
  }
  
  /* Builds an expression for an indirection through T, simplifying some
!    cases.  Note that the type of the resulting expression does not
!    necessarily match that of the type pointed to by T.  */
  
  tree
  build_fold_indirect_ref (tree t)
*************** tree
*** 11466,11476 ****
  fold_indirect_ref (tree t)
  {
    tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
  
!   if (sub)
      return sub;
    else
!     return t;
  }
  
  /* Strip non-trapping, non-side-effecting tree nodes from an expression
--- 11478,11492 ----
  fold_indirect_ref (tree t)
  {
    tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
+   if (! sub)
+     return t;
  
!   if (TREE_TYPE (sub) == TREE_TYPE (t))
      return sub;
+   else if (maybe_lvalue_p (sub))
+     return fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (t), sub);
    else
!     return fold_convert (TREE_TYPE (t), sub);
  }
  
  /* Strip non-trapping, non-side-effecting tree nodes from an expression

Reply via email to