[PATCH][RFC] Introduce MEM_REF

Richard Guenther rguenther@suse.de
Wed Mar 10 16:19:00 GMT 2010


This introduces a new memory-access tree, MEM_REF, which is supposed
to replace INDIRECT_REF (and its variants with some additional support
elsewhere).  There are several issues that MEM_REF is supposed to
address:

 1) We really want to get rid of pointer-type conversions as they
    are generally value-preserving.  Doing so facilitates must-alias
    analysis and CSE and should save IL memory.

 2) We want type-based alias information to be tied to the memory
    access, not to the pointer-type.  Doing the latter is one thing
    that forces us to retain pointer-type conversions.

 3) There is no way to attach per-access information to plain decls.
    See for example the hoops we jump through to preserve volatileness
    on non-volatile qualified decls.

To address 1) and 2) the MEM_REF tree has an explicit type that is
used for TBAA.  It happens to be that this needs to be a pointer
type (because of the TYPE_REF_CAN_ALIAS_ALL flag).  Thus the
MEM_REF operation implicitly contains a pointer-conversion.
MEM_REF <T*, p> is *(T*)p.  Conveniently we encode this pointer-type
using a tree constant operand - which conveniently gets us a
constant offset we can use to compact simple component references
as well as re-materialize all accesses get_ref_base_and_extent
can analyze.  So, MEM_REF <p, CST> then is *(typeof(CST)p + CST).

To address 3) the pointer operand of a MEM_REF can be an address-taking
operation (gimple in theory allows this for INDIRECT_REFs as well,
just nobody properly deals with that).  The trick is to not force
decls addressable (and thus aliased) just because they are used
as MEM_REF operand wrapped inside an ADDR_EXPR.  This allows a
similar trick I used to address PR42834 to rewrite decls used in
MEM_REF trees into SSA once they no longer really have their
address taken.

The patch is an incremental step towards a flatter representation
of memory accesses like it had been developed on the mem-ref branch.

Sofar I rewrite all INDIRECT_REFs to MEM_REFs at gimplification
time (so yes, you can have component-refs around MEM_REFs).

This is just a prototype for now (it does not bootstrap but it is
able to build all target libraries without ICEing.
Certainly the verifier will trigger on ALIGN_INDIRECT_REFs
and MISALIGNED_INDIRECT_REFs the vectorizer still produces).
ALIGN_INDIRECT_REFs should simply be issued in lowered form.
MISALIGNED_INDIRECT_REFs should be treated at the point we
introduce alignment information to SSA names.

Further patches might get rid of VIEW_CONVERT_EXPRs on memory
(retaining them on registers only, just like mem-ref branch did).
Similar with BIT_FIELD_REF (though that raised concerns previously).
Especially VN and SRA might benefit from the possibility to
re-materialize memory references in an easier way.

For now this should make possible to fix PR42834 without introducing
TARGET_MEM_REFs in the IL so early.

The patch at least fails gcc.c-torture/execute/20000113-1.c because
SRA completely scalarizes structs with bitfields (but MEM_REF has
only byte offsets).  So SRA needs to be modified to either avoid
this or to do what bitfield lowering did on the mem-ref branch,
create one byte-aligned load and several BIT_FIELD_REFs.

What is currently missing?
 - folding of &MEM[p + CST] to p + CST, doesn't work because
   build_fold_addr_expr doesn't know of useless conversions
   so we generate non-gimple with type conversions
 - forwarding of q = p + CST into MEM[q + CST']
 - adjusting optimization passes (both SRA and IVOPTs are completely
   disabled in the patch, FRE has very rudimentary support for MEMs)
 - CALL_EXPRs miss an explicit function type, so function pointer
   conversions are not useless (yet).  An easy way out is to
   use Fn rather than Fn * as call argument (so we'd get a
   MEM_REF for indirect calls).  Other suggestions welcome.
 - I have to think about restrict support (again), for now
   conversions to restrict pointers are not useless (though we
   do have all memory accesses via restrict qualified pointers
   marked properly by the pointer-type in the MEM_REF tree).

Basically the patch is in a stage where feedback would be nice.
The patch allows experiments.

What would be the plan?  The plan would be to roll out MEM_REF support
as far as to allow PR42834 being fixed w/o using TARGET_MEM_REF.
Thus mainly leave the gimplification and INDIRECT_REF path removals
out.  With the chance that we might end up with INDIRECT_REF not
being removed for 4.6.


(ChangeLog to-be-written)

Index: trunk/gcc/alias.c
===================================================================
*** trunk.orig/gcc/alias.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/alias.c	2010-03-09 15:08:13.000000000 +0100
*************** ao_ref_from_mem (ao_ref *ref, const_rtx
*** 280,286 ****
  
    /* If this is a pointer dereference of a non-SSA_NAME punt.
       ???  We could replace it with a pointer to anything.  */
!   if (INDIRECT_REF_P (base)
        && TREE_CODE (TREE_OPERAND (base, 0)) != SSA_NAME)
      return false;
  
--- 280,286 ----
  
    /* If this is a pointer dereference of a non-SSA_NAME punt.
       ???  We could replace it with a pointer to anything.  */
!   if (TREE_CODE (base) == MEM_REF
        && TREE_CODE (TREE_OPERAND (base, 0)) != SSA_NAME)
      return false;
  
*************** ao_ref_from_mem (ao_ref *ref, const_rtx
*** 301,307 ****
        if (namep)
  	{
  	  ref->base_alias_set = get_alias_set (base);
! 	  ref->base = build1 (INDIRECT_REF, TREE_TYPE (base), *(tree *)namep);
  	}
      }
  
--- 301,307 ----
        if (namep)
  	{
  	  ref->base_alias_set = get_alias_set (base);
! 	  ref->base = build_simple_mem_ref (*(tree *)namep);
  	}
      }
  
*************** get_alias_set (tree t)
*** 668,673 ****
--- 668,675 ----
  	  if (set != -1)
  	    return set;
  	}
+       else if (TREE_CODE (inner) == MEM_REF)
+ 	return get_deref_alias_set (TREE_OPERAND (inner, 1));
  
        /* Otherwise, pick up the outermost object that we could have a pointer
  	 to, processing conversions as above.  */
Index: trunk/gcc/expr.c
===================================================================
*** trunk.orig/gcc/expr.c	2010-03-08 10:32:38.000000000 +0100
--- trunk/gcc/expr.c	2010-03-10 16:40:03.000000000 +0100
*************** expand_assignment (tree to, tree from, b
*** 4215,4220 ****
--- 4215,4224 ----
       an array element in an unaligned packed structure field, has the same
       problem.  */
    if (handled_component_p (to)
+       /* ???  We only need to handle MEM_REF here if the access is not
+          a full access of the base object.  */
+       || (TREE_CODE (to) == MEM_REF
+ 	  && TREE_CODE (TREE_OPERAND (to, 0)) == ADDR_EXPR)
        || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
      {
        enum machine_mode mode1;
*************** get_inner_reference (tree exp, HOST_WIDE
*** 6085,6090 ****
--- 6089,6116 ----
  	    goto done;
  	  break;
  
+ 	case MEM_REF:
+ 	  if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
+ 	    {
+ 	      tree off = TREE_OPERAND (exp, 1);
+ 	      if (!integer_zerop (off))
+ 		{
+ 		  unsigned HOST_WIDE_INT boffl;
+ 		  HOST_WIDE_INT boffh;
+ 		  lshift_double (TREE_INT_CST_LOW (off),
+ 				 TREE_INT_CST_HIGH (off),
+ 				 exact_log2 (BITS_PER_UNIT),
+ 				 2 * HOST_BITS_PER_WIDE_INT,
+ 				 &boffl, &boffh, 1);
+ 		  bit_offset
+ 		    = size_binop (PLUS_EXPR, bit_offset,
+ 				  build_int_cst_wide_type (bitsizetype,
+ 							   boffl, boffh));
+ 		}
+ 	      exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ 	    }
+ 	  goto done;
+ 
  	default:
  	  goto done;
  	}
*************** expand_expr_addr_expr_1 (tree exp, rtx t
*** 6843,6848 ****
--- 6869,6883 ----
        /* This case will happen via recursion for &a->b.  */
        return expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
  
+     case MEM_REF:
+       {
+ 	tree tem = TREE_OPERAND (exp, 0);
+ 	if (!integer_zerop (TREE_OPERAND (exp, 1)))
+ 	  tem = build2 (POINTER_PLUS_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)),
+ 			tem, fold_convert (sizetype, TREE_OPERAND (exp, 1)));
+ 	return expand_expr (tem, target, tmode, modifier);
+       }
+ 
      case CONST_DECL:
        /* Expand the initializer like constants above.  */
        return XEXP (expand_expr_constant (DECL_INITIAL (exp), 0, modifier), 0);
*************** expand_expr_real_1 (tree exp, rtx target
*** 8736,8741 ****
--- 8771,8838 ----
        }
        return temp;
  
+     case MEM_REF:
+       {
+ 	addr_space_t as
+ 	  = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))));
+ 	enum machine_mode address_mode;
+ 	tree base = TREE_OPERAND (exp, 0);
+ 	/* Handle expansion of non-aliased memory with non-BLKmode.  That
+ 	   might end up in a register.  */
+ 	if (TREE_CODE (base) == ADDR_EXPR)
+ 	  {
+ 	    tree offset = TREE_OPERAND (exp, 1);
+ 	    base = TREE_OPERAND (base, 0);
+ 	    offset = build_int_cst_wide_type (bitsizetype,
+ 					      TREE_INT_CST_LOW (offset),
+ 					      TREE_INT_CST_HIGH (offset));
+ 	    offset = size_binop (MULT_EXPR,
+ 				 offset, bitsize_int (BITS_PER_UNIT));
+ 	    if (!DECL_P (base))
+ 	      {
+ 		HOST_WIDE_INT off, size, max_size;
+ 		base = get_ref_base_and_extent (base, &off, &size, &max_size);
+ 		offset = size_binop (PLUS_EXPR, offset, bitsize_int (off));
+ 	      }
+ 	    if (DECL_P (base)
+ 		&& !TREE_ADDRESSABLE (base)
+ 		&& integer_zerop (offset)
+ 		&& DECL_MODE (base) != BLKmode
+ 		&& host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ 		&& (GET_MODE_BITSIZE (DECL_MODE (base))
+ 		    == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))
+ 	      return expand_expr (build1 (VIEW_CONVERT_EXPR,
+ 					  TREE_TYPE (exp), base),
+ 				  target, tmode, modifier);
+ 	    if (DECL_P (base)
+ 		&& !TREE_ADDRESSABLE (base)
+ 		&& TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
+ 	      return expand_expr (build3 (BIT_FIELD_REF, TREE_TYPE (exp),
+ 					  base,
+ 					  bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp)))),
+ 					  offset),
+ 				  target, tmode, modifier);
+ 	  }
+ 	address_mode = targetm.addr_space.address_mode (as);
+ 	op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, address_mode,
+ 			   EXPAND_NORMAL);
+ 	if (!integer_zerop (TREE_OPERAND (exp, 1)))
+ 	  {
+ 	    rtx off;
+ 	    off = immed_double_const (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)),
+ 				      TREE_INT_CST_HIGH (TREE_OPERAND (exp, 1)),
+ 				      address_mode);
+ 	    op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
+ 	  }
+ 	op0 = memory_address_addr_space (mode, op0, as);
+ 	temp = gen_rtx_MEM (mode, op0);
+ 	set_mem_attributes (temp, exp, 0);
+ 	set_mem_addr_space (temp, as);
+ 	if (TREE_THIS_VOLATILE (exp))
+ 	  MEM_VOLATILE_P (temp) = 1;
+ 	return temp;
+       }
+ 
      case ARRAY_REF:
  
        {
Index: trunk/gcc/fold-const.c
===================================================================
*** trunk.orig/gcc/fold-const.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/fold-const.c	2010-03-08 17:22:01.000000000 +0100
*************** build_fold_addr_expr_with_type_loc (loca
*** 8299,8304 ****
--- 8299,8313 ----
        if (TREE_TYPE (t) != ptrtype)
  	t = fold_convert_loc (loc, ptrtype, t);
      }
+   else if (TREE_CODE (t) == MEM_REF)
+     {
+       tree tem = fold_convert_loc (loc, ptrtype, TREE_OPERAND (t, 0));
+       if (!integer_zerop (TREE_OPERAND (t, 1)))
+ 	t = fold_build2 (POINTER_PLUS_EXPR, ptrtype, tem,
+ 			 fold_convert (sizetype, TREE_OPERAND (t, 1)));
+       else
+ 	t = tem;
+     }
    else
      {
        t = build1 (ADDR_EXPR, ptrtype, t);
*************** fold_comparison (location_t loc, enum tr
*** 9361,9366 ****
--- 9370,9380 ----
        else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
  	{
  	  base0 = TREE_OPERAND (arg0, 0);
+ 	  if (TREE_CODE (base0) == ADDR_EXPR)
+ 	    {
+ 	      base0 = TREE_OPERAND (base0, 0);
+ 	      indirect_base0 = true;
+ 	    }
  	  offset0 = TREE_OPERAND (arg0, 1);
  	}
  
*************** fold_comparison (location_t loc, enum tr
*** 9378,9383 ****
--- 9392,9402 ----
        else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR)
  	{
  	  base1 = TREE_OPERAND (arg1, 0);
+ 	  if (TREE_CODE (base1) == ADDR_EXPR)
+ 	    {
+ 	      base1 = TREE_OPERAND (base1, 0);
+ 	      indirect_base1 = true;
+ 	    }
  	  offset1 = TREE_OPERAND (arg1, 1);
  	}
  
Index: trunk/gcc/gimple.c
===================================================================
*** trunk.orig/gcc/gimple.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/gimple.c	2010-03-08 16:22:53.000000000 +0100
*************** is_gimple_condexpr (tree t)
*** 2475,2481 ****
  bool
  is_gimple_addressable (tree t)
  {
!   return (is_gimple_id (t) || handled_component_p (t) || INDIRECT_REF_P (t));
  }
  
  /* Return true if T is a valid gimple constant.  */
--- 2475,2482 ----
  bool
  is_gimple_addressable (tree t)
  {
!   return (is_gimple_id (t) || handled_component_p (t)
! 	  || TREE_CODE (t) == MEM_REF);
  }
  
  /* Return true if T is a valid gimple constant.  */
*************** is_gimple_address (const_tree t)
*** 2526,2532 ****
        op = TREE_OPERAND (op, 0);
      }
  
!   if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op))
      return true;
  
    switch (TREE_CODE (op))
--- 2527,2533 ----
        op = TREE_OPERAND (op, 0);
      }
  
!   if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
      return true;
  
    switch (TREE_CODE (op))
*************** is_gimple_min_lval (tree t)
*** 2804,2810 ****
  {
    if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
      return false;
!   return (is_gimple_id (t) || TREE_CODE (t) == INDIRECT_REF);
  }
  
  /* Return true if T is a typecast operation.  */
--- 2805,2811 ----
  {
    if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
      return false;
!   return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
  }
  
  /* Return true if T is a typecast operation.  */
*************** get_base_address (tree t)
*** 2858,2864 ****
    if (SSA_VAR_P (t)
        || TREE_CODE (t) == STRING_CST
        || TREE_CODE (t) == CONSTRUCTOR
!       || INDIRECT_REF_P (t))
      return t;
    else
      return NULL_TREE;
--- 2859,2865 ----
    if (SSA_VAR_P (t)
        || TREE_CODE (t) == STRING_CST
        || TREE_CODE (t) == CONSTRUCTOR
!       || TREE_CODE (t) == MEM_REF)
      return t;
    else
      return NULL_TREE;
*************** count_ptr_derefs (tree *tp, int *walk_su
*** 4252,4258 ****
        return NULL_TREE;
      }
  
!   if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
      {
        if (wi_p->is_lhs)
  	count_p->num_stores++;
--- 4253,4259 ----
        return NULL_TREE;
      }
  
!   if (TREE_CODE (*tp) == MEM_REF && TREE_OPERAND (*tp, 0) == count_p->ptr)
      {
        if (wi_p->is_lhs)
  	count_p->num_stores++;
*************** get_base_loadstore (tree op)
*** 4324,4330 ****
    while (handled_component_p (op))
      op = TREE_OPERAND (op, 0);
    if (DECL_P (op)
!       || INDIRECT_REF_P (op)
        || TREE_CODE (op) == TARGET_MEM_REF)
      return op;
    return NULL_TREE;
--- 4325,4331 ----
    while (handled_component_p (op))
      op = TREE_OPERAND (op, 0);
    if (DECL_P (op)
!       || TREE_CODE (op) == MEM_REF
        || TREE_CODE (op) == TARGET_MEM_REF)
      return op;
    return NULL_TREE;
Index: trunk/gcc/gimplify.c
===================================================================
*** trunk.orig/gcc/gimplify.c	2010-03-08 10:32:38.000000000 +0100
--- trunk/gcc/gimplify.c	2010-03-09 17:03:36.000000000 +0100
*************** gimplify_init_ctor_preeval_1 (tree *tp,
*** 3211,3223 ****
    /* If the constructor component is indirect, determine if we have a
       potential overlap with the lhs.  The only bits of information we
       have to go on at this point are addressability and alias sets.  */
!   if (TREE_CODE (t) == INDIRECT_REF
        && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
        && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
      return t;
  
    /* If the constructor component is a call, determine if it can hide a
!      potential overlap with the lhs through an INDIRECT_REF like above.  */
    if (TREE_CODE (t) == CALL_EXPR)
      {
        tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
--- 3211,3226 ----
    /* If the constructor component is indirect, determine if we have a
       potential overlap with the lhs.  The only bits of information we
       have to go on at this point are addressability and alias sets.  */
!   if ((INDIRECT_REF_P (t)
!        || TREE_CODE (t) == MEM_REF)
        && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
        && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
      return t;
  
    /* If the constructor component is a call, determine if it can hide a
!      potential overlap with the lhs through an INDIRECT_REF like above.
!      ??? Ugh - this is completely broken.  In fact this whole analysis
!      doesn't look conservative.  */
    if (TREE_CODE (t) == CALL_EXPR)
      {
        tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
*************** gimplify_init_constructor (tree *expr_p,
*** 3957,3963 ****
  tree
  gimple_fold_indirect_ref (tree t)
  {
!   tree type = TREE_TYPE (TREE_TYPE (t));
    tree sub = t;
    tree subtype;
  
--- 3960,3966 ----
  tree
  gimple_fold_indirect_ref (tree t)
  {
!   tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype);
    tree sub = t;
    tree subtype;
  
*************** gimple_fold_indirect_ref (tree t)
*** 4000,4050 ****
          }
      }
  
!   /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
    if (TREE_CODE (sub) == POINTER_PLUS_EXPR
        && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
      {
!       tree op00 = TREE_OPERAND (sub, 0);
!       tree op01 = TREE_OPERAND (sub, 1);
!       tree op00type;
! 
!       STRIP_NOPS (op00);
!       op00type = TREE_TYPE (op00);
!       if (TREE_CODE (op00) == ADDR_EXPR
! 	  && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
! 	  && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
! 	{
! 	  HOST_WIDE_INT offset = tree_low_cst (op01, 0);
! 	  tree part_width = TYPE_SIZE (type);
! 	  unsigned HOST_WIDE_INT part_widthi
! 	    = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
! 	  unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
! 	  tree index = bitsize_int (indexi);
! 	  if (offset / part_widthi
! 	      <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
! 	    return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
! 				part_width, index);
! 	}
!     }
! 
!   /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
!   if (TREE_CODE (sub) == POINTER_PLUS_EXPR
!       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
!     {
!       tree op00 = TREE_OPERAND (sub, 0);
!       tree op01 = TREE_OPERAND (sub, 1);
!       tree op00type;
! 
!       STRIP_NOPS (op00);
!       op00type = TREE_TYPE (op00);
!       if (TREE_CODE (op00) == ADDR_EXPR
! 	  && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
! 	  && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
! 	{
! 	  tree size = TYPE_SIZE_UNIT (type);
! 	  if (tree_int_cst_equal (size, op01))
! 	    return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
! 	}
      }
  
    /* *(foo *)fooarrptr => (*fooarrptr)[0] */
--- 4003,4022 ----
          }
      }
  
!   /* *(p + CST) -> MEM_REF <p, CST>.  */
    if (TREE_CODE (sub) == POINTER_PLUS_EXPR
        && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
      {
!       tree addr = TREE_OPERAND (sub, 0);
!       tree off = TREE_OPERAND (sub, 1);
!       STRIP_NOPS (addr);
!       if (TREE_CODE (addr) != ADDR_EXPR
! 	  || DECL_P (TREE_OPERAND (addr, 0)))
! 	return fold_build2 (MEM_REF, type,
! 			    addr,
! 			    build_int_cst_wide (ptype,
! 						TREE_INT_CST_LOW (off),
! 						TREE_INT_CST_HIGH (off)));
      }
  
    /* *(foo *)fooarrptr => (*fooarrptr)[0] */
*************** gimplify_expr (tree *expr_p, gimple_seq
*** 6669,6684 ****
  	  recalculate_side_effects (*expr_p);
  	  break;
  
- 	case INDIRECT_REF:
- 	  *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
- 	  if (*expr_p != save_expr)
- 	    break;
- 	  /* else fall through.  */
  	case ALIGN_INDIRECT_REF:
  	case MISALIGNED_INDIRECT_REF:
  	  ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 			       is_gimple_reg, fb_rvalue);
! 	  recalculate_side_effects (*expr_p);
  	  break;
  
  	  /* Constants need not be gimplified.  */
--- 6641,6674 ----
  	  recalculate_side_effects (*expr_p);
  	  break;
  
  	case ALIGN_INDIRECT_REF:
  	case MISALIGNED_INDIRECT_REF:
+ 	  gcc_unreachable ();
+ 
+ 	case INDIRECT_REF:
+ 	  {
+ 	    bool volatilep = TREE_THIS_VOLATILE (*expr_p);
+ 	    tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
+ 
+ 	    *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
+ 	    if (*expr_p != save_expr)
+ 	      break;
+ 
+ 	    ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+ 				 is_gimple_reg, fb_rvalue);
+ 	    recalculate_side_effects (*expr_p);
+ 
+ 	    *expr_p = fold_build2_loc (input_location, MEM_REF,
+ 				       TREE_TYPE (*expr_p),
+ 				       TREE_OPERAND (*expr_p, 0),
+ 				       build_int_cst (saved_ptr_type, 0));
+ 	    TREE_THIS_VOLATILE (*expr_p) = volatilep;
+ 	    break;
+ 	  }
+ 
+ 	case MEM_REF:
  	  ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 			       is_gimple_val, fb_rvalue);
  	  break;
  
  	  /* Constants need not be gimplified.  */
Index: trunk/gcc/tree-cfg.c
===================================================================
*** trunk.orig/gcc/tree-cfg.c	2010-03-08 10:32:38.000000000 +0100
--- trunk/gcc/tree-cfg.c	2010-03-09 12:04:39.000000000 +0100
*************** verify_expr (tree *tp, int *walk_subtree
*** 2596,2601 ****
--- 2596,2617 ----
  	}
        break;
  
+     case MEM_REF:
+       x = TREE_OPERAND (t, 0);
+       if (!is_gimple_reg (x) && !is_gimple_min_invariant (x))
+ 	{
+ 	  error ("MEM_REFs operand is not a register or a constant.");
+ 	  return x;
+ 	}
+       if (TREE_CODE (x) == ADDR_EXPR
+ 	  && !DECL_P (TREE_OPERAND (x, 0))
+ 	  && !CONSTANT_CLASS_P (TREE_OPERAND (x, 0)))
+ 	{
+ 	  error ("Invalid address operand of MEM_REF.");
+ 	  return x;
+ 	}
+       break;
+ 
      case ASSERT_EXPR:
        x = fold (ASSERT_EXPR_COND (t));
        if (x == boolean_false_node)
*************** verify_expr (tree *tp, int *walk_subtree
*** 2648,2658 ****
--- 2664,2677 ----
  	      || TREE_CODE (x) == PARM_DECL
  	      || TREE_CODE (x) == RESULT_DECL))
  	  return NULL;
+ #if 0
+ 	/* FIXME.  */
  	if (!TREE_ADDRESSABLE (x))
  	  {
  	    error ("address taken, but ADDRESSABLE bit not set");
  	    return x;
  	  }
+ #endif
  	if (DECL_GIMPLE_REG_P (x))
  	  {
  	    error ("DECL_GIMPLE_REG_P set on a variable with address taken");
*************** verify_types_in_gimple_min_lval (tree ex
*** 2842,2849 ****
    if (is_gimple_id (expr))
      return false;
  
!   if (!INDIRECT_REF_P (expr)
!       && TREE_CODE (expr) != TARGET_MEM_REF)
      {
        error ("invalid expression for min lvalue");
        return true;
--- 2861,2868 ----
    if (is_gimple_id (expr))
      return false;
  
!   if (TREE_CODE (expr) != TARGET_MEM_REF
!       && TREE_CODE (expr) != MEM_REF)
      {
        error ("invalid expression for min lvalue");
        return true;
*************** verify_types_in_gimple_min_lval (tree ex
*** 2860,2865 ****
--- 2879,2885 ----
        debug_generic_stmt (op);
        return true;
      }
+ #if 0
    if (!useless_type_conversion_p (TREE_TYPE (expr),
  				  TREE_TYPE (TREE_TYPE (op))))
      {
*************** verify_types_in_gimple_min_lval (tree ex
*** 2868,2873 ****
--- 2888,2894 ----
        debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
        return true;
      }
+ #endif
  
    return false;
  }
*************** verify_types_in_gimple_reference (tree e
*** 2961,2966 ****
--- 2982,3008 ----
        expr = op;
      }
  
+   if (TREE_CODE (expr) == MEM_REF)
+     {
+       if (!is_gimple_val (TREE_OPERAND (expr, 0))
+ 	  || TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST
+ 	  || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
+ 	{
+ 	  error ("Invalid operands in MEM_REF.");
+ 	  debug_generic_stmt (expr);
+ 	  return true;
+ 	}
+       if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR
+ 	  && !DECL_P (TREE_OPERAND (TREE_OPERAND (expr, 0), 0))
+ 	  /* ???  FIXME.  We should always fold these.  */
+ 	  && !CONSTANT_CLASS_P (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
+ 	{
+ 	  error ("Invalid address operand for MEM_REF.");
+ 	  debug_generic_stmt (expr);
+ 	  return true;
+ 	}
+     }
+ 
    return ((require_lvalue || !is_gimple_min_invariant (expr))
  	  && verify_types_in_gimple_min_lval (expr));
  }
*************** verify_gimple_assign_single (gimple stmt
*** 3605,3621 ****
        }
  
      /* tcc_reference  */
-     case COMPONENT_REF:
-     case BIT_FIELD_REF:
      case INDIRECT_REF:
      case ALIGN_INDIRECT_REF:
      case MISALIGNED_INDIRECT_REF:
      case ARRAY_REF:
      case ARRAY_RANGE_REF:
      case VIEW_CONVERT_EXPR:
      case REALPART_EXPR:
      case IMAGPART_EXPR:
      case TARGET_MEM_REF:
        if (!is_gimple_reg (lhs)
  	  && is_gimple_reg_type (TREE_TYPE (lhs)))
  	{
--- 3647,3667 ----
        }
  
      /* tcc_reference  */
      case INDIRECT_REF:
      case ALIGN_INDIRECT_REF:
      case MISALIGNED_INDIRECT_REF:
+       error ("INDIRECT_REF in gimple IL");
+       return true;
+ 
+     case COMPONENT_REF:
+     case BIT_FIELD_REF:
      case ARRAY_REF:
      case ARRAY_RANGE_REF:
      case VIEW_CONVERT_EXPR:
      case REALPART_EXPR:
      case IMAGPART_EXPR:
      case TARGET_MEM_REF:
+     case MEM_REF:
        if (!is_gimple_reg (lhs)
  	  && is_gimple_reg_type (TREE_TYPE (lhs)))
  	{
Index: trunk/gcc/tree-flow.h
===================================================================
*** trunk.orig/gcc/tree-flow.h	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-flow.h	2010-03-08 16:22:53.000000000 +0100
*************** void release_ssa_name_after_update_ssa (
*** 599,604 ****
--- 599,605 ----
  void compute_global_livein (bitmap, bitmap);
  void mark_sym_for_renaming (tree);
  void mark_set_for_renaming (bitmap);
+ bool symbol_marked_for_renaming (tree);
  tree get_current_def (tree);
  void set_current_def (tree, tree);
  
Index: trunk/gcc/tree-into-ssa.c
===================================================================
*** trunk.orig/gcc/tree-into-ssa.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-into-ssa.c	2010-03-08 16:22:53.000000000 +0100
*************** set_livein_block (tree var, basic_block
*** 561,567 ****
  
  /* Return true if symbol SYM is marked for renaming.  */
  
! static inline bool
  symbol_marked_for_renaming (tree sym)
  {
    return bitmap_bit_p (SYMS_TO_RENAME (cfun), DECL_UID (sym));
--- 561,567 ----
  
  /* Return true if symbol SYM is marked for renaming.  */
  
! bool
  symbol_marked_for_renaming (tree sym)
  {
    return bitmap_bit_p (SYMS_TO_RENAME (cfun), DECL_UID (sym));
Index: trunk/gcc/tree-pretty-print.c
===================================================================
*** trunk.orig/gcc/tree-pretty-print.c	2010-03-08 11:32:57.000000000 +0100
--- trunk/gcc/tree-pretty-print.c	2010-03-09 11:40:31.000000000 +0100
*************** dump_generic_node (pretty_printer *buffe
*** 786,791 ****
--- 786,815 ----
        NIY;
        break;
  
+     case MEM_REF:
+       {
+ 	if (0 && integer_zerop (TREE_OPERAND (node, 1)))
+ 	  {
+ 	    pp_string (buffer, "*");
+ 	    dump_generic_node (buffer, TREE_OPERAND (node, 0),
+ 			       spc, flags, false);
+ 	  }
+ 	else
+ 	  {
+ 	    pp_string (buffer, "MEM[");
+ 	    pp_string (buffer, "(");
+ 	    dump_generic_node (buffer, TREE_TYPE (TREE_OPERAND (node, 1)),
+ 			       spc, flags, false);
+ 	    pp_string (buffer, ")");
+ 	    dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+ 	    pp_string (buffer, " + ");
+ 	    dump_generic_node (buffer, TREE_OPERAND (node, 1),
+ 			       spc, flags, false);
+ 	    pp_string (buffer, "]");
+ 	  }
+ 	break;
+       }
+ 
      case TARGET_MEM_REF:
        {
  	const char *sep = "";
*************** dump_generic_node (pretty_printer *buffe
*** 1092,1098 ****
      case COMPONENT_REF:
        op0 = TREE_OPERAND (node, 0);
        str = ".";
!       if (op0 && TREE_CODE (op0) == INDIRECT_REF)
  	{
  	  op0 = TREE_OPERAND (op0, 0);
  	  str = "->";
--- 1116,1125 ----
      case COMPONENT_REF:
        op0 = TREE_OPERAND (node, 0);
        str = ".";
!       if (op0
! 	  && (TREE_CODE (op0) == INDIRECT_REF
! 	      || (0 && TREE_CODE (op0) == MEM_REF
! 		  && integer_zerop (TREE_OPERAND (op0, 1)))))
  	{
  	  op0 = TREE_OPERAND (op0, 0);
  	  str = "->";
Index: trunk/gcc/tree-ssa-alias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-alias.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-ssa-alias.c	2010-03-09 13:25:34.000000000 +0100
*************** ptr_deref_may_alias_decl_p (tree ptr, tr
*** 185,191 ****
      {
        tree base = get_base_address (TREE_OPERAND (ptr, 0));
        if (base
! 	  && INDIRECT_REF_P (base))
  	ptr = TREE_OPERAND (base, 0);
        else if (base
  	       && SSA_VAR_P (base))
--- 185,191 ----
      {
        tree base = get_base_address (TREE_OPERAND (ptr, 0));
        if (base
! 	  && TREE_CODE (base) == MEM_REF)
  	ptr = TREE_OPERAND (base, 0);
        else if (base
  	       && SSA_VAR_P (base))
*************** ptr_derefs_may_alias_p (tree ptr1, tree
*** 241,247 ****
      {
        tree base = get_base_address (TREE_OPERAND (ptr1, 0));
        if (base
! 	  && INDIRECT_REF_P (base))
  	ptr1 = TREE_OPERAND (base, 0);
        else if (base
  	       && SSA_VAR_P (base))
--- 241,247 ----
      {
        tree base = get_base_address (TREE_OPERAND (ptr1, 0));
        if (base
! 	  && TREE_CODE (base) == MEM_REF)
  	ptr1 = TREE_OPERAND (base, 0);
        else if (base
  	       && SSA_VAR_P (base))
*************** ptr_derefs_may_alias_p (tree ptr1, tree
*** 253,259 ****
      {
        tree base = get_base_address (TREE_OPERAND (ptr2, 0));
        if (base
! 	  && INDIRECT_REF_P (base))
  	ptr2 = TREE_OPERAND (base, 0);
        else if (base
  	       && SSA_VAR_P (base))
--- 253,259 ----
      {
        tree base = get_base_address (TREE_OPERAND (ptr2, 0));
        if (base
! 	  && TREE_CODE (base) == MEM_REF)
  	ptr2 = TREE_OPERAND (base, 0);
        else if (base
  	       && SSA_VAR_P (base))
*************** ptr_deref_may_alias_ref_p_1 (tree ptr, a
*** 302,308 ****
  {
    tree base = ao_ref_base (ref);
  
!   if (INDIRECT_REF_P (base))
      return ptr_derefs_may_alias_p (ptr, TREE_OPERAND (base, 0));
    else if (SSA_VAR_P (base))
      return ptr_deref_may_alias_decl_p (ptr, base);
--- 302,308 ----
  {
    tree base = ao_ref_base (ref);
  
!   if (TREE_CODE (base) == MEM_REF)
      return ptr_derefs_may_alias_p (ptr, TREE_OPERAND (base, 0));
    else if (SSA_VAR_P (base))
      return ptr_deref_may_alias_decl_p (ptr, base);
*************** ao_ref_init_from_ptr_and_size (ao_ref *r
*** 505,511 ****
  					 &ref->offset, &t1, &t2);
    else
      {
!       ref->base = build1 (INDIRECT_REF, char_type_node, ptr);
        ref->offset = 0;
      }
    if (size
--- 505,512 ----
  					 &ref->offset, &t1, &t2);
    else
      {
!       ref->base = build2 (MEM_REF, char_type_node,
! 			  ptr, build_int_cst (ptr_type_node, 0));
        ref->offset = 0;
      }
    if (size
*************** refs_may_alias_p_1 (ao_ref *ref1, ao_ref
*** 775,787 ****
    gcc_assert ((!ref1->ref
  	       || SSA_VAR_P (ref1->ref)
  	       || handled_component_p (ref1->ref)
! 	       || INDIRECT_REF_P (ref1->ref)
  	       || TREE_CODE (ref1->ref) == TARGET_MEM_REF
  	       || TREE_CODE (ref1->ref) == CONST_DECL)
  	      && (!ref2->ref
  		  || SSA_VAR_P (ref2->ref)
  		  || handled_component_p (ref2->ref)
! 		  || INDIRECT_REF_P (ref2->ref)
  		  || TREE_CODE (ref2->ref) == TARGET_MEM_REF
  		  || TREE_CODE (ref2->ref) == CONST_DECL));
  
--- 776,788 ----
    gcc_assert ((!ref1->ref
  	       || SSA_VAR_P (ref1->ref)
  	       || handled_component_p (ref1->ref)
! 	       || TREE_CODE (ref1->ref) == MEM_REF
  	       || TREE_CODE (ref1->ref) == TARGET_MEM_REF
  	       || TREE_CODE (ref1->ref) == CONST_DECL)
  	      && (!ref2->ref
  		  || SSA_VAR_P (ref2->ref)
  		  || handled_component_p (ref2->ref)
! 		  || TREE_CODE (ref2->ref) == MEM_REF
  		  || TREE_CODE (ref2->ref) == TARGET_MEM_REF
  		  || TREE_CODE (ref2->ref) == CONST_DECL));
  
*************** refs_may_alias_p_1 (ao_ref *ref1, ao_ref
*** 820,827 ****
      return decl_refs_may_alias_p (base1, offset1, max_size1,
  				  base2, offset2, max_size2);
  
!   ind1_p = INDIRECT_REF_P (base1);
!   ind2_p = INDIRECT_REF_P (base2);
    /* Canonicalize the pointer-vs-decl case.  */
    if (ind1_p && var2_p)
      {
--- 821,833 ----
      return decl_refs_may_alias_p (base1, offset1, max_size1,
  				  base2, offset2, max_size2);
  
!   ind1_p = (TREE_CODE (base1) == MEM_REF);
!   ind2_p = (TREE_CODE (base2) == MEM_REF);
!   if (ind1_p)
!     offset1 += TREE_INT_CST_LOW (TREE_OPERAND (base1, 1)) * BITS_PER_UNIT;
!   if (ind2_p)
!     offset2 += TREE_INT_CST_LOW (TREE_OPERAND (base2, 1)) * BITS_PER_UNIT;
! 
    /* Canonicalize the pointer-vs-decl case.  */
    if (ind1_p && var2_p)
      {
*************** refs_may_alias_p_1 (ao_ref *ref1, ao_ref
*** 909,922 ****
    set = tbaa_p ? -1 : 0;
    if (var1_p && ind2_p)
      return indirect_ref_may_alias_decl_p (ref2->ref, TREE_OPERAND (base2, 0),
! 					  offset2, max_size2, set,
  					  ref1->ref, base1,
  					  offset1, max_size1, set);
    else if (ind1_p && ind2_p)
      return indirect_refs_may_alias_p (ref1->ref, TREE_OPERAND (base1, 0),
! 				      offset1, max_size1, set,
  				      ref2->ref, TREE_OPERAND (base2, 0),
! 				      offset2, max_size2, set);
  
    gcc_unreachable ();
  }
--- 915,931 ----
    set = tbaa_p ? -1 : 0;
    if (var1_p && ind2_p)
      return indirect_ref_may_alias_decl_p (ref2->ref, TREE_OPERAND (base2, 0),
! 					  offset2, max_size2,
! 					  tbaa_p ? ao_ref_base_alias_set (ref2) : 0,
  					  ref1->ref, base1,
  					  offset1, max_size1, set);
    else if (ind1_p && ind2_p)
      return indirect_refs_may_alias_p (ref1->ref, TREE_OPERAND (base1, 0),
! 				      offset1, max_size1,
! 				      tbaa_p ? ao_ref_base_alias_set (ref1) : 0,
  				      ref2->ref, TREE_OPERAND (base2, 0),
! 				      offset2, max_size2,
! 				      tbaa_p ? ao_ref_base_alias_set (ref2) : 0);
  
    gcc_unreachable ();
  }
*************** ref_maybe_used_by_call_p_1 (gimple call,
*** 1079,1085 ****
  	  if (is_call_used (base))
  	    return true;
  	}
!       else if (INDIRECT_REF_P (base)
  	       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
  	{
  	  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
--- 1088,1094 ----
  	  if (is_call_used (base))
  	    return true;
  	}
!       else if (TREE_CODE (base) == MEM_REF
  	       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
  	{
  	  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
*************** ref_maybe_used_by_call_p_1 (gimple call,
*** 1101,1107 ****
  	  if (is_call_clobbered (base))
  	    return true;
  	}
!       else if (INDIRECT_REF_P (base)
  	       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
  	{
  	  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
--- 1110,1116 ----
  	  if (is_call_clobbered (base))
  	    return true;
  	}
!       else if (TREE_CODE (base) == MEM_REF
  	       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
  	{
  	  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
*************** call_may_clobber_ref_p_1 (gimple call, a
*** 1270,1276 ****
  	      if (DECL_P (base)
  		  && !TREE_STATIC (base))
  		return true;
! 	      else if (INDIRECT_REF_P (base)
  		       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
  		       && (pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0))))
  		return pi->pt.anything || pi->pt.nonlocal;
--- 1279,1285 ----
  	      if (DECL_P (base)
  		  && !TREE_STATIC (base))
  		return true;
! 	      else if (TREE_CODE (base) == MEM_REF
  		       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
  		       && (pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0))))
  		return pi->pt.anything || pi->pt.nonlocal;
*************** call_may_clobber_ref_p_1 (gimple call, a
*** 1349,1355 ****
  
    if (DECL_P (base))
      return is_call_clobbered (base);
!   else if (INDIRECT_REF_P (base)
  	   && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
      {
        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
--- 1358,1364 ----
  
    if (DECL_P (base))
      return is_call_clobbered (base);
!   else if (TREE_CODE (base) == MEM_REF
  	   && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
      {
        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
Index: trunk/gcc/tree-ssa-loop-im.c
===================================================================
*** trunk.orig/gcc/tree-ssa-loop-im.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-ssa-loop-im.c	2010-03-09 12:22:19.000000000 +0100
*************** for_each_index (tree *addr_p, bool (*cbc
*** 274,284 ****
  	case SSA_NAME:
  	  return cbck (*addr_p, addr_p, data);
  
! 	case MISALIGNED_INDIRECT_REF:
! 	case ALIGN_INDIRECT_REF:
! 	case INDIRECT_REF:
! 	  nxt = &TREE_OPERAND (*addr_p, 0);
! 	  return cbck (*addr_p, nxt, data);
  
  	case BIT_FIELD_REF:
  	case VIEW_CONVERT_EXPR:
--- 274,281 ----
  	case SSA_NAME:
  	  return cbck (*addr_p, addr_p, data);
  
! 	case MEM_REF:
! 	  return cbck (*addr_p, &TREE_OPERAND (*addr_p, 0), data);
  
  	case BIT_FIELD_REF:
  	case VIEW_CONVERT_EXPR:
*************** gen_lsm_tmp_name (tree ref)
*** 1750,1759 ****
--- 1747,1761 ----
      case MISALIGNED_INDIRECT_REF:
      case ALIGN_INDIRECT_REF:
      case INDIRECT_REF:
+     case MEM_REF:
        gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
        lsm_tmp_name_add ("_");
        break;
  
+     case ADDR_EXPR:
+       gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+       break;
+ 
      case BIT_FIELD_REF:
      case VIEW_CONVERT_EXPR:
      case ARRAY_RANGE_REF:
Index: trunk/gcc/tree-ssa-loop-ivopts.c
===================================================================
*** trunk.orig/gcc/tree-ssa-loop-ivopts.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-ssa-loop-ivopts.c	2010-03-08 16:22:53.000000000 +0100
*************** determine_base_object (tree expr)
*** 806,812 ****
        if (!base)
  	return expr;
  
!       if (TREE_CODE (base) == INDIRECT_REF)
  	return determine_base_object (TREE_OPERAND (base, 0));
  
        return fold_convert (ptr_type_node,
--- 806,812 ----
        if (!base)
  	return expr;
  
!       if (TREE_CODE (base) == MEM_REF)
  	return determine_base_object (TREE_OPERAND (base, 0));
  
        return fold_convert (ptr_type_node,
*************** strip_offset_1 (tree expr, bool inside_a
*** 2009,2015 ****
        expr = build_fold_addr_expr (op0);
        return fold_convert (orig_type, expr);
  
!     case INDIRECT_REF:
        inside_addr = false;
        break;
  
--- 2009,2016 ----
        expr = build_fold_addr_expr (op0);
        return fold_convert (orig_type, expr);
  
!     case MEM_REF:
!       /* ???  Offset operand?  */
        inside_addr = false;
        break;
  
*************** tree_ssa_iv_optimize (void)
*** 5852,5857 ****
--- 5853,5860 ----
    struct ivopts_data data;
    loop_iterator li;
  
+   return;
+ 
    tree_ssa_iv_optimize_init (&data);
  
    /* Optimize the loops starting with the innermost ones.  */
Index: trunk/gcc/tree-ssa-operands.c
===================================================================
*** trunk.orig/gcc/tree-ssa-operands.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-ssa-operands.c	2010-03-09 15:15:16.000000000 +0100
*************** static struct
*** 126,131 ****
--- 126,137 ----
     clobbering sites like function calls or ASM_EXPRs.  */
  #define opf_implicit	(1 << 2)
  
+ /* Operand is in a place where address-taken does not imply addressable.  */
+ #define opf_non_addressable (1 << 3)
+ 
+ /* Operand is in a place where opf_non_addressable does not apply.  */
+ #define opf_not_non_addressable (1 << 4)
+ 
  /* Array for building all the def operands.  */
  static VEC(tree,heap) *build_defs;
  
*************** mark_address_taken (tree ref)
*** 691,698 ****
       be referenced using pointer arithmetic.  See PR 21407 and the
       ensuing mailing list discussion.  */
    var = get_base_address (ref);
!   if (var && DECL_P (var))
!     TREE_ADDRESSABLE (var) = 1;
  }
  
  
--- 697,711 ----
       be referenced using pointer arithmetic.  See PR 21407 and the
       ensuing mailing list discussion.  */
    var = get_base_address (ref);
!   if (var)
!     {
!       if (DECL_P (var))
! 	TREE_ADDRESSABLE (var) = 1;
!       else if (TREE_CODE (var) == MEM_REF
! 	       && TREE_CODE (TREE_OPERAND (var, 0)) == ADDR_EXPR
! 	       && DECL_P (TREE_OPERAND (TREE_OPERAND (var, 0), 0)))
! 	TREE_ADDRESSABLE (TREE_OPERAND (TREE_OPERAND (var, 0), 0)) = 1;
!     }
  }
  
  
*************** get_indirect_ref_operands (gimple stmt,
*** 723,729 ****
    /* If requested, add a USE operand for the base pointer.  */
    if (recurse_on_base)
      get_expr_operands (stmt, pptr,
! 		       opf_use | (flags & opf_no_vops));
  }
  
  
--- 736,742 ----
    /* If requested, add a USE operand for the base pointer.  */
    if (recurse_on_base)
      get_expr_operands (stmt, pptr,
! 		       opf_non_addressable | opf_use | (flags & opf_no_vops));
  }
  
  
*************** get_asm_expr_operands (gimple stmt)
*** 795,805 ****
        /* Memory operands are addressable.  Note that STMT needs the
  	 address of this operand.  */
        if (!allows_reg && allows_mem)
! 	{
! 	  tree t = get_base_address (TREE_VALUE (link));
! 	  if (t && DECL_P (t))
! 	    mark_address_taken (t);
! 	}
  
        get_expr_operands (stmt, &TREE_VALUE (link), opf_def);
      }
--- 808,814 ----
        /* Memory operands are addressable.  Note that STMT needs the
  	 address of this operand.  */
        if (!allows_reg && allows_mem)
! 	mark_address_taken (TREE_VALUE (link));
  
        get_expr_operands (stmt, &TREE_VALUE (link), opf_def);
      }
*************** get_asm_expr_operands (gimple stmt)
*** 815,825 ****
        /* Memory operands are addressable.  Note that STMT needs the
  	 address of this operand.  */
        if (!allows_reg && allows_mem)
! 	{
! 	  tree t = get_base_address (TREE_VALUE (link));
! 	  if (t && DECL_P (t))
! 	    mark_address_taken (t);
! 	}
  
        get_expr_operands (stmt, &TREE_VALUE (link), 0);
      }
--- 824,830 ----
        /* Memory operands are addressable.  Note that STMT needs the
  	 address of this operand.  */
        if (!allows_reg && allows_mem)
! 	mark_address_taken (TREE_VALUE (link));
  
        get_expr_operands (stmt, &TREE_VALUE (link), 0);
      }
*************** get_expr_operands (gimple stmt, tree *ex
*** 865,871 ****
  	 reference to it, but the fact that the statement takes its
  	 address will be of interest to some passes (e.g. alias
  	 resolution).  */
!       if (!is_gimple_debug (stmt))
  	mark_address_taken (TREE_OPERAND (expr, 0));
  
        /* If the address is invariant, there may be no interesting
--- 870,878 ----
  	 reference to it, but the fact that the statement takes its
  	 address will be of interest to some passes (e.g. alias
  	 resolution).  */
!       if ((!(flags & opf_non_addressable)
! 	   || (flags & opf_not_non_addressable))
! 	  && !is_gimple_debug (stmt))
  	mark_address_taken (TREE_OPERAND (expr, 0));
  
        /* If the address is invariant, there may be no interesting
*************** get_expr_operands (gimple stmt, tree *ex
*** 879,885 ****
  	 here are ARRAY_REF indices which will always be real operands
  	 (GIMPLE does not allow non-registers as array indices).  */
        flags |= opf_no_vops;
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
        return;
  
      case SSA_NAME:
--- 886,893 ----
  	 here are ARRAY_REF indices which will always be real operands
  	 (GIMPLE does not allow non-registers as array indices).  */
        flags |= opf_no_vops;
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0),
! 			 flags | opf_not_non_addressable);
        return;
  
      case SSA_NAME:
*************** get_expr_operands (gimple stmt, tree *ex
*** 896,907 ****
        gcc_assert (gimple_debug_bind_p (stmt));
        return;
  
!     case MISALIGNED_INDIRECT_REF:
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
!       /* fall through */
! 
!     case ALIGN_INDIRECT_REF:
!     case INDIRECT_REF:
        get_indirect_ref_operands (stmt, expr, flags, true);
        return;
  
--- 904,910 ----
        gcc_assert (gimple_debug_bind_p (stmt));
        return;
  
!     case MEM_REF:
        get_indirect_ref_operands (stmt, expr, flags, true);
        return;
  
Index: trunk/gcc/tree-ssa-pre.c
===================================================================
*** trunk.orig/gcc/tree-ssa-pre.c	2010-03-08 16:13:31.000000000 +0100
--- trunk/gcc/tree-ssa-pre.c	2010-03-08 16:36:23.000000000 +0100
*************** create_component_ref_by_pieces_1 (basic_
*** 2679,2684 ****
--- 2679,2693 ----
  	return folded;
        }
        break;
+     case MEM_REF:
+       {
+ 	tree baseop = create_component_ref_by_pieces_1 (block, ref, operand,
+ 							stmts, domstmt);
+ 	if (!baseop)
+ 	  return NULL_TREE;
+ 	return build2 (MEM_REF, currop->type, baseop, currop->op0);
+       }
+       break;
      case TARGET_MEM_REF:
        {
  	vn_reference_op_t nextop = VEC_index (vn_reference_op_s, ref->operands,
Index: trunk/gcc/tree-ssa-sccvn.c
===================================================================
*** trunk.orig/gcc/tree-ssa-sccvn.c	2010-03-08 16:13:31.000000000 +0100
--- trunk/gcc/tree-ssa-sccvn.c	2010-03-08 16:36:45.000000000 +0100
*************** copy_reference_ops_from_ref (tree ref, V
*** 528,539 ****
  
        switch (temp.opcode)
  	{
! 	case ALIGN_INDIRECT_REF:
! 	case INDIRECT_REF:
! 	  /* The only operand is the address, which gets its own
! 	     vn_reference_op_s structure.  */
! 	  break;
! 	case MISALIGNED_INDIRECT_REF:
  	  temp.op0 = TREE_OPERAND (ref, 1);
  	  break;
  	case BIT_FIELD_REF:
--- 528,535 ----
  
        switch (temp.opcode)
  	{
! 	case MEM_REF:
! 	  /* The base address gets its own vn_reference_op_s structure.  */
  	  temp.op0 = TREE_OPERAND (ref, 1);
  	  break;
  	case BIT_FIELD_REF:
Index: trunk/gcc/tree-ssa-sink.c
===================================================================
*** trunk.orig/gcc/tree-ssa-sink.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-ssa-sink.c	2010-03-08 16:22:53.000000000 +0100
*************** is_hidden_global_store (gimple stmt)
*** 192,198 ****
  	    return true;
  
  	}
!       else if (INDIRECT_REF_P (lhs))
  	return ptr_deref_may_alias_global_p (TREE_OPERAND (lhs, 0));
        else
  	gcc_unreachable ();
--- 192,198 ----
  	    return true;
  
  	}
!       else if (TREE_CODE (lhs) == MEM_REF)
  	return ptr_deref_may_alias_global_p (TREE_OPERAND (lhs, 0));
        else
  	gcc_unreachable ();
Index: trunk/gcc/tree-ssa.c
===================================================================
*** trunk.orig/gcc/tree-ssa.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-ssa.c	2010-03-08 16:47:10.000000000 +0100
*************** useless_type_conversion_p (tree outer_ty
*** 1291,1318 ****
  	  && TYPE_VOLATILE (TREE_TYPE (outer_type)))
  	return false;
  
!       /* We require explicit conversions from incomplete target types.  */
!       if (!COMPLETE_TYPE_P (TREE_TYPE (inner_type))
! 	  && COMPLETE_TYPE_P (TREE_TYPE (outer_type)))
! 	return false;
! 
!       /* Do not lose casts between pointers that when dereferenced access
! 	 memory with different alias sets.  */
!       if (get_deref_alias_set (inner_type) != get_deref_alias_set (outer_type))
  	return false;
  
        /* We do not care for const qualification of the pointed-to types
  	 as const qualification has no semantic value to the middle-end.  */
  
!       /* Otherwise pointers/references are equivalent if their pointed
! 	 to types are effectively the same.  We can strip qualifiers
! 	 on pointed-to types for further comparison, which is done in
! 	 the callee.  Note we have to use true compatibility here
! 	 because addresses are subject to propagation into dereferences
! 	 and thus might get the original type exposed which is equivalent
! 	 to a reverse conversion.  */
!       return types_compatible_p (TREE_TYPE (outer_type),
! 				 TREE_TYPE (inner_type));
      }
  
    /* Recurse for complex types.  */
--- 1291,1308 ----
  	  && TYPE_VOLATILE (TREE_TYPE (outer_type)))
  	return false;
  
!       /* Do not lose casts to function pointer types.  */
!       if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
! 	   || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
! 	  && !useless_type_conversion_p (TREE_TYPE (outer_type),
! 					 TREE_TYPE (inner_type)))
  	return false;
  
        /* We do not care for const qualification of the pointed-to types
  	 as const qualification has no semantic value to the middle-end.  */
  
!       /* Otherwise pointers/references are equivalent.  */
!       return true;
      }
  
    /* Recurse for complex types.  */
*************** execute_update_addresses_taken (bool do_
*** 1933,1949 ****
  	    {
                tree lhs = gimple_get_lhs (stmt);
  
!               /* We may not rewrite TMR_SYMBOL to SSA.  */
!               if (lhs && TREE_CODE (lhs) == TARGET_MEM_REF
!                   && TMR_SYMBOL (lhs))
!                 bitmap_set_bit (not_reg_needs, DECL_UID (TMR_SYMBOL (lhs)));
  
                /* A plain decl does not need it set.  */
!               else if (lhs && handled_component_p (lhs))
!                 {
!                   var = get_base_address (lhs);
!                   if (DECL_P (var))
!                     bitmap_set_bit (not_reg_needs, DECL_UID (var));
                  }
  	    }
  	}
--- 1923,1960 ----
  	    {
                tree lhs = gimple_get_lhs (stmt);
  
!               /* A plain decl does not need it set.  */
!               if (lhs && !DECL_P (lhs))
! 		{
! 		  if (handled_component_p (lhs))
! 		    lhs = get_base_address (lhs);
! 
!                   if (DECL_P (lhs))
!                     bitmap_set_bit (not_reg_needs, DECL_UID (lhs));
! 		  else if (TREE_CODE (lhs) == MEM_REF
! 			   && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR
! 			   && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs, 0), 0))
! 			   && !integer_zerop (TREE_OPERAND (lhs, 1)))
! 		    bitmap_set_bit (not_reg_needs, DECL_UID (TREE_OPERAND (TREE_OPERAND (lhs, 0), 0)));
!                 }
! 	    }
! 
! 	  if (gimple_assign_single_p (stmt))
! 	    {
! 	      tree rhs = gimple_assign_rhs1 (stmt);
  
                /* A plain decl does not need it set.  */
!               if (!DECL_P (rhs))
! 		{
! 		  if (handled_component_p (rhs))
! 		    rhs = get_base_address (rhs);
! 
! 		  if (rhs
! 		      && TREE_CODE (rhs) == MEM_REF
! 		      && TREE_CODE (TREE_OPERAND (rhs, 0)) == ADDR_EXPR
! 		      && DECL_P (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0))
! 		      && !integer_zerop (TREE_OPERAND (rhs, 1)))
! 		    bitmap_set_bit (not_reg_needs, DECL_UID (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0)));
                  }
  	    }
  	}
*************** execute_update_addresses_taken (bool do_
*** 2021,2026 ****
--- 2032,2097 ----
  	    {
  	      gimple stmt = gsi_stmt (gsi);
  
+ 	      /* Re-write TARGET_MEM_REFs of symbols we want to
+ 		 rewrite into SSA form.  */
+ 	      if (gimple_assign_single_p (stmt))
+ 		{
+ 		  tree lhs = gimple_assign_lhs (stmt);
+ 		  tree rhs, *rhsp = gimple_assign_rhs1_ptr (stmt);
+ 		  tree sym;
+ 
+ 		  /* We shouldn't have any fancy wrapping of
+ 		     component-refs on the LHS, but look through
+ 		     VIEW_CONVERT_EXPRs as that is easy.  */
+ 		  while (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
+ 		    lhs = TREE_OPERAND (lhs, 0);
+ 		  if (TREE_CODE (lhs) == MEM_REF
+ 		      && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR
+ 		      && integer_zerop (TREE_OPERAND (lhs, 1))
+ 		      && (sym = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0))
+ 		      && DECL_P (sym)
+ 		      && !TREE_ADDRESSABLE (sym)
+ 		      && symbol_marked_for_renaming (sym))
+ 		    lhs = sym;
+ 		  else
+ 		    lhs = gimple_assign_lhs (stmt);
+ 
+ 		  /* We can have fancy wrappings on the RHS though.  */
+ 		  while (handled_component_p (*rhsp))
+ 		    rhsp = &TREE_OPERAND (*rhsp, 0);
+ 		  if (TREE_CODE (*rhsp) == MEM_REF
+ 		      && TREE_CODE (TREE_OPERAND (*rhsp, 0)) == ADDR_EXPR
+ 		      && integer_zerop (TREE_OPERAND (*rhsp, 1))
+ 		      && (sym = TREE_OPERAND (TREE_OPERAND (*rhsp, 0), 0))
+ 		      && DECL_P (sym)
+ 		      && !TREE_ADDRESSABLE (sym)
+ 		      && symbol_marked_for_renaming (sym))
+ 		    {
+ 		      if (!useless_type_conversion_p (TREE_TYPE (*rhsp),
+ 						      TREE_TYPE (sym)))
+ 			*rhsp = build1 (VIEW_CONVERT_EXPR,
+ 					TREE_TYPE (*rhsp), sym);
+ 		      else
+ 			*rhsp = sym;
+ 		    }
+ 
+ 		  rhs = gimple_assign_rhs1 (stmt);
+ 		  if (gimple_assign_lhs (stmt) != lhs
+ 		      && !useless_type_conversion_p (TREE_TYPE (lhs),
+ 						     TREE_TYPE (rhs)))
+ 		    rhs = fold_build1 (VIEW_CONVERT_EXPR,
+ 				       TREE_TYPE (lhs), rhs);
+ 
+ 		  if (gimple_assign_lhs (stmt) != lhs)
+ 		    gimple_assign_set_lhs (stmt, lhs);
+ 
+ 		  if (gimple_assign_rhs1 (stmt) != rhs)
+ 		    {
+ 		      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ 		      gimple_assign_set_rhs_from_tree (&gsi, rhs);
+ 		    }
+ 		}
+ 
  	      if (gimple_references_memory_p (stmt)
  		  || is_gimple_debug (stmt))
  		update_stmt (stmt);
Index: trunk/gcc/tree.def
===================================================================
*** trunk.orig/gcc/tree.def	2010-03-08 10:32:38.000000000 +0100
--- trunk/gcc/tree.def	2010-03-08 16:24:48.000000000 +0100
*************** DEFTREECODE (REALIGN_LOAD_EXPR, "realign
*** 973,978 ****
--- 973,987 ----
  
  DEFTREECODE (TARGET_MEM_REF, "target_mem_ref", tcc_reference, 6)
  
+ /* Memory addressing.  Operands are a pointer and a tree constant integer
+    byte offset of the pointer type that when dereferenced yields the
+    type of the base object the pointer points to and which is used for
+    TBAA purposes.
+    The type of the MEM_REF is the type of the value load from memory.
+    MEM_REF <p, c> is equivalent to ((typeof(c))p)->x... where x... is a
+    chain of component references offsetting p by c.  */
+ DEFTREECODE (MEM_REF, "mem_ref", tcc_reference, 2)
+ 
  /* The ordering of the codes between OMP_PARALLEL and OMP_CRITICAL is
     exposed to TREE_RANGE_CHECK.  */
  /* OpenMP - #pragma omp parallel [clause1 ... clauseN]
Index: trunk/gcc/tree-ssa-ccp.c
===================================================================
*** trunk.orig/gcc/tree-ssa-ccp.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-ssa-ccp.c	2010-03-10 11:04:51.000000000 +0100
*************** maybe_fold_reference (tree expr, bool is
*** 2430,2435 ****
--- 2430,2476 ----
  	  return expr;
  	}
      }
+   /* Fold back MEM_REFs to reference trees.  */
+   else if (TREE_CODE (*t) == MEM_REF
+ 	   && TREE_CODE (TREE_OPERAND (*t, 0)) == ADDR_EXPR
+ 	   && integer_zerop (TREE_OPERAND (*t, 1))
+ 	   && TREE_THIS_VOLATILE (*t) == TREE_THIS_VOLATILE (TREE_OPERAND (TREE_OPERAND (*t, 0), 0))
+ 	   && get_alias_set (*t) == get_alias_set (TREE_OPERAND (TREE_OPERAND (*t, 0), 0))
+ 	   && useless_type_conversion_p (TREE_TYPE (*t),
+ 					 TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*t, 0), 0))))
+     {
+       tree tem;
+       *t = TREE_OPERAND (TREE_OPERAND (*t, 0), 0);
+       tem = maybe_fold_reference (expr, is_lhs);
+       if (tem)
+ 	return tem;
+       return expr;
+     }
+   /* Canonicalize MEM_REFs invariant address operand.  */
+   else if (TREE_CODE (*t) == MEM_REF
+ 	   && TREE_CODE (TREE_OPERAND (*t, 0)) == ADDR_EXPR
+ 	   && !DECL_P (TREE_OPERAND (TREE_OPERAND (*t, 0), 0))
+ 	   && !CONSTANT_CLASS_P (TREE_OPERAND (TREE_OPERAND (*t, 0), 0))
+ 	   && is_gimple_min_invariant (TREE_OPERAND (*t, 0)))
+     {
+       tree base;
+       HOST_WIDE_INT offset, size, max_size;
+       base = get_ref_base_and_extent (TREE_OPERAND (TREE_OPERAND (*t, 0), 0),
+ 				      &offset, &size, &max_size);
+       /* We only care for the offset here - and is_gimple_min_invariant
+          address should ensure that that is not variable.
+ 	 ???  Maybe better use get_inner_reference for this.  */
+       gcc_assert (offset % BITS_PER_UNIT == 0);
+       TREE_OPERAND (*t, 0) = build_fold_addr_expr_loc (EXPR_LOCATION (TREE_OPERAND (*t, 0)),
+ 						       base);
+       TREE_OPERAND (*t, 1) = int_const_binop (PLUS_EXPR,
+ 					      TREE_OPERAND (*t, 1),
+ 					      build_int_cst (TREE_TYPE (TREE_OPERAND (*t, 1)), offset / BITS_PER_UNIT), 0);
+       base = maybe_fold_reference (expr, is_lhs);
+       if (base)
+ 	return base;
+       return expr;
+     }
    else if (!is_lhs
  	   && DECL_P (*t))
      {
*************** maybe_fold_reference (tree expr, bool is
*** 2445,2450 ****
--- 2486,2516 ----
  	}
      }
  
+   /* Strip constant-offset component refs.  */
+   if (TREE_CODE (*t) == MEM_REF
+       && handled_component_p (expr))
+     {
+       tree base;
+       HOST_WIDE_INT offset, size, max_size;
+       base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
+       if (max_size != -1
+ 	  && size == max_size
+ 	  && offset % BITS_PER_UNIT == 0)
+ 	{
+ 	  if (base == *t)
+ 	    return build2 (MEM_REF, TREE_TYPE (expr),
+ 			   TREE_OPERAND (*t, 0),
+ 			   int_const_binop (PLUS_EXPR,
+ 					    TREE_OPERAND (*t, 1),
+ 					    build_int_cst (TREE_TYPE (TREE_OPERAND (*t, 1)), offset / BITS_PER_UNIT), 0));
+ 	  else if (TREE_CODE (TREE_OPERAND (*t, 0)) == ADDR_EXPR
+ 		   && base == TREE_OPERAND (TREE_OPERAND (*t, 0), 0))
+ 	    return build2 (MEM_REF, TREE_TYPE (expr),
+ 			   TREE_OPERAND (*t, 0),
+ 			   build_int_cst (TREE_TYPE (TREE_OPERAND (*t, 1)), offset / BITS_PER_UNIT));
+ 	}
+     }
+ 
    return NULL_TREE;
  }
  
Index: trunk/gcc/tree-dfa.c
===================================================================
*** trunk.orig/gcc/tree-dfa.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-dfa.c	2010-03-10 16:32:32.000000000 +0100
*************** get_ref_base_and_extent (tree exp, HOST_
*** 877,882 ****
--- 877,897 ----
  	case VIEW_CONVERT_EXPR:
  	  break;
  
+ 	case MEM_REF:
+ 	  if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
+ 	      /* We do need to handle large offsets here, for example
+ 	         from gcc.c-torture/compile/pr28489.c.  Thus the whole
+ 		 function should probably be audited for overflowing
+ 		 bit_offset ... */
+ 	      && (TREE_INT_CST_HIGH (TREE_OPERAND (exp, 1)) == -1
+ 		  || host_integerp (TREE_OPERAND (exp, 1), 0)))
+ 	    {
+ 	      bit_offset
+ 		+= TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT;
+ 	      exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ 	    }
+ 	  goto done;
+ 
  	default:
  	  goto done;
  	}
Index: trunk/gcc/tree-nested.c
===================================================================
*** trunk.orig/gcc/tree-nested.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-nested.c	2010-03-08 16:22:53.000000000 +0100
*************** get_static_chain (struct nesting_info *i
*** 760,766 ****
  	{
  	  tree field = get_chain_field (i);
  
! 	  x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
  	  x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
  	  x = init_tmp_var (info, x, gsi);
  	}
--- 760,766 ----
  	{
  	  tree field = get_chain_field (i);
  
! 	  x = build_simple_mem_ref (x);
  	  x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
  	  x = init_tmp_var (info, x, gsi);
  	}
*************** get_frame_field (struct nesting_info *in
*** 795,806 ****
  	{
  	  tree field = get_chain_field (i);
  
! 	  x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
  	  x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
  	  x = init_tmp_var (info, x, gsi);
  	}
  
!       x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
      }
  
    x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
--- 795,806 ----
  	{
  	  tree field = get_chain_field (i);
  
! 	  x = build_simple_mem_ref (x);
  	  x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
  	  x = init_tmp_var (info, x, gsi);
  	}
  
!       x = build_simple_mem_ref (x);
      }
  
    x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
*************** get_nonlocal_debug_decl (struct nesting_
*** 843,858 ****
        for (i = info->outer; i->context != target_context; i = i->outer)
  	{
  	  field = get_chain_field (i);
! 	  x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
  	  x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
  	}
!       x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
      }
  
    field = lookup_field_for_decl (i, decl, INSERT);
    x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
    if (use_pointer_in_frame (decl))
!     x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
  
    /* ??? We should be remapping types as well, surely.  */
    new_decl = build_decl (DECL_SOURCE_LOCATION (decl),
--- 843,858 ----
        for (i = info->outer; i->context != target_context; i = i->outer)
  	{
  	  field = get_chain_field (i);
! 	  x = build_simple_mem_ref (x);
  	  x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
  	}
!       x = build_simple_mem_ref (x);
      }
  
    field = lookup_field_for_decl (i, decl, INSERT);
    x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
    if (use_pointer_in_frame (decl))
!     x = build_simple_mem_ref (x);
  
    /* ??? We should be remapping types as well, surely.  */
    new_decl = build_decl (DECL_SOURCE_LOCATION (decl),
*************** convert_nonlocal_reference_op (tree *tp,
*** 929,935 ****
  	      if (use_pointer_in_frame (t))
  		{
  		  x = init_tmp_var (info, x, &wi->gsi);
! 		  x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
  		}
  	    }
  
--- 929,935 ----
  	      if (use_pointer_in_frame (t))
  		{
  		  x = init_tmp_var (info, x, &wi->gsi);
! 		  x = build_simple_mem_ref (x);
  		}
  	    }
  
Index: trunk/gcc/tree-ssa-dce.c
===================================================================
*** trunk.orig/gcc/tree-ssa-dce.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-ssa-dce.c	2010-03-09 15:52:59.000000000 +0100
*************** ref_may_be_aliased (tree ref)
*** 482,487 ****
--- 482,490 ----
  {
    while (handled_component_p (ref))
      ref = TREE_OPERAND (ref, 0);
+   if (TREE_CODE (ref) == MEM_REF
+       && TREE_CODE (TREE_OPERAND (ref, 0)) == ADDR_EXPR)
+     ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
    return !(DECL_P (ref)
  	   && !may_be_aliased (ref));
  }
Index: trunk/gcc/tree-stdarg.c
===================================================================
*** trunk.orig/gcc/tree-stdarg.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-stdarg.c	2010-03-08 16:42:40.000000000 +0100
*************** check_all_va_list_escapes (struct stdarg
*** 511,517 ****
  		  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
  
  		  /* x = *ap_temp;  */
! 		  if (gimple_assign_rhs_code (stmt) == INDIRECT_REF
  		      && TREE_OPERAND (rhs, 0) == use
  		      && TYPE_SIZE_UNIT (TREE_TYPE (rhs))
  		      && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), 1)
--- 511,517 ----
  		  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
  
  		  /* x = *ap_temp;  */
! 		  if (gimple_assign_rhs_code (stmt) == MEM_REF
  		      && TREE_OPERAND (rhs, 0) == use
  		      && TYPE_SIZE_UNIT (TREE_TYPE (rhs))
  		      && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), 1)
*************** check_all_va_list_escapes (struct stdarg
*** 521,526 ****
--- 521,527 ----
  		      tree access_size = TYPE_SIZE_UNIT (TREE_TYPE (rhs));
  
  		      gpr_size = si->offsets[SSA_NAME_VERSION (use)]
+ 			  	 + tree_low_cst (TREE_OPERAND (rhs, 1), 0)
  				 + tree_low_cst (access_size, 1);
  		      if (gpr_size >= VA_LIST_MAX_GPR_SIZE)
  			cfun->va_list_gpr_size = VA_LIST_MAX_GPR_SIZE;
Index: trunk/gcc/tree-vect-stmts.c
===================================================================
*** trunk.orig/gcc/tree-vect-stmts.c	2010-03-08 11:32:58.000000000 +0100
--- trunk/gcc/tree-vect-stmts.c	2010-03-08 16:22:53.000000000 +0100
*************** vectorizable_store (gimple stmt, gimple_
*** 3193,3199 ****
  	    vec_oprnd = VEC_index (tree, result_chain, i);
  
            if (aligned_access_p (first_dr))
!             data_ref = build_fold_indirect_ref (dataref_ptr);
            else
            {
              int mis = DR_MISALIGNMENT (first_dr);
--- 3193,3199 ----
  	    vec_oprnd = VEC_index (tree, result_chain, i);
  
            if (aligned_access_p (first_dr))
! 	    data_ref = build_simple_mem_ref (dataref_ptr);
            else
            {
              int mis = DR_MISALIGNMENT (first_dr);
*************** vectorizable_load (gimple stmt, gimple_s
*** 3570,3576 ****
  	    {
  	    case dr_aligned:
  	      gcc_assert (aligned_access_p (first_dr));
! 	      data_ref = build_fold_indirect_ref (dataref_ptr);
  	      break;
  	    case dr_unaligned_supported:
  	      {
--- 3570,3576 ----
  	    {
  	    case dr_aligned:
  	      gcc_assert (aligned_access_p (first_dr));
! 	      data_ref = build_simple_mem_ref (dataref_ptr);
  	      break;
  	    case dr_unaligned_supported:
  	      {
Index: trunk/gcc/tree.c
===================================================================
*** trunk.orig/gcc/tree.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree.c	2010-03-08 16:43:30.000000000 +0100
*************** build6_stat (enum tree_code code, tree t
*** 3832,3837 ****
--- 3832,3850 ----
    return t;
  }
  
+ /* Build a simple MEM_REF tree with the sematics of a plain INDIRECT_REF
+    on the pointer PTR.  */
+ 
+ tree
+ build_simple_mem_ref_loc (location_t loc, tree ptr)
+ {
+   tree tem;
+   tem = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (ptr)),
+ 		ptr, build_int_cst (TREE_TYPE (ptr), 0));
+   SET_EXPR_LOCATION (tem, loc);
+   return tem;
+ }
+ 
  /* Similar except don't specify the TREE_TYPE
     and leave the TREE_SIDE_EFFECTS as 0.
     It is permissible for arguments to be null,
Index: trunk/gcc/tree.h
===================================================================
*** trunk.orig/gcc/tree.h	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree.h	2010-03-08 16:22:53.000000000 +0100
*************** extern tree build_fold_indirect_ref_loc
*** 4884,4889 ****
--- 4884,4892 ----
  #define fold_indirect_ref(T)\
          fold_indirect_ref_loc (UNKNOWN_LOCATION, T)
  extern tree fold_indirect_ref_loc (location_t, tree);
+ extern tree build_simple_mem_ref_loc (location_t, tree);
+ #define build_simple_mem_ref(T)\
+ 	build_simple_mem_ref_loc (UNKNOWN_LOCATION, T)
  extern tree constant_boolean_node (int, tree);
  extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
  
Index: trunk/gcc/cfgexpand.c
===================================================================
*** trunk.orig/gcc/cfgexpand.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/cfgexpand.c	2010-03-08 16:43:52.000000000 +0100
*************** expand_debug_expr (tree exp)
*** 2419,2424 ****
--- 2419,2429 ----
  	return op0;
        }
  
+     case MEM_REF:
+       /* ??? FIXME.  */
+       if (!integer_zerop (TREE_OPERAND (exp, 1)))
+ 	return NULL;
+       /* Fallthru.  */
      case INDIRECT_REF:
      case ALIGN_INDIRECT_REF:
      case MISALIGNED_INDIRECT_REF:
Index: trunk/gcc/config/i386/i386.c
===================================================================
*** trunk.orig/gcc/config/i386/i386.c	2010-03-08 11:32:56.000000000 +0100
--- trunk/gcc/config/i386/i386.c	2010-03-08 16:22:53.000000000 +0100
*************** ix86_va_start (tree valist, rtx nextarg)
*** 6922,6928 ****
    f_ovf = TREE_CHAIN (f_fpr);
    f_sav = TREE_CHAIN (f_ovf);
  
!   valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
    gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
    fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
    ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
--- 6922,6931 ----
    f_ovf = TREE_CHAIN (f_fpr);
    f_sav = TREE_CHAIN (f_ovf);
  
!   /* valist needs to be decomposed if it is &a.b.c -- do that in
!      build_simple_mem_ref.  */
!   valist = build_simple_mem_ref (valist);
!   /* The following should be folded into the MEM_REF offset.  */
    gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
    fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
    ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
*************** ix86_canonical_va_list_type (tree type)
*** 30134,30139 ****
--- 30137,30144 ----
      type = TREE_TYPE (type);
    else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
      type = TREE_TYPE (type);
+   else if (POINTER_TYPE_P (type) && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
+     type = TREE_TYPE (type);
  
    if (TARGET_64BIT)
      {
Index: trunk/gcc/dwarf2out.c
===================================================================
*** trunk.orig/gcc/dwarf2out.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/dwarf2out.c	2010-03-08 16:44:19.000000000 +0100
*************** loc_list_from_tree (tree loc, int want_a
*** 14482,14487 ****
--- 14482,14492 ----
        }
        break;
  
+     case MEM_REF:
+       /* ??? FIXME.  */
+       if (!integer_zerop (TREE_OPERAND (loc, 1)))
+ 	return 0;
+       /* Fallthru.  */
      case INDIRECT_REF:
      case ALIGN_INDIRECT_REF:
      case MISALIGNED_INDIRECT_REF:
Index: trunk/gcc/tree-ssa-forwprop.c
===================================================================
*** trunk.orig/gcc/tree-ssa-forwprop.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-ssa-forwprop.c	2010-03-08 16:22:53.000000000 +0100
*************** forward_propagate_into_gimple_cond (gimp
*** 398,422 ****
  
    do {
      tree tmp = NULL_TREE;
!     tree name, rhs0 = NULL_TREE, rhs1 = NULL_TREE;
      gimple def_stmt;
      bool single_use0_p = false, single_use1_p = false;
      enum tree_code code = gimple_cond_code (stmt);
  
      /* We can do tree combining on SSA_NAME and comparison expressions.  */
!     if (TREE_CODE_CLASS (gimple_cond_code (stmt)) == tcc_comparison
!         && TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME)
        {
  	/* For comparisons use the first operand, that is likely to
  	   simplify comparisons against constants.  */
! 	name = gimple_cond_lhs (stmt);
! 	def_stmt = get_prop_source_stmt (name, false, &single_use0_p);
! 	if (def_stmt && can_propagate_from (def_stmt))
  	  {
! 	    tree op1 = gimple_cond_rhs (stmt);
! 	    rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt);
! 	    tmp = combine_cond_expr_cond (loc, code, boolean_type_node, rhs0,
! 					  op1, !single_use0_p);
  	  }
  	/* If that wasn't successful, try the second operand.  */
  	if (tmp == NULL_TREE
--- 398,424 ----
  
    do {
      tree tmp = NULL_TREE;
!     tree name = NULL_TREE, rhs0 = NULL_TREE, rhs1 = NULL_TREE;
      gimple def_stmt;
      bool single_use0_p = false, single_use1_p = false;
      enum tree_code code = gimple_cond_code (stmt);
  
      /* We can do tree combining on SSA_NAME and comparison expressions.  */
!     if (TREE_CODE_CLASS (gimple_cond_code (stmt)) == tcc_comparison)
        {
  	/* For comparisons use the first operand, that is likely to
  	   simplify comparisons against constants.  */
! 	if (TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME)
  	  {
! 	    name = gimple_cond_lhs (stmt);
! 	    def_stmt = get_prop_source_stmt (name, false, &single_use0_p);
! 	    if (def_stmt && can_propagate_from (def_stmt))
! 	      {
! 		tree op1 = gimple_cond_rhs (stmt);
! 		rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt);
! 		tmp = combine_cond_expr_cond (loc, code, boolean_type_node,
! 					      rhs0, op1, !single_use0_p);
! 	      }
  	  }
  	/* If that wasn't successful, try the second operand.  */
  	if (tmp == NULL_TREE
Index: trunk/gcc/tree-eh.c
===================================================================
*** trunk.orig/gcc/tree-eh.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-eh.c	2010-03-08 16:22:53.000000000 +0100
*************** tree_could_trap_p (tree expr)
*** 2400,2405 ****
--- 2400,2409 ----
  	return false;
        return !in_array_bounds_p (expr);
  
+     case MEM_REF:
+       if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
+ 	return false;
+       /* Fallthru.  */
      case INDIRECT_REF:
      case ALIGN_INDIRECT_REF:
      case MISALIGNED_INDIRECT_REF:
Index: trunk/gcc/tree-sra.c
===================================================================
*** trunk.orig/gcc/tree-sra.c	2010-03-08 10:33:26.000000000 +0100
--- trunk/gcc/tree-sra.c	2010-03-09 16:41:38.000000000 +0100
*************** build_access_from_expr_1 (tree *expr_ptr
*** 932,937 ****
--- 932,938 ----
    switch (TREE_CODE (expr))
      {
      case INDIRECT_REF:
+     case MEM_REF:
        if (sra_mode != SRA_MODE_EARLY_IPA)
  	return NULL;
        /* fall through */
*************** make_fancy_name (tree expr)
*** 1372,1471 ****
    return XOBFINISH (&name_obstack, char *);
  }
  
- /* Helper function for build_ref_for_offset.  */
- 
- static bool
- build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset,
- 			tree exp_type)
- {
-   while (1)
-     {
-       tree fld;
-       tree tr_size, index, minidx;
-       HOST_WIDE_INT el_size;
- 
-       if (offset == 0 && exp_type
- 	  && types_compatible_p (exp_type, type))
- 	return true;
- 
-       switch (TREE_CODE (type))
- 	{
- 	case UNION_TYPE:
- 	case QUAL_UNION_TYPE:
- 	case RECORD_TYPE:
- 	  for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
- 	    {
- 	      HOST_WIDE_INT pos, size;
- 	      tree expr, *expr_ptr;
- 
- 	      if (TREE_CODE (fld) != FIELD_DECL)
- 		continue;
- 
- 	      pos = int_bit_position (fld);
- 	      gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
- 	      tr_size = DECL_SIZE (fld);
- 	      if (!tr_size || !host_integerp (tr_size, 1))
- 		continue;
- 	      size = tree_low_cst (tr_size, 1);
- 	      if (size == 0)
- 		{
- 		  if (pos != offset)
- 		    continue;
- 		}
- 	      else if (pos > offset || (pos + size) <= offset)
- 		continue;
- 
- 	      if (res)
- 		{
- 		  expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
- 				 NULL_TREE);
- 		  expr_ptr = &expr;
- 		}
- 	      else
- 		expr_ptr = NULL;
- 	      if (build_ref_for_offset_1 (expr_ptr, TREE_TYPE (fld),
- 					  offset - pos, exp_type))
- 		{
- 		  if (res)
- 		    *res = expr;
- 		  return true;
- 		}
- 	    }
- 	  return false;
- 
- 	case ARRAY_TYPE:
- 	  tr_size = TYPE_SIZE (TREE_TYPE (type));
- 	  if (!tr_size || !host_integerp (tr_size, 1))
- 	    return false;
- 	  el_size = tree_low_cst (tr_size, 1);
- 
- 	  minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
- 	  if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
- 	    return false;
- 	  if (res)
- 	    {
- 	      index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
- 	      if (!integer_zerop (minidx))
- 		index = int_const_binop (PLUS_EXPR, index, minidx, 0);
- 	      *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
- 			     NULL_TREE, NULL_TREE);
- 	    }
- 	  offset = offset % el_size;
- 	  type = TREE_TYPE (type);
- 	  break;
- 
- 	default:
- 	  if (offset != 0)
- 	    return false;
- 
- 	  if (exp_type)
- 	    return false;
- 	  else
- 	    return true;
- 	}
-     }
- }
- 
  /* Construct an expression that would reference a part of aggregate *EXPR of
     type TYPE at the given OFFSET of the type EXP_TYPE.  If EXPR is NULL, the
     function only determines whether it can build such a reference without
--- 1373,1378 ----
*************** build_ref_for_offset (tree *expr, tree t
*** 1483,1499 ****
  {
    location_t loc = expr ? EXPR_LOCATION (*expr) : UNKNOWN_LOCATION;
  
!   if (expr)
!     *expr = unshare_expr (*expr);
  
    if (allow_ptr && POINTER_TYPE_P (type))
      {
!       type = TREE_TYPE (type);
!       if (expr)
! 	*expr = fold_build1_loc (loc, INDIRECT_REF, type, *expr);
      }
  
!   return build_ref_for_offset_1 (expr, type, offset, exp_type);
  }
  
  /* Return true iff TYPE is stdarg va_list type.  */
--- 1390,1425 ----
  {
    location_t loc = expr ? EXPR_LOCATION (*expr) : UNKNOWN_LOCATION;
  
!   if (offset % BITS_PER_UNIT != 0)
!     return false;
! 
!   if (!expr)
!     return true;
! 
!   *expr = unshare_expr (*expr);
  
    if (allow_ptr && POINTER_TYPE_P (type))
+     *expr = build2 (MEM_REF, exp_type,
+ 		    *expr, build_int_cst (type, offset / BITS_PER_UNIT));
+   else if (TREE_CODE (*expr) == MEM_REF)
+     {
+       tree addr = TREE_OPERAND (*expr, 0);
+       tree off = build_int_cst (TREE_TYPE (TREE_OPERAND (*expr, 1)),
+ 				offset / BITS_PER_UNIT);
+       off = int_const_binop (PLUS_EXPR, TREE_OPERAND (*expr, 1), off, 0);
+       *expr = build2 (MEM_REF, exp_type, addr, off);
+     }
+   else
      {
!       tree ptype = build_pointer_type (type);
!       tree off = build_int_cst (ptype, offset / BITS_PER_UNIT);
!       tree addr = build_fold_addr_expr (*expr);
!       STRIP_NOPS (addr);
!       *expr = build2 (MEM_REF, exp_type, addr, off);
      }
  
!   SET_EXPR_LOCATION (*expr, loc);
!   return true;
  }
  
  /* Return true iff TYPE is stdarg va_list type.  */
*************** late_intra_sra (void)
*** 2839,2845 ****
  static bool
  gate_intra_sra (void)
  {
!   return flag_tree_sra != 0;
  }
  
  
--- 2765,2771 ----
  static bool
  gate_intra_sra (void)
  {
!   return 0 && flag_tree_sra != 0;
  }
  
  
*************** sra_ipa_modify_expr (tree *expr, gimple_
*** 3830,3835 ****
--- 3756,3767 ----
    if (INDIRECT_REF_P (base))
      base = TREE_OPERAND (base, 0);
  
+   if (TREE_CODE (base) == MEM_REF)
+     {
+       offset += TREE_INT_CST_LOW (TREE_OPERAND (base, 1)) * BITS_PER_UNIT;
+       base = TREE_OPERAND (base, 0);
+     }
+ 
    base = get_ssa_base_param (base);
    if (!base || TREE_CODE (base) != PARM_DECL)
      return false;
*************** ipa_early_sra (void)
*** 4198,4204 ****
  static bool
  ipa_early_sra_gate (void)
  {
!   return flag_ipa_sra;
  }
  
  struct gimple_opt_pass pass_early_ipa_sra =
--- 4130,4136 ----
  static bool
  ipa_early_sra_gate (void)
  {
!   return 0 && flag_ipa_sra;
  }
  
  struct gimple_opt_pass pass_early_ipa_sra =
Index: trunk/gcc/tree-ssa-structalias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-structalias.c	2010-02-09 15:20:18.000000000 +0100
--- trunk/gcc/tree-ssa-structalias.c	2010-03-09 14:03:28.000000000 +0100
*************** get_constraint_for_1 (tree t, VEC (ce_s,
*** 3179,3184 ****
--- 3179,3191 ----
  	      do_deref (results);
  	      return;
  	    }
+ 	  case MEM_REF:
+ 	    {
+ 	      get_constraint_for_ptr_offset (TREE_OPERAND (t, 0),
+ 					     TREE_OPERAND (t, 1), results);
+ 	      do_deref (results);
+ 	      return;
+ 	    }
  	  case ARRAY_REF:
  	  case ARRAY_RANGE_REF:
  	  case COMPONENT_REF:
Index: trunk/gcc/tree-complex.c
===================================================================
*** trunk.orig/gcc/tree-complex.c	2010-01-13 11:06:22.000000000 +0100
--- trunk/gcc/tree-complex.c	2010-03-09 15:29:35.000000000 +0100
*************** extract_component (gimple_stmt_iterator
*** 603,608 ****
--- 603,609 ----
      case COMPONENT_REF:
      case ARRAY_REF:
      case VIEW_CONVERT_EXPR:
+     case MEM_REF:
        {
  	tree inner_type = TREE_TYPE (TREE_TYPE (t));
  
Index: trunk/gcc/tree-inline.c
===================================================================
*** trunk.orig/gcc/tree-inline.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/tree-inline.c	2010-03-10 12:05:22.000000000 +0100
*************** declare_return_variable (copy_body_data
*** 2591,2596 ****
--- 2591,2599 ----
  					  false);
  	      if (TREE_CODE (base) == INDIRECT_REF)
  		base = TREE_OPERAND (base, 0);
+ 	      if (TREE_CODE (base) == MEM_REF
+ 		  && integer_zerop (TREE_OPERAND (base, 1)))
+ 		base = TREE_OPERAND (base, 0);
  	      if (TREE_CODE (base) == SSA_NAME)
  		base = SSA_NAME_VAR (base);
  	      mark_sym_for_renaming (base);
Index: trunk/gcc/builtins.c
===================================================================
*** trunk.orig/gcc/builtins.c	2010-03-08 10:32:39.000000000 +0100
--- trunk/gcc/builtins.c	2010-03-10 15:37:28.000000000 +0100
*************** stabilize_va_list_loc (location_t loc, t
*** 4340,4346 ****
--- 4340,4353 ----
  {
    tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
  
+   /* The current way of determining the type of valist is completely
+      bogus.  We should have the information on the current function
+      declaration instead.  */
+ #if 0
    gcc_assert (vatype != NULL_TREE);
+ #endif
+   if (!vatype)
+     vatype = va_list_type_node;
  
    if (TREE_CODE (vatype) == ARRAY_TYPE)
      {



More information about the Gcc-patches mailing list