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][mem-ref2] Initial MEM_REF deployment


I have created a new branch, mem-ref2, that contains the MEM_REF work
that is supposed to be merged during stage1 of GCC 4.6 (I'll document
it soon in svn.html).  Patches are reviewed by me and should have
[mem-ref2] in the subject.

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 old 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).

ALIGN_INDIRECT_REFs and MISALIGNED_INDIRECT_REFs as produced by
the vectorizer are retained for now.  They need a better representation
of alignment information after which they should vanish as well.

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 bootstraps for all languages on x86_64 with multilibs enabled.
Testing succeeds without execution fails (there's two execution fails
in the vectorizer testsuite though).  Loads of ICEs remain.

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).


Thus the following is the initial patch I am deploying to the newly
created mem-ref2 branch which I hope to get ready for merging during
stage1.  Sofar feedback was overwhelming as usual, so the design
should be sound and a definitive progress for GCC.

The first block of changes (in the ChangeLog entry) are fixes independent
of MEM_REF, to be pushed early during stage1.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the
branch.  For testresults of this initial revision see
http://gcc.gnu.org/ml/gcc-testresults/2010-03/msg01904.html

Richard.


	* fold-const.c (fold_unary_loc): Do not strip qualifiers when
	folding address expressions.
	* gimple.c (gimple_ior_addresses_taken_1): Use get_base_address.
	* tree-ssa-alias.c (decl_refs_may_alias_p): Do not use
	operand_equal_p to compare decls.
	(ptr_deref_may_alias_decl_p): Likewise.
	* tree-ssa-operands.c (get_asm_expr_operands): Simplify
	* tree-ssa-forwprop.c (forward_propagate_into_gimple_cond):
	Handle reversed comparison ops.
	* tree-sra.c (asm_visit_addr): Use get_base_address.
	* ipa-prop.c (visit_store_addr_for_mod_analysis): Use
	get_base_address.
	* ipa-reference.c (mark_address): Use get_base_address.

	* alias.c (ao_ref_from_mem): Handle MEM_REF.
	(get_alias_set): Likewise.
	* expr.c (expand_assignment): Handle MEM_REF.
	(get_inner_reference): Likewise.
	(expand_expr_addr_expr_1): Likewise.
	(expand_expr_real_1): Likewise.
	* fold-const.c (build_fold_addr_expr_with_type_loc): Handle MEM_REF.
	(fold_comparison): Likewise.
	* gimple.c (is_gimple_addressable): Adjust for MEM_REF.
	(is_gimple_address): Likewise.
	(is_gimple_min_lval): Likewise.
	(get_base_address): Adjust for MEM_REFs with ADDR_EXPRs.
	(count_ptr_derefs): Adjust for MEM_REFs.
	(get_base_loadstore): Likewise.
	* gimplify.c (gimplify_init_ctor_preeval_1): Handle MEM_REF.
	(gimple_fold_indirect_ref): Adjust for MEM_REF.
	(gimplify_expr): Gimplify INDIRECT_REF to MEM_REF.  Handle
	MEM_REF.
	* tree-cfg.c (verify_expr): Handle MEM_REF.
	Disable TREE_ADDRESSABLE checking for now.
	(verify_types_in_gimple_min_lval): Handle MEM_REF.
	(verify_types_in_gimple_reference): Likewise.
	(verify_gimple_assign_single): Do not allow INDIRECT_REF.
	Handle MEM_REF.
	* tree-flow.h (get_addr_base_and_offset): Declare.
	(symbol_marked_for_renaming): Likewise.
	* tree-into-ssa.c (symbol_marked_for_renaming): Export.
	* tree-pretty-print.c (dump_generic_node): Handle MEM_REF.
	* tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Adjust
	for MEM_REFs.
	(ptr_derefs_may_alias_p): Likewise.
	(ptr_deref_may_alias_ref_p_1): Likewise.
	(ao_ref_init_from_ptr_and_size): Likewise.
	(indirect_ref_may_alias_decl_p): Likewise.
	(indirect_refs_may_alias_p): Likewise.
	(refs_may_alias_p_1): Likewise.
	(ref_maybe_used_by_call_p_1): Likewise.
	(call_may_clobber_ref_p_1): Likewise.
	* tree-ssa-loop-im.c (for_each_index): Handle MEM_REF.
	(gen_lsm_tmp_name): Likewise.  Handle ADDR_EXPR.
	* tree-ssa-loop-ivopts.c (determine_base_object): Adjust
	for MEM_REF.
	(strip_offset_1): Likewise.
	(tree_ssa_iv_optimize): Disable for now.
	* tree-ssa-operands.c (opf_non_addressable, opf_not_non_addressable):
	New.
	(mark_address_taken): Handle MEM_REF.
	(get_indirect_ref_operands): Pass through opf_not_non_addressable.
	* tree-ssa-operands.c (get_asm_expr_operands): Pass
	opf_not_non_addressable.
	(get_expr_operands): Handle opf_[not_]non_addressable.
	Handle MEM_REF.
	* tree-ssa-pre.c (create_component_ref_by_pieces_1): Handle
	MEM_REF.
	* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Handle MEM_REF.
	* tree-ssa-sink.c (is_hidden_global_store): Handle MEM_REF
	and constants.
	* tree-ssa.c (useless_type_conversion_p): Make most pointer
	conversions useless.
	(execute_update_addresses_taken): Implement re-writing of MEM_REFs
	to SSA form.
	* tree.def (MEM_REF): New tree code.
	* tree-ssa-ccp.c (maybe_fold_reference): Fold MEM_REF back to
	usual references if possible.  Validize MEM_REF of invariant
	address bases.  Collapse component-refs around MEM_REF.
	(fold_gimple_assign): Fold the address of a MEM_REF to
	POINTER_PLUS_EXPR.
	* tree-dfa.c (get_ref_base_and_extent): Handle MEM_REF.
	(get_addr_base_and_offset): New function.
	* tree-nested.c (get_static_chain): Adjust for MEM_REF.
	(get_frame_field): Likewise.
	(get_nonlocal_debug_decl): Likewise.
	(convert_nonlocal_reference_op): Likewise.
	* tree-ssa-dce.c (ref_may_be_aliased): Handle MEM_REF.
	* tree-stdarg.c (check_all_va_list_escapes): Adjust for MEM_REF.
	* tree-vect-stmts.c (vectorizable_store): Adjust for MEM_REF.
	(vectorizable_load): Likewise.
	* tree.c (build_simple_mem_ref_loc): New function.
	* tree.h (build_simple_mem_ref_loc): Declare.
	(build_simple_mem_ref): Define.
	* cfgexpand.c (expand_debug_expr): Handle MEM_REF.
	* config/i386/i386.c (ix86_va_start): Adjust for MEM_REF.
	(ix86_canonical_va_list_type): Likewise.
	* dwarf2out.c (loc_list_from_tree): Handle MEM_REF.
	* tree-eh.c (tree_could_trap_p): Handle MEM_REF.
	* tree-sra.c (build_access_from_expr_1): Handle MEM_REF.
	(build_ref_for_offset_1): Remove.
	(build_ref_for_offset): Build MEM_REFs.
	(gate_intra_sra): Disable for now.
	(sra_ipa_modify_expr): Handle MEM_REF.
	(ipa_early_sra_gate): Disable for now.
	* tree-ssa-structalias.c (get_constraint_for_1): Handle MEM_REF.
	* tree-complex.c (extract_component): Handle MEM_REF.
	* tree-inline.c (declare_return_variable): Handle MEM_REF.
	* builtins.c (stabilize_va_list_loc): Work around very broken
	va_list_type_node design.
	* tree-data-ref.c (dr_analyze_indices): Handle MEM_REF.
	* cgraphunit.c (thunk_adjust): Adjust for MEM_REF.
	* omp-low.c (build_receiver_ref): Adjust for MEM_REF.
	(build_outer_var_ref): Likewise.
	(scan_omp_1_op): Likewise.
	(lower_rec_input_clauses): Likewise.
	(lower_lastprivate_clauses): Likewise.
	(lower_reduction_clauses): Likewise.
	(lower_copyprivate_clauses): Likewise.
	(expand_omp_atomic_pipeline): Likewise.
	(expand_omp_atomic_mutex): Likewise.
	(create_task_copyfn): Likewise.
	* tree-parloops.c (take_address_of): Adjust for MEM_REF.
	(eliminate_local_variables_1): Likewise.
	(create_call_for_reduction_1): Likewise.
	(create_loads_for_reductions): Likewise.
	(create_loads_and_stores_for_name): Likewise.
	* ipa-struct-reorg.c (decompose_indirect_ref_acc): Handle MEM_REF.
	(decompose_access): Likewise.
	(replace_field_acc): Likewise.
	(replace_field_access_stmt): Likewise.
	(insert_new_var_in_stmt): Likewise.
	(get_stmt_accesses): Likewise.
	* tree-mudflap.c (mf_xform_derefs_1): Adjust for MEM_REF.

	* gcc.c-torture/execute/20100316-1.c: New testcase.


Index: trunk/gcc/alias.c
===================================================================
*** trunk.orig/gcc/alias.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/alias.c	2010-03-22 13:40: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,287 ----
  
    /* 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 (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);
  	}
      }
  
--- 302,308 ----
        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 ****
--- 669,676 ----
  	  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-22 13:36:55.000000000 +0100
--- trunk/gcc/expr.c	2010-03-22 14:22:50.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,6118 ----
  	    goto done;
  	  break;
  
+ 	case MEM_REF:
+ 	  /* ???  We should avoid doing this when doing so hides
+ 	     the effective alias set.  */
+ 	  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 ****
--- 6871,6885 ----
        /* 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 ****
--- 8773,8841 ----
        }
        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;
+ 		base = get_addr_base_and_offset (base, &off);
+ 		gcc_assert (base);
+ 		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-22 13:36:55.000000000 +0100
--- trunk/gcc/fold-const.c	2010-03-22 13:40:13.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_unary_loc (location_t loc, enum tre
*** 8556,8565 ****
  				      &mode, &unsignedp, &volatilep, false);
  	  /* If the reference was to a (constant) zero offset, we can use
  	     the address of the base if it has the same base type
! 	     as the result type.  */
  	  if (! offset && bitpos == 0
! 	      && TYPE_MAIN_VARIANT (TREE_TYPE (type))
  		  == TYPE_MAIN_VARIANT (TREE_TYPE (base)))
  	    return fold_convert_loc (loc, type,
  				     build_fold_addr_expr_loc (loc, base));
          }
--- 8565,8575 ----
  				      &mode, &unsignedp, &volatilep, false);
  	  /* If the reference was to a (constant) zero offset, we can use
  	     the address of the base if it has the same base type
! 	     as the result type and the pointer type is unqualified.  */
  	  if (! offset && bitpos == 0
! 	      && (TYPE_MAIN_VARIANT (TREE_TYPE (type))
  		  == TYPE_MAIN_VARIANT (TREE_TYPE (base)))
+ 	      && TYPE_QUALS (type) == TYPE_UNQUALIFIED)
  	    return fold_convert_loc (loc, type,
  				     build_fold_addr_expr_loc (loc, base));
          }
*************** fold_comparison (location_t loc, enum tr
*** 9361,9366 ****
--- 9371,9381 ----
        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 ****
--- 9393,9403 ----
        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-22 13:36:55.000000000 +0100
--- trunk/gcc/gimple.c	2010-03-22 13:40:13.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)
*** 2855,2864 ****
    while (handled_component_p (t))
      t = TREE_OPERAND (t, 0);
  
    if (SSA_VAR_P (t)
        || TREE_CODE (t) == STRING_CST
        || TREE_CODE (t) == CONSTRUCTOR
!       || INDIRECT_REF_P (t))
      return t;
    else
      return NULL_TREE;
--- 2856,2869 ----
    while (handled_component_p (t))
      t = TREE_OPERAND (t, 0);
  
+   if (TREE_CODE (t) == MEM_REF
+       && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
+     t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ 
    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++;
--- 4257,4263 ----
        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;
--- 4329,4335 ----
    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;
*************** gimple_ior_addresses_taken_1 (gimple stm
*** 4532,4540 ****
  			      tree addr, void *data)
  {
    bitmap addresses_taken = (bitmap)data;
!   while (handled_component_p (addr))
!     addr = TREE_OPERAND (addr, 0);
!   if (DECL_P (addr))
      {
        bitmap_set_bit (addresses_taken, DECL_UID (addr));
        return true;
--- 4537,4545 ----
  			      tree addr, void *data)
  {
    bitmap addresses_taken = (bitmap)data;
!   addr = get_base_address (addr);
!   if (addr
!       && DECL_P (addr))
      {
        bitmap_set_bit (addresses_taken, DECL_UID (addr));
        return true;
Index: trunk/gcc/gimplify.c
===================================================================
*** trunk.orig/gcc/gimplify.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/gimplify.c	2010-03-22 13:40:13.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,6683 ****
  	  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;
  
--- 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);
  	  recalculate_side_effects (*expr_p);
  	  break;
  
Index: trunk/gcc/tree-cfg.c
===================================================================
*** trunk.orig/gcc/tree-cfg.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-cfg.c	2010-03-22 13:40:13.000000000 +0100
*************** verify_expr (tree *tp, int *walk_subtree
*** 2518,2523 ****
--- 2518,2539 ----
  	}
        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
*** 2570,2580 ****
--- 2586,2599 ----
  	      || 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
*** 2764,2771 ****
    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;
--- 2783,2792 ----
    if (is_gimple_id (expr))
      return false;
  
!   if (TREE_CODE (expr) != ALIGN_INDIRECT_REF
!       && TREE_CODE (expr) != MISALIGNED_INDIRECT_REF
!       && 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
*** 2782,2787 ****
--- 2803,2809 ----
        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
*** 2790,2795 ****
--- 2812,2818 ----
        debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
        return true;
      }
+ #endif
  
    return false;
  }
*************** verify_types_in_gimple_reference (tree e
*** 2883,2888 ****
--- 2906,2932 ----
        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
*** 3527,3535 ****
        }
  
      /* tcc_reference  */
      case COMPONENT_REF:
      case BIT_FIELD_REF:
-     case INDIRECT_REF:
      case ALIGN_INDIRECT_REF:
      case MISALIGNED_INDIRECT_REF:
      case ARRAY_REF:
--- 3571,3582 ----
        }
  
      /* tcc_reference  */
+     case INDIRECT_REF:
+       error ("INDIRECT_REF in gimple IL");
+       return true;
+ 
      case COMPONENT_REF:
      case BIT_FIELD_REF:
      case ALIGN_INDIRECT_REF:
      case MISALIGNED_INDIRECT_REF:
      case ARRAY_REF:
*************** verify_gimple_assign_single (gimple stmt
*** 3538,3543 ****
--- 3585,3591 ----
      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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-flow.h	2010-03-22 13:40:13.000000000 +0100
*************** extern tree gimple_default_def (struct f
*** 519,524 ****
--- 519,525 ----
  extern bool stmt_references_abnormal_ssa_name (gimple);
  extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
  				     HOST_WIDE_INT *, HOST_WIDE_INT *);
+ extern tree get_addr_base_and_offset (tree, HOST_WIDE_INT *);
  extern void find_referenced_vars_in (gimple);
  
  /* In tree-phinodes.c  */
*************** void release_ssa_name_after_update_ssa (
*** 599,604 ****
--- 600,606 ----
  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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-into-ssa.c	2010-03-22 13:40:13.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-pretty-print.c	2010-03-22 13:40:13.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-alias.c	2010-03-22 14:16:43.000000000 +0100
*************** ptr_deref_may_alias_decl_p (tree ptr, tr
*** 185,195 ****
      {
        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))
! 	return operand_equal_p (base, decl, 0);
        else if (base
  	       && CONSTANT_CLASS_P (base))
  	return false;
--- 185,196 ----
      {
        tree base = get_base_address (TREE_OPERAND (ptr, 0));
        if (base
! 	  && (INDIRECT_REF_P (base)
! 	      || TREE_CODE (base) == MEM_REF))
  	ptr = TREE_OPERAND (base, 0);
        else if (base
  	       && SSA_VAR_P (base))
! 	return base == decl;
        else if (base
  	       && CONSTANT_CLASS_P (base))
  	return false;
*************** 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))
--- 242,249 ----
      {
        tree base = get_base_address (TREE_OPERAND (ptr1, 0));
        if (base
! 	  && (INDIRECT_REF_P (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))
--- 255,262 ----
      {
        tree base = get_base_address (TREE_OPERAND (ptr2, 0));
        if (base
! 	  && (INDIRECT_REF_P (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);
--- 305,312 ----
  {
    tree base = ao_ref_base (ref);
  
!   if (INDIRECT_REF_P (base)
!       || 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
--- 509,516 ----
  					 &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
*************** decl_refs_may_alias_p (tree base1,
*** 629,635 ****
    gcc_assert (SSA_VAR_P (base1) && SSA_VAR_P (base2));
  
    /* If both references are based on different variables, they cannot alias.  */
!   if (!operand_equal_p (base1, base2, 0))
      return false;
  
    /* If both references are based on the same variable, they cannot alias if
--- 634,640 ----
    gcc_assert (SSA_VAR_P (base1) && SSA_VAR_P (base2));
  
    /* If both references are based on different variables, they cannot alias.  */
!   if (base1 != base2)
      return false;
  
    /* If both references are based on the same variable, they cannot alias if
*************** decl_refs_may_alias_p (tree base1,
*** 645,657 ****
     if non-NULL are the complete memory reference trees.  */
  
  static bool
! indirect_ref_may_alias_decl_p (tree ref1, tree ptr1,
  			       HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
  			       alias_set_type base1_alias_set,
  			       tree ref2, tree base2,
  			       HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2,
  			       alias_set_type base2_alias_set)
  {
    /* If only one reference is based on a variable, they cannot alias if
       the pointer access is beyond the extent of the variable access.
       (the pointer base cannot validly point to an offset less than zero
--- 650,665 ----
     if non-NULL are the complete memory reference trees.  */
  
  static bool
! indirect_ref_may_alias_decl_p (tree ref1, tree base1,
  			       HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
  			       alias_set_type base1_alias_set,
  			       tree ref2, tree base2,
  			       HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2,
  			       alias_set_type base2_alias_set)
  {
+   tree ptr1 = TREE_OPERAND (base1, 0);
+   tree ptrtype1;
+ 
    /* If only one reference is based on a variable, they cannot alias if
       the pointer access is beyond the extent of the variable access.
       (the pointer base cannot validly point to an offset less than zero
*************** indirect_ref_may_alias_decl_p (tree ref1
*** 667,675 ****
    if (!flag_strict_aliasing)
      return true;
  
    /* If the alias set for a pointer access is zero all bets are off.  */
    if (base1_alias_set == -1)
!     base1_alias_set = get_deref_alias_set (ptr1);
    if (base1_alias_set == 0)
      return true;
    if (base2_alias_set == -1)
--- 675,688 ----
    if (!flag_strict_aliasing)
      return true;
  
+   if (TREE_CODE (base1) == MEM_REF)
+     ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
+   else
+     ptrtype1 = TREE_TYPE (ptr1);
+ 
    /* If the alias set for a pointer access is zero all bets are off.  */
    if (base1_alias_set == -1)
!     base1_alias_set = get_deref_alias_set (ptrtype1);
    if (base1_alias_set == 0)
      return true;
    if (base2_alias_set == -1)
*************** indirect_ref_may_alias_decl_p (tree ref1
*** 678,684 ****
    /* If both references are through the same type, they do not alias
       if the accesses do not overlap.  This does extra disambiguation
       for mixed/pointer accesses but requires strict aliasing.  */
!   if (same_type_for_tbaa (TREE_TYPE (TREE_TYPE (ptr1)),
  			  TREE_TYPE (base2)) == 1)
      return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
  
--- 691,697 ----
    /* If both references are through the same type, they do not alias
       if the accesses do not overlap.  This does extra disambiguation
       for mixed/pointer accesses but requires strict aliasing.  */
!   if (same_type_for_tbaa (TREE_TYPE (ptrtype1),
  			  TREE_TYPE (base2)) == 1)
      return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
  
*************** indirect_ref_may_alias_decl_p (tree ref1
*** 692,698 ****
    if (ref1 && ref2
        && handled_component_p (ref1)
        && handled_component_p (ref2))
!     return aliasing_component_refs_p (ref1, TREE_TYPE (TREE_TYPE (ptr1)),
  				      offset1, max_size1,
  				      ref2, TREE_TYPE (base2),
  				      offset2, max_size2);
--- 705,711 ----
    if (ref1 && ref2
        && handled_component_p (ref1)
        && handled_component_p (ref2))
!     return aliasing_component_refs_p (ref1, TREE_TYPE (ptrtype1),
  				      offset1, max_size1,
  				      ref2, TREE_TYPE (base2),
  				      offset2, max_size2);
*************** indirect_ref_may_alias_decl_p (tree ref1
*** 708,720 ****
     if non-NULL are the complete memory reference trees. */
  
  static bool
! indirect_refs_may_alias_p (tree ref1, tree ptr1,
  			   HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
  			   alias_set_type base1_alias_set,
! 			   tree ref2, tree ptr2,
  			   HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2,
  			   alias_set_type base2_alias_set)
  {
    /* If both bases are based on pointers they cannot alias if they may not
       point to the same memory object or if they point to the same object
       and the accesses do not overlap.  */
--- 721,737 ----
     if non-NULL are the complete memory reference trees. */
  
  static bool
! indirect_refs_may_alias_p (tree ref1, tree base1,
  			   HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
  			   alias_set_type base1_alias_set,
! 			   tree ref2, tree base2,
  			   HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2,
  			   alias_set_type base2_alias_set)
  {
+   tree ptr1 = TREE_OPERAND (base1, 0);
+   tree ptr2 = TREE_OPERAND (base2, 0);
+   tree ptrtype1, ptrtype2;
+ 
    /* If both bases are based on pointers they cannot alias if they may not
       point to the same memory object or if they point to the same object
       and the accesses do not overlap.  */
*************** indirect_refs_may_alias_p (tree ref1, tr
*** 727,747 ****
    if (!flag_strict_aliasing)
      return true;
  
    /* If the alias set for a pointer access is zero all bets are off.  */
    if (base1_alias_set == -1)
!     base1_alias_set = get_deref_alias_set (ptr1);
    if (base1_alias_set == 0)
      return true;
    if (base2_alias_set == -1)
!     base2_alias_set = get_deref_alias_set (ptr2);
    if (base2_alias_set == 0)
      return true;
  
    /* If both references are through the same type, they do not alias
       if the accesses do not overlap.  This does extra disambiguation
       for mixed/pointer accesses but requires strict aliasing.  */
!   if (same_type_for_tbaa (TREE_TYPE (TREE_TYPE (ptr1)),
! 			  TREE_TYPE (TREE_TYPE (ptr2))) == 1)
      return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
  
    /* Do type-based disambiguation.  */
--- 744,773 ----
    if (!flag_strict_aliasing)
      return true;
  
+   if (TREE_CODE (base1) == MEM_REF)
+     ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
+   else
+     ptrtype1 = TREE_TYPE (ptr1);
+   if (TREE_CODE (base2) == MEM_REF)
+     ptrtype2 = TREE_TYPE (TREE_OPERAND (base2, 1));
+   else
+     ptrtype2 = TREE_TYPE (ptr2);
+ 
    /* If the alias set for a pointer access is zero all bets are off.  */
    if (base1_alias_set == -1)
!     base1_alias_set = get_deref_alias_set (ptrtype1);
    if (base1_alias_set == 0)
      return true;
    if (base2_alias_set == -1)
!     base2_alias_set = get_deref_alias_set (ptrtype2);
    if (base2_alias_set == 0)
      return true;
  
    /* If both references are through the same type, they do not alias
       if the accesses do not overlap.  This does extra disambiguation
       for mixed/pointer accesses but requires strict aliasing.  */
!   if (same_type_for_tbaa (TREE_TYPE (ptrtype1),
! 			  TREE_TYPE (ptrtype2)) == 1)
      return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
  
    /* Do type-based disambiguation.  */
*************** indirect_refs_may_alias_p (tree ref1, tr
*** 753,761 ****
    if (ref1 && ref2
        && handled_component_p (ref1)
        && handled_component_p (ref2))
!     return aliasing_component_refs_p (ref1, TREE_TYPE (TREE_TYPE (ptr1)),
  				      offset1, max_size1,
! 				      ref2, TREE_TYPE (TREE_TYPE (ptr2)),
  				      offset2, max_size2);
  
    return true;
--- 779,787 ----
    if (ref1 && ref2
        && handled_component_p (ref1)
        && handled_component_p (ref2))
!     return aliasing_component_refs_p (ref1, TREE_TYPE (ptrtype1),
  				      offset1, max_size1,
! 				      ref2, TREE_TYPE (ptrtype2),
  				      offset2, max_size2);
  
    return true;
*************** refs_may_alias_p_1 (ao_ref *ref1, ao_ref
*** 776,787 ****
--- 802,815 ----
  	       || SSA_VAR_P (ref1->ref)
  	       || handled_component_p (ref1->ref)
  	       || INDIRECT_REF_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)
  		  || INDIRECT_REF_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)
      {
--- 848,860 ----
      return decl_refs_may_alias_p (base1, offset1, max_size1,
  				  base2, offset2, max_size2);
  
!   ind1_p = INDIRECT_REF_P (base1) || (TREE_CODE (base1) == MEM_REF);
!   ind2_p = INDIRECT_REF_P (base2) || (TREE_CODE (base2) == MEM_REF);
!   if (TREE_CODE (base1) == MEM_REF)
!     offset1 += TREE_INT_CST_LOW (TREE_OPERAND (base1, 1)) * BITS_PER_UNIT;
!   if (TREE_CODE (base2) == MEM_REF)
!     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
*** 908,921 ****
    /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators.  */
    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 ();
--- 941,954 ----
    /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators.  */
    set = tbaa_p ? -1 : 0;
    if (var1_p && ind2_p)
!     return indirect_ref_may_alias_decl_p (ref2->ref, base2,
  					  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, base1,
  				      offset1, max_size1, set,
! 				      ref2->ref, base2,
  				      offset2, max_size2, set);
  
    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));
--- 1112,1119 ----
  	  if (is_call_used (base))
  	    return true;
  	}
!       else if ((INDIRECT_REF_P (base)
! 		|| 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));
--- 1135,1142 ----
  	  if (is_call_clobbered (base))
  	    return true;
  	}
!       else if ((INDIRECT_REF_P (base)
! 		|| 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;
--- 1305,1312 ----
  	      if (DECL_P (base)
  		  && !TREE_STATIC (base))
  		return true;
! 	      else if ((INDIRECT_REF_P (base)
! 			|| 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));
--- 1385,1392 ----
  
    if (DECL_P (base))
      return is_call_clobbered (base);
!   else if ((INDIRECT_REF_P (base)
! 	    || 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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-loop-im.c	2010-03-22 13:40:13.000000000 +0100
*************** for_each_index (tree *addr_p, bool (*cbc
*** 276,282 ****
  
  	case MISALIGNED_INDIRECT_REF:
  	case ALIGN_INDIRECT_REF:
! 	case INDIRECT_REF:
  	  nxt = &TREE_OPERAND (*addr_p, 0);
  	  return cbck (*addr_p, nxt, data);
  
--- 276,282 ----
  
  	case MISALIGNED_INDIRECT_REF:
  	case ALIGN_INDIRECT_REF:
! 	case MEM_REF:
  	  nxt = &TREE_OPERAND (*addr_p, 0);
  	  return cbck (*addr_p, nxt, data);
  
*************** gen_lsm_tmp_name (tree ref)
*** 1749,1759 ****
      {
      case MISALIGNED_INDIRECT_REF:
      case ALIGN_INDIRECT_REF:
!     case INDIRECT_REF:
        gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
        lsm_tmp_name_add ("_");
        break;
  
      case BIT_FIELD_REF:
      case VIEW_CONVERT_EXPR:
      case ARRAY_RANGE_REF:
--- 1749,1763 ----
      {
      case MISALIGNED_INDIRECT_REF:
      case ALIGN_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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-loop-ivopts.c	2010-03-22 13:40:13.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-operands.c	2010-03-22 13:40:13.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,743 ----
    /* 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|opf_not_non_addressable)));
  }
  
  
*************** get_asm_expr_operands (gimple stmt)
*** 795,807 ****
        /* 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);
      }
  
    /* Gather all input operands.  */
--- 809,817 ----
        /* 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 | opf_not_non_addressable);
      }
  
    /* Gather all input operands.  */
*************** get_asm_expr_operands (gimple stmt)
*** 815,827 ****
        /* 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);
      }
  
    /* Clobber all memory and addressable symbols for asm ("" : : : "memory");  */
--- 825,833 ----
        /* 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_not_non_addressable);
      }
  
    /* Clobber all memory and addressable symbols for asm ("" : : : "memory");  */
*************** 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
--- 871,879 ----
  	 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:
--- 887,894 ----
  	 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
*** 902,907 ****
--- 911,917 ----
  
      case ALIGN_INDIRECT_REF:
      case INDIRECT_REF:
+     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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-pre.c	2010-03-22 13:40:13.000000000 +0100
*************** create_component_ref_by_pieces_1 (basic_
*** 2697,2702 ****
--- 2697,2724 ----
  	return folded;
        }
        break;
+     case MEM_REF:
+       {
+ 	tree baseop = create_component_ref_by_pieces_1 (block, ref, operand,
+ 							stmts, domstmt);
+ 	tree offset = currop->op0;
+ 	if (!baseop)
+ 	  return NULL_TREE;
+ 	if (TREE_CODE (baseop) == ADDR_EXPR
+ 	    && handled_component_p (TREE_OPERAND (baseop, 0)))
+ 	  {
+ 	    HOST_WIDE_INT off;
+ 	    tree base;
+ 	    base = get_addr_base_and_offset (TREE_OPERAND (baseop, 0), &off);
+ 	    gcc_assert (base && off % BITS_PER_UNIT == 0);
+ 	    offset = int_const_binop (PLUS_EXPR, offset,
+ 				      build_int_cst (TREE_TYPE (offset),
+ 						     off / BITS_PER_UNIT), 0);
+ 	    baseop = build_fold_addr_expr (base);
+ 	  }
+ 	return build2 (MEM_REF, currop->type, baseop, offset);
+       }
+       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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-sccvn.c	2010-03-22 13:40:13.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-sink.c	2010-03-22 13:40:13.000000000 +0100
*************** is_hidden_global_store (gimple stmt)
*** 192,199 ****
  	    return true;
  
  	}
!       else if (INDIRECT_REF_P (lhs))
  	return ptr_deref_may_alias_global_p (TREE_OPERAND (lhs, 0));
        else
  	gcc_unreachable ();
      }
--- 192,202 ----
  	    return true;
  
  	}
!       else if (INDIRECT_REF_P (lhs)
! 	       || TREE_CODE (lhs) == MEM_REF)
  	return ptr_deref_may_alias_global_p (TREE_OPERAND (lhs, 0));
+       else if (CONSTANT_CLASS_P (lhs))
+ 	return true;
        else
  	gcc_unreachable ();
      }
Index: trunk/gcc/tree-ssa.c
===================================================================
*** trunk.orig/gcc/tree-ssa.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa.c	2010-03-22 13:40:13.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree.def	2010-03-22 13:40:13.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-ccp.c	2010-03-22 13:40:13.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,2519 ----
  	}
      }
  
+   /* Strip constant-offset component refs.  */
+   if (TREE_CODE (*t) == MEM_REF
+       && handled_component_p (expr)
+       /* We can't properly expand these.  */
+       && !((TREE_CODE (expr) == COMPONENT_REF
+ 	    && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
+ 	   || TREE_CODE (expr) == BIT_FIELD_REF))
+     {
+       tree base;
+       HOST_WIDE_INT offset;
+       base = get_addr_base_and_offset (expr, &offset);
+       if (base
+ 	  && 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;
  }
  
*************** fold_gimple_assign (gimple_stmt_iterator
*** 2821,2830 ****
  
  	else if (TREE_CODE (rhs) == ADDR_EXPR)
  	  {
! 	    tree tem = maybe_fold_reference (TREE_OPERAND (rhs, 0), true);
! 	    if (tem)
  	      result = fold_convert (TREE_TYPE (rhs),
  				     build_fold_addr_expr_loc (loc, tem));
  	  }
  
  	else if (TREE_CODE (rhs) == CONSTRUCTOR
--- 2890,2914 ----
  
  	else if (TREE_CODE (rhs) == ADDR_EXPR)
  	  {
! 	    tree ref = TREE_OPERAND (rhs, 0);
! 	    tree tem = maybe_fold_reference (ref, true);
! 	    if (tem
! 		&& TREE_CODE (tem) == MEM_REF)
! 	      {
! 		ref = tem;
! 		goto do_mem_ref;
! 	      }
! 	    else if (tem)
  	      result = fold_convert (TREE_TYPE (rhs),
  				     build_fold_addr_expr_loc (loc, tem));
+ 	    else if (TREE_CODE (ref) == MEM_REF)
+ 	      {
+ do_mem_ref:
+ 		result = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rhs),
+ 				      TREE_OPERAND (ref, 0),
+ 				      fold_convert (sizetype,
+ 						    TREE_OPERAND (ref, 1)));
+ 	      }
  	  }
  
  	else if (TREE_CODE (rhs) == CONSTRUCTOR
Index: trunk/gcc/tree-dfa.c
===================================================================
*** trunk.orig/gcc/tree-dfa.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-dfa.c	2010-03-22 14:22:46.000000000 +0100
*************** get_ref_base_and_extent (tree exp, HOST_
*** 877,882 ****
--- 877,899 ----
  	case VIEW_CONVERT_EXPR:
  	  break;
  
+ 	case MEM_REF:
+ 	  /* ???  We should avoid doing this when doing so hides 
+ 	     the effective alias set.  */
+ 	  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;
  	}
*************** get_ref_base_and_extent (tree exp, HOST_
*** 923,928 ****
--- 940,966 ----
    return exp;
  }
  
+ /* Returns the base object and a constant offset in *POFFSET that
+    denotes the starting address of the memory access EXP.
+    Returns NULL_TREE if the offset is not constant.  */
+ 
+ tree
+ get_addr_base_and_offset (tree exp, HOST_WIDE_INT *poffset)
+ {
+   tree base;
+   HOST_WIDE_INT size;
+   tree ncoffset;
+   enum machine_mode mode;
+   int dummy;
+ 
+   base = get_inner_reference (exp, &size, poffset, &ncoffset,
+ 			      &mode, &dummy, &dummy, false);
+   if (ncoffset != NULL_TREE)
+     return NULL_TREE;
+ 
+   return base;
+ }
+ 
  /* Returns true if STMT references an SSA_NAME that has
     SSA_NAME_OCCURS_IN_ABNORMAL_PHI set, otherwise false.  */
  
Index: trunk/gcc/tree-nested.c
===================================================================
*** trunk.orig/gcc/tree-nested.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-nested.c	2010-03-22 13:40:13.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-dce.c	2010-03-22 13:40:13.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-stdarg.c	2010-03-22 13:40:14.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-vect-stmts.c	2010-03-22 13:40:14.000000000 +0100
*************** vectorizable_store (gimple stmt, gimple_
*** 2942,2948 ****
        && TREE_CODE (scalar_dest) != INDIRECT_REF
        && TREE_CODE (scalar_dest) != COMPONENT_REF
        && TREE_CODE (scalar_dest) != IMAGPART_EXPR
!       && TREE_CODE (scalar_dest) != REALPART_EXPR)
      return false;
  
    gcc_assert (gimple_assign_single_p (stmt));
--- 2942,2949 ----
        && TREE_CODE (scalar_dest) != INDIRECT_REF
        && TREE_CODE (scalar_dest) != COMPONENT_REF
        && TREE_CODE (scalar_dest) != IMAGPART_EXPR
!       && TREE_CODE (scalar_dest) != REALPART_EXPR
!       && TREE_CODE (scalar_dest) != MEM_REF)
      return false;
  
    gcc_assert (gimple_assign_single_p (stmt));
*************** 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);
--- 3194,3200 ----
  	    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
*** 3332,3338 ****
        && code != INDIRECT_REF
        && code != COMPONENT_REF
        && code != IMAGPART_EXPR
!       && code != REALPART_EXPR)
      return false;
  
    if (!STMT_VINFO_DATA_REF (stmt_info))
--- 3333,3340 ----
        && code != INDIRECT_REF
        && code != COMPONENT_REF
        && code != IMAGPART_EXPR
!       && code != REALPART_EXPR
!       && code != MEM_REF)
      return false;
  
    if (!STMT_VINFO_DATA_REF (stmt_info))
*************** 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:
  	      {
--- 3572,3578 ----
  	    {
  	    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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree.c	2010-03-22 13:40:14.000000000 +0100
*************** build6_stat (enum tree_code code, tree t
*** 3832,3837 ****
--- 3832,3864 ----
    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)
+ {
+   HOST_WIDE_INT offset = 0;
+   tree ptype = TREE_TYPE (ptr);
+   tree tem;
+   /* For convenience allow invariant addresses with component-refs.  */
+   if (TREE_CODE (ptr) == ADDR_EXPR
+       && handled_component_p (TREE_OPERAND (ptr, 0)))
+     {
+       HOST_WIDE_INT size, max_size;
+       gcc_assert (is_gimple_min_invariant (ptr));
+       ptr = get_ref_base_and_extent (TREE_OPERAND (ptr, 0), &offset,
+ 				     &size, &max_size);
+       gcc_assert (SSA_VAR_P (ptr) && offset % BITS_PER_UNIT == 0);
+       offset = offset / BITS_PER_UNIT;
+       ptr = build_fold_addr_expr (ptr);
+     }
+   tem = build2 (MEM_REF, TREE_TYPE (ptype),
+ 		ptr, build_int_cst (ptype, offset));
+   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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree.h	2010-03-22 13:40:14.000000000 +0100
*************** extern tree build_fold_indirect_ref_loc
*** 4886,4891 ****
--- 4886,4894 ----
  #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-22 13:36:55.000000000 +0100
--- trunk/gcc/cfgexpand.c	2010-03-22 13:40:14.000000000 +0100
*************** expand_debug_expr (tree exp)
*** 2418,2423 ****
--- 2418,2428 ----
  	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-22 13:36:55.000000000 +0100
--- trunk/gcc/config/i386/i386.c	2010-03-22 13:40:14.000000000 +0100
*************** ix86_va_start (tree valist, rtx nextarg)
*** 6928,6938 ****
    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);
!   sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
  
    /* Count number of gp and fp argument registers used.  */
    words = crtl->args.info.words;
--- 6928,6944 ----
    f_ovf = TREE_CHAIN (f_fpr);
    f_sav = TREE_CHAIN (f_ovf);
  
!   valist = build_simple_mem_ref (valist);
!   TREE_TYPE (valist) = TREE_TYPE (sysv_va_list_type_node);
!   /* The following should be folded into the MEM_REF offset.  */
!   gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), unshare_expr (valist),
! 		f_gpr, NULL_TREE);
!   fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), unshare_expr (valist),
! 		f_fpr, NULL_TREE);
!   ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), unshare_expr (valist),
! 		f_ovf, NULL_TREE);
!   sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), unshare_expr (valist),
! 		f_sav, NULL_TREE);
  
    /* Count number of gp and fp argument registers used.  */
    words = crtl->args.info.words;
*************** ix86_canonical_va_list_type (tree type)
*** 30205,30210 ****
--- 30211,30218 ----
      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-22 13:36:55.000000000 +0100
--- trunk/gcc/dwarf2out.c	2010-03-22 13:40:14.000000000 +0100
*************** loc_list_from_tree (tree loc, int want_a
*** 14491,14496 ****
--- 14491,14501 ----
        }
        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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-forwprop.c	2010-03-22 13:40:14.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-eh.c	2010-03-22 13:40:14.000000000 +0100
*************** tree_could_trap_p (tree expr)
*** 2419,2424 ****
--- 2419,2428 ----
  	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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-sra.c	2010-03-22 13:40:14.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 */
*************** static bool
*** 1066,1072 ****
  asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
  		void *data ATTRIBUTE_UNUSED)
  {
!   if (DECL_P (op))
      disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
  
    return false;
--- 1067,1075 ----
  asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
  		void *data ATTRIBUTE_UNUSED)
  {
!   op = get_base_address (op);
!   if (op
!       && DECL_P (op))
      disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
  
    return false;
*************** 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
--- 1375,1380 ----
*************** 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.  */
--- 1392,1427 ----
  {
    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;
  }
  
  
--- 2767,2773 ----
  static bool
  gate_intra_sra (void)
  {
!   return 0 && flag_tree_sra != 0;
  }
  
  
*************** sra_ipa_modify_expr (tree *expr, gimple_
*** 3830,3835 ****
--- 3758,3769 ----
    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)
*** 4219,4225 ****
  static bool
  ipa_early_sra_gate (void)
  {
!   return flag_ipa_sra;
  }
  
  struct gimple_opt_pass pass_early_ipa_sra =
--- 4153,4159 ----
  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-03-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-ssa-structalias.c	2010-03-22 13:40:14.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-03-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-complex.c	2010-03-22 13:40:14.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-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-inline.c	2010-03-22 13:40:14.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-22 13:36:55.000000000 +0100
--- trunk/gcc/builtins.c	2010-03-22 13:40:14.000000000 +0100
*************** stabilize_va_list_loc (location_t loc, t
*** 4353,4359 ****
--- 4353,4366 ----
  {
    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)
      {
Index: trunk/gcc/tree-data-ref.c
===================================================================
*** trunk.orig/gcc/tree-data-ref.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-data-ref.c	2010-03-22 13:40:14.000000000 +0100
*************** dr_analyze_indices (struct data_referenc
*** 846,858 ****
        aref = TREE_OPERAND (aref, 0);
      }
  
!   if (nest && INDIRECT_REF_P (aref))
      {
        op = TREE_OPERAND (aref, 0);
        access_fn = analyze_scalar_evolution (loop, op);
        access_fn = instantiate_scev (before_loop, loop, access_fn);
        base = initial_condition (access_fn);
        split_constant_offset (base, &base, &off);
        access_fn = chrec_replace_initial_condition (access_fn,
  			fold_convert (TREE_TYPE (base), off));
  
--- 846,863 ----
        aref = TREE_OPERAND (aref, 0);
      }
  
!   if (nest
!       && (INDIRECT_REF_P (aref)
! 	  || TREE_CODE (aref) == MEM_REF))
      {
        op = TREE_OPERAND (aref, 0);
        access_fn = analyze_scalar_evolution (loop, op);
        access_fn = instantiate_scev (before_loop, loop, access_fn);
        base = initial_condition (access_fn);
        split_constant_offset (base, &base, &off);
+       if (TREE_CODE (aref) == MEM_REF)
+ 	off = size_binop (PLUS_EXPR, off,
+ 			  fold_convert (ssizetype, TREE_OPERAND (aref, 1)));
        access_fn = chrec_replace_initial_condition (access_fn,
  			fold_convert (TREE_TYPE (base), off));
  
Index: trunk/gcc/cgraphunit.c
===================================================================
*** trunk.orig/gcc/cgraphunit.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/cgraphunit.c	2010-03-22 13:40:14.000000000 +0100
*************** thunk_adjust (gimple_stmt_iterator * bsi
*** 1279,1286 ****
        vtabletmp2 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp)),
  				   "vtableaddr");
        stmt = gimple_build_assign (vtabletmp2,
! 				  build1 (INDIRECT_REF,
! 					  TREE_TYPE (vtabletmp2), vtabletmp));
        gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
        mark_symbols_for_renaming (stmt);
        find_referenced_vars_in (stmt);
--- 1279,1285 ----
        vtabletmp2 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp)),
  				   "vtableaddr");
        stmt = gimple_build_assign (vtabletmp2,
! 				  build_simple_mem_ref (vtabletmp));
        gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
        mark_symbols_for_renaming (stmt);
        find_referenced_vars_in (stmt);
*************** thunk_adjust (gimple_stmt_iterator * bsi
*** 1299,1307 ****
        vtabletmp3 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp2)),
  				   "vcalloffset");
        stmt = gimple_build_assign (vtabletmp3,
! 				  build1 (INDIRECT_REF,
! 					  TREE_TYPE (vtabletmp3),
! 					  vtabletmp2));
        gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
        mark_symbols_for_renaming (stmt);
        find_referenced_vars_in (stmt);
--- 1298,1304 ----
        vtabletmp3 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp2)),
  				   "vcalloffset");
        stmt = gimple_build_assign (vtabletmp3,
! 				  build_simple_mem_ref (vtabletmp2));
        gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
        mark_symbols_for_renaming (stmt);
        find_referenced_vars_in (stmt);
Index: trunk/gcc/ipa-prop.c
===================================================================
*** trunk.orig/gcc/ipa-prop.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/ipa-prop.c	2010-03-22 13:40:14.000000000 +0100
*************** visit_store_addr_for_mod_analysis (gimpl
*** 198,204 ****
  {
    struct ipa_node_params *info = (struct ipa_node_params *) data;
  
!   if (TREE_CODE (op) == PARM_DECL)
      {
        int index = ipa_get_param_decl_index (info, op);
        gcc_assert (index >= 0);
--- 198,206 ----
  {
    struct ipa_node_params *info = (struct ipa_node_params *) data;
  
!   op = get_base_address (op);
!   if (op
!       && TREE_CODE (op) == PARM_DECL)
      {
        int index = ipa_get_param_decl_index (info, op);
        gcc_assert (index >= 0);
Index: trunk/gcc/ipa-reference.c
===================================================================
*** trunk.orig/gcc/ipa-reference.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/ipa-reference.c	2010-03-22 13:40:14.000000000 +0100
*************** static bool
*** 351,359 ****
  mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
  	      void *data ATTRIBUTE_UNUSED)
  {
!   while (handled_component_p (addr))
!     addr = TREE_OPERAND (addr, 0);
!   mark_address_taken (addr);
    return false;
  }
  
--- 351,359 ----
  mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
  	      void *data ATTRIBUTE_UNUSED)
  {
!   addr = get_base_address (addr);
!   if (addr)
!     mark_address_taken (addr);
    return false;
  }
  
Index: trunk/gcc/omp-low.c
===================================================================
*** trunk.orig/gcc/omp-low.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/omp-low.c	2010-03-22 13:40:14.000000000 +0100
*************** build_receiver_ref (tree var, bool by_re
*** 863,872 ****
    if (x != NULL)
      field = x;
  
!   x = build_fold_indirect_ref (ctx->receiver_decl);
    x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
    if (by_ref)
!     x = build_fold_indirect_ref (x);
  
    return x;
  }
--- 863,872 ----
    if (x != NULL)
      field = x;
  
!   x = build_simple_mem_ref (ctx->receiver_decl);
    x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
    if (by_ref)
!     x = build_simple_mem_ref (x);
  
    return x;
  }
*************** build_outer_var_ref (tree var, omp_conte
*** 886,892 ****
      {
        x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
        x = build_outer_var_ref (x, ctx);
!       x = build_fold_indirect_ref (x);
      }
    else if (is_taskreg_ctx (ctx))
      {
--- 886,892 ----
      {
        x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
        x = build_outer_var_ref (x, ctx);
!       x = build_simple_mem_ref (x);
      }
    else if (is_taskreg_ctx (ctx))
      {
*************** build_outer_var_ref (tree var, omp_conte
*** 903,909 ****
      gcc_unreachable ();
  
    if (is_reference (var))
!     x = build_fold_indirect_ref (x);
  
    return x;
  }
--- 903,909 ----
      gcc_unreachable ();
  
    if (is_reference (var))
!     x = build_simple_mem_ref (x);
  
    return x;
  }
*************** scan_omp_1_op (tree *tp, int *walk_subtr
*** 1933,1939 ****
  	{
  	  *walk_subtrees = 1;
  	  if (ctx)
! 	    TREE_TYPE (t) = remap_type (TREE_TYPE (t), &ctx->cb);
  	}
        break;
      }
--- 1933,1950 ----
  	{
  	  *walk_subtrees = 1;
  	  if (ctx)
! 	    {
! 	      tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
! 	      if (tem != TREE_TYPE (t))
! 		{
! 		  if (TREE_CODE (t) == INTEGER_CST)
! 		    *tp = build_int_cst_wide (tem,
! 					      TREE_INT_CST_LOW (t),
! 					      TREE_INT_CST_HIGH (t));
! 		  else
! 		    TREE_TYPE (t) = tem;
! 		}
! 	    }
  	}
        break;
      }
*************** lower_rec_input_clauses (tree clauses, g
*** 2354,2360 ****
  	      x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
  	      gimplify_assign (new_var, x, ilist);
  
! 	      new_var = build_fold_indirect_ref_loc (clause_loc, new_var);
  	    }
  	  else if (c_kind == OMP_CLAUSE_REDUCTION
  		   && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
--- 2365,2371 ----
  	      x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
  	      gimplify_assign (new_var, x, ilist);
  
! 	      new_var = build_simple_mem_ref_loc (clause_loc, new_var);
  	    }
  	  else if (c_kind == OMP_CLAUSE_REDUCTION
  		   && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
*************** lower_lastprivate_clauses (tree clauses,
*** 2572,2578 ****
  
  	  x = build_outer_var_ref (var, ctx);
  	  if (is_reference (var))
! 	    new_var = build_fold_indirect_ref_loc (clause_loc, new_var);
  	  x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
  	  gimplify_and_add (x, stmt_list);
  	}
--- 2583,2589 ----
  
  	  x = build_outer_var_ref (var, ctx);
  	  if (is_reference (var))
! 	    new_var = build_simple_mem_ref_loc (clause_loc, new_var);
  	  x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
  	  gimplify_and_add (x, stmt_list);
  	}
*************** lower_reduction_clauses (tree clauses, g
*** 2639,2645 ****
        var = OMP_CLAUSE_DECL (c);
        new_var = lookup_decl (var, ctx);
        if (is_reference (var))
! 	new_var = build_fold_indirect_ref_loc (clause_loc, new_var);
        ref = build_outer_var_ref (var, ctx);
        code = OMP_CLAUSE_REDUCTION_CODE (c);
  
--- 2650,2656 ----
        var = OMP_CLAUSE_DECL (c);
        new_var = lookup_decl (var, ctx);
        if (is_reference (var))
! 	new_var = build_simple_mem_ref_loc (clause_loc, new_var);
        ref = build_outer_var_ref (var, ctx);
        code = OMP_CLAUSE_REDUCTION_CODE (c);
  
*************** lower_copyprivate_clauses (tree clauses,
*** 2719,2726 ****
        ref = build_receiver_ref (var, by_ref, ctx);
        if (is_reference (var))
  	{
! 	  ref = build_fold_indirect_ref_loc (clause_loc, ref);
! 	  var = build_fold_indirect_ref_loc (clause_loc, var);
  	}
        x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
        gimplify_and_add (x, rlist);
--- 2730,2737 ----
        ref = build_receiver_ref (var, by_ref, ctx);
        if (is_reference (var))
  	{
! 	  ref = build_simple_mem_ref_loc (clause_loc, ref);
! 	  var = build_simple_mem_ref_loc (clause_loc, var);
  	}
        x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
        gimplify_and_add (x, rlist);
*************** expand_omp_atomic_pipeline (basic_block
*** 5072,5079 ****
        loadedi = loaded_val;
      }
  
!   initial = force_gimple_operand_gsi (&si, build_fold_indirect_ref (iaddr),
! 				      true, NULL_TREE, true, GSI_SAME_STMT);
  
    /* Move the value to the LOADEDI temporary.  */
    if (gimple_in_ssa_p (cfun))
--- 5083,5094 ----
        loadedi = loaded_val;
      }
  
!   initial
!     = force_gimple_operand_gsi (&si,
! 				build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
! 					iaddr,
! 					build_int_cst (TREE_TYPE (iaddr), 0)),
! 				true, NULL_TREE, true, GSI_SAME_STMT);
  
    /* Move the value to the LOADEDI temporary.  */
    if (gimple_in_ssa_p (cfun))
*************** expand_omp_atomic_mutex (basic_block loa
*** 5217,5231 ****
    t = build_function_call_expr (UNKNOWN_LOCATION, t, 0);
    force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
  
!   stmt = gimple_build_assign (loaded_val, build_fold_indirect_ref (addr));
    gsi_insert_before (&si, stmt, GSI_SAME_STMT);
    gsi_remove (&si, true);
  
    si = gsi_last_bb (store_bb);
    gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
  
!   stmt = gimple_build_assign (build_fold_indirect_ref (unshare_expr (addr)),
! 				stored_val);
    gsi_insert_before (&si, stmt, GSI_SAME_STMT);
  
    t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
--- 5232,5246 ----
    t = build_function_call_expr (UNKNOWN_LOCATION, t, 0);
    force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
  
!   stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
    gsi_insert_before (&si, stmt, GSI_SAME_STMT);
    gsi_remove (&si, true);
  
    si = gsi_last_bb (store_bb);
    gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
  
!   stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
! 			      stored_val);
    gsi_insert_before (&si, stmt, GSI_SAME_STMT);
  
    t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
*************** create_task_copyfn (gimple task_stmt, om
*** 6272,6278 ****
  	  n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
  	  sf = (tree) n->value;
  	  sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	  src = build_fold_indirect_ref_loc (loc, sarg);
  	  src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
  	  t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
  	  append_to_statement_list (t, &list);
--- 6287,6293 ----
  	  n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
  	  sf = (tree) n->value;
  	  sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	  src = build_simple_mem_ref_loc (loc, sarg);
  	  src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
  	  t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
  	  append_to_statement_list (t, &list);
*************** create_task_copyfn (gimple task_stmt, om
*** 6295,6303 ****
  	sf = (tree) n->value;
  	if (tcctx.cb.decl_map)
  	  sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	src = build_fold_indirect_ref_loc (loc, sarg);
  	src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
! 	dst = build_fold_indirect_ref_loc (loc, arg);
  	dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
  	t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
  	append_to_statement_list (t, &list);
--- 6310,6318 ----
  	sf = (tree) n->value;
  	if (tcctx.cb.decl_map)
  	  sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	src = build_simple_mem_ref_loc (loc, sarg);
  	src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
! 	dst = build_simple_mem_ref_loc (loc, arg);
  	dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
  	t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
  	append_to_statement_list (t, &list);
*************** create_task_copyfn (gimple task_stmt, om
*** 6318,6331 ****
  	    sf = (tree) n->value;
  	    if (tcctx.cb.decl_map)
  	      sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	    src = build_fold_indirect_ref_loc (loc, sarg);
  	    src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
  	    if (use_pointer_for_field (decl, NULL) || is_reference (decl))
! 	      src = build_fold_indirect_ref_loc (loc, src);
  	  }
  	else
  	  src = decl;
! 	dst = build_fold_indirect_ref_loc (loc, arg);
  	dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
  	t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
  	append_to_statement_list (t, &list);
--- 6333,6346 ----
  	    sf = (tree) n->value;
  	    if (tcctx.cb.decl_map)
  	      sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	    src = build_simple_mem_ref_loc (loc, sarg);
  	    src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
  	    if (use_pointer_for_field (decl, NULL) || is_reference (decl))
! 	      src = build_simple_mem_ref_loc (loc, src);
  	  }
  	else
  	  src = decl;
! 	dst = build_simple_mem_ref_loc (loc, arg);
  	dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
  	t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
  	append_to_statement_list (t, &list);
*************** create_task_copyfn (gimple task_stmt, om
*** 6344,6357 ****
  	    sf = (tree) n->value;
  	    if (tcctx.cb.decl_map)
  	      sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	    src = build_fold_indirect_ref_loc (loc, sarg);
  	    src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
  	    if (use_pointer_for_field (decl, NULL))
! 	      src = build_fold_indirect_ref_loc (loc, src);
  	  }
  	else
  	  src = decl;
! 	dst = build_fold_indirect_ref_loc (loc, arg);
  	dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
  	t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
  	append_to_statement_list (t, &list);
--- 6359,6372 ----
  	    sf = (tree) n->value;
  	    if (tcctx.cb.decl_map)
  	      sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	    src = build_simple_mem_ref_loc (loc, sarg);
  	    src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
  	    if (use_pointer_for_field (decl, NULL))
! 	      src = build_simple_mem_ref_loc (loc, src);
  	  }
  	else
  	  src = decl;
! 	dst = build_simple_mem_ref_loc (loc, arg);
  	dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
  	t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
  	append_to_statement_list (t, &list);
*************** create_task_copyfn (gimple task_stmt, om
*** 6383,6392 ****
  				 (splay_tree_key) TREE_OPERAND (ind, 0));
  	  sf = (tree) n->value;
  	  sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	  src = build_fold_indirect_ref_loc (loc, sarg);
  	  src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
! 	  src = build_fold_indirect_ref_loc (loc, src);
! 	  dst = build_fold_indirect_ref_loc (loc, arg);
  	  dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
  	  t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
  	  append_to_statement_list (t, &list);
--- 6398,6407 ----
  				 (splay_tree_key) TREE_OPERAND (ind, 0));
  	  sf = (tree) n->value;
  	  sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
! 	  src = build_simple_mem_ref_loc (loc, sarg);
  	  src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
! 	  src = build_simple_mem_ref_loc (loc, src);
! 	  dst = build_simple_mem_ref_loc (loc, arg);
  	  dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
  	  t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
  	  append_to_statement_list (t, &list);
*************** create_task_copyfn (gimple task_stmt, om
*** 6394,6400 ****
  				 (splay_tree_key) TREE_OPERAND (ind, 0));
  	  df = (tree) n->value;
  	  df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
! 	  ptr = build_fold_indirect_ref_loc (loc, arg);
  	  ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL);
  	  t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
  		      build_fold_addr_expr_loc (loc, dst));
--- 6409,6415 ----
  				 (splay_tree_key) TREE_OPERAND (ind, 0));
  	  df = (tree) n->value;
  	  df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
! 	  ptr = build_simple_mem_ref_loc (loc, arg);
  	  ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL);
  	  t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
  		      build_fold_addr_expr_loc (loc, dst));
Index: trunk/gcc/tree-parloops.c
===================================================================
*** trunk.orig/gcc/tree-parloops.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-parloops.c	2010-03-22 13:40:14.000000000 +0100
*************** take_address_of (tree obj, tree type, ed
*** 357,363 ****
  
    if (var_p != &obj)
      {
!       *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name);
        name = force_gimple_operand (build_addr (obj, current_function_decl),
  				   &stmts, true, NULL_TREE);
        if (!gimple_seq_empty_p (stmts))
--- 357,363 ----
  
    if (var_p != &obj)
      {
!       *var_p = build_simple_mem_ref (name);
        name = force_gimple_operand (build_addr (obj, current_function_decl),
  				   &stmts, true, NULL_TREE);
        if (!gimple_seq_empty_p (stmts))
*************** eliminate_local_variables_1 (tree *tp, i
*** 456,462 ****
        type = TREE_TYPE (t);
        addr_type = build_pointer_type (type);
        addr = take_address_of (t, addr_type, dta->entry, dta->decl_address);
!       *tp = build1 (INDIRECT_REF, TREE_TYPE (*tp), addr);
  
        dta->changed = true;
        return NULL_TREE;
--- 456,462 ----
        type = TREE_TYPE (t);
        addr_type = build_pointer_type (type);
        addr = take_address_of (t, addr_type, dta->entry, dta->decl_address);
!       *tp = build_simple_mem_ref (addr);
  
        dta->changed = true;
        return NULL_TREE;
*************** create_call_for_reduction_1 (void **slot
*** 857,863 ****
    struct clsn_data *const clsn_data = (struct clsn_data *) data;
    gimple_stmt_iterator gsi;
    tree type = TREE_TYPE (PHI_RESULT (reduc->reduc_phi));
-   tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
    tree load_struct;
    basic_block bb;
    basic_block new_bb;
--- 857,862 ----
*************** create_call_for_reduction_1 (void **slot
*** 866,872 ****
    tree tmp_load, name;
    gimple load;
  
!   load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
    t = build3 (COMPONENT_REF, type, load_struct, reduc->field, NULL_TREE);
  
    addr = build_addr (t, current_function_decl);
--- 865,871 ----
    tree tmp_load, name;
    gimple load;
  
!   load_struct = build_simple_mem_ref (clsn_data->load);
    t = build3 (COMPONENT_REF, type, load_struct, reduc->field, NULL_TREE);
  
    addr = build_addr (t, current_function_decl);
*************** create_loads_for_reductions (void **slot
*** 925,937 ****
    gimple stmt;
    gimple_stmt_iterator gsi;
    tree type = TREE_TYPE (gimple_assign_lhs (red->reduc_stmt));
-   tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
    tree load_struct;
    tree name;
    tree x;
  
    gsi = gsi_after_labels (clsn_data->load_bb);
!   load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
    load_struct = build3 (COMPONENT_REF, type, load_struct, red->field,
  			NULL_TREE);
  
--- 924,935 ----
    gimple stmt;
    gimple_stmt_iterator gsi;
    tree type = TREE_TYPE (gimple_assign_lhs (red->reduc_stmt));
    tree load_struct;
    tree name;
    tree x;
  
    gsi = gsi_after_labels (clsn_data->load_bb);
!   load_struct = build_simple_mem_ref (clsn_data->load);
    load_struct = build3 (COMPONENT_REF, type, load_struct, red->field,
  			NULL_TREE);
  
*************** create_loads_and_stores_for_name (void *
*** 1012,1018 ****
    gimple stmt;
    gimple_stmt_iterator gsi;
    tree type = TREE_TYPE (elt->new_name);
-   tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
    tree load_struct;
  
    gsi = gsi_last_bb (clsn_data->store_bb);
--- 1010,1015 ----
*************** create_loads_and_stores_for_name (void *
*** 1022,1028 ****
    gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
  
    gsi = gsi_last_bb (clsn_data->load_bb);
!   load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
    t = build3 (COMPONENT_REF, type, load_struct, elt->field, NULL_TREE);
    stmt = gimple_build_assign (elt->new_name, t);
    SSA_NAME_DEF_STMT (elt->new_name) = stmt;
--- 1019,1025 ----
    gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
  
    gsi = gsi_last_bb (clsn_data->load_bb);
!   load_struct = build_simple_mem_ref (clsn_data->load);
    t = build3 (COMPONENT_REF, type, load_struct, elt->field, NULL_TREE);
    stmt = gimple_build_assign (elt->new_name, t);
    SSA_NAME_DEF_STMT (elt->new_name) = stmt;
Index: trunk/gcc/ipa-struct-reorg.c
===================================================================
*** trunk.orig/gcc/ipa-struct-reorg.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/ipa-struct-reorg.c	2010-03-22 13:40:14.000000000 +0100
*************** decompose_indirect_ref_acc (tree str_dec
*** 419,424 ****
--- 419,428 ----
    if (!is_result_of_mult (before_cast, &acc->num, struct_size))
      return false;
  
+   /* ???  Add TREE_OPERAND (acc->ref, 1) to acc->offset.  */
+   if (!integer_zerop (TREE_OPERAND (acc->ref, 1)))
+     return false;
+ 
    return true;
  }
  
*************** decompose_access (tree str_decl, struct
*** 432,438 ****
  {
    gcc_assert (acc->ref);
  
!   if (TREE_CODE (acc->ref) == INDIRECT_REF)
      return decompose_indirect_ref_acc (str_decl, acc);
    else if (TREE_CODE (acc->ref) == ARRAY_REF)
      return true;
--- 436,442 ----
  {
    gcc_assert (acc->ref);
  
!   if (TREE_CODE (acc->ref) == MEM_REF)
      return decompose_indirect_ref_acc (str_decl, acc);
    else if (TREE_CODE (acc->ref) == ARRAY_REF)
      return true;
*************** replace_field_acc (struct field_access_s
*** 967,978 ****
    type_wrapper_t *wr_p = NULL;
    struct ref_pos r_pos;
  
!   while (TREE_CODE (ref_var) == INDIRECT_REF
  	 || TREE_CODE (ref_var) == ARRAY_REF)
      {
        type_wrapper_t wr;
  
!       if ( TREE_CODE (ref_var) == INDIRECT_REF)
  	{
  	  wr.wrap = 0;
  	  wr.domain = 0;
--- 971,982 ----
    type_wrapper_t *wr_p = NULL;
    struct ref_pos r_pos;
  
!   while (TREE_CODE (ref_var) == MEM_REF
  	 || TREE_CODE (ref_var) == ARRAY_REF)
      {
        type_wrapper_t wr;
  
!       if (TREE_CODE (ref_var) == MEM_REF)
  	{
  	  wr.wrap = 0;
  	  wr.domain = 0;
*************** replace_field_acc (struct field_access_s
*** 999,1005 ****
  	new_ref = build4 (ARRAY_REF, type, new_ref,
  			  wr_p->domain, NULL_TREE, NULL_TREE);
        else /* Pointer.  */
! 	new_ref = build1 (INDIRECT_REF, type, new_ref);
        VEC_pop (type_wrapper_t, wrapper);
      }
  
--- 1003,1009 ----
  	new_ref = build4 (ARRAY_REF, type, new_ref,
  			  wr_p->domain, NULL_TREE, NULL_TREE);
        else /* Pointer.  */
! 	new_ref = build_simple_mem_ref (new_ref);
        VEC_pop (type_wrapper_t, wrapper);
      }
  
*************** static void
*** 1039,1045 ****
  replace_field_access_stmt (struct field_access_site *acc, tree new_type)
  {
  
!   if (TREE_CODE (acc->ref) == INDIRECT_REF
        ||TREE_CODE (acc->ref) == ARRAY_REF
        ||TREE_CODE (acc->ref) == VAR_DECL)
      replace_field_acc (acc, new_type);
--- 1043,1049 ----
  replace_field_access_stmt (struct field_access_site *acc, tree new_type)
  {
  
!   if (TREE_CODE (acc->ref) == MEM_REF
        ||TREE_CODE (acc->ref) == ARRAY_REF
        ||TREE_CODE (acc->ref) == VAR_DECL)
      replace_field_acc (acc, new_type);
*************** insert_new_var_in_stmt (gimple stmt, tre
*** 1275,1287 ****
    pos = find_pos_in_stmt (stmt, var, &r_pos);
    gcc_assert (pos);
  
!   while (r_pos.container && (TREE_CODE(r_pos.container) == INDIRECT_REF
  			     || TREE_CODE(r_pos.container) == ADDR_EXPR))
      {
!       tree type = TREE_TYPE (TREE_TYPE (new_var));
! 
!       if (TREE_CODE(r_pos.container) == INDIRECT_REF)
! 	new_var = build1 (INDIRECT_REF, type, new_var);
        else
  	new_var = build_fold_addr_expr (new_var);
        pos = find_pos_in_stmt (stmt, r_pos.container, &r_pos);
--- 1279,1289 ----
    pos = find_pos_in_stmt (stmt, var, &r_pos);
    gcc_assert (pos);
  
!   while (r_pos.container && (TREE_CODE(r_pos.container) == MEM_REF
  			     || TREE_CODE(r_pos.container) == ADDR_EXPR))
      {
!       if (TREE_CODE(r_pos.container) == MEM_REF)
! 	new_var = build_simple_mem_ref (new_var);
        else
  	new_var = build_fold_addr_expr (new_var);
        pos = find_pos_in_stmt (stmt, r_pos.container, &r_pos);
*************** get_stmt_accesses (tree *tp, int *walk_s
*** 2528,2534 ****
  	tree field_decl = TREE_OPERAND (t, 1);
  
  
! 	if ((TREE_CODE (ref) == INDIRECT_REF
  	     || TREE_CODE (ref) == ARRAY_REF
  	     || TREE_CODE (ref) == VAR_DECL)
  	    && TREE_CODE (field_decl) == FIELD_DECL)
--- 2530,2536 ----
  	tree field_decl = TREE_OPERAND (t, 1);
  
  
! 	if ((TREE_CODE (ref) == MEM_REF
  	     || TREE_CODE (ref) == ARRAY_REF
  	     || TREE_CODE (ref) == VAR_DECL)
  	    && TREE_CODE (field_decl) == FIELD_DECL)
Index: trunk/gcc/tree-mudflap.c
===================================================================
*** trunk.orig/gcc/tree-mudflap.c	2010-03-22 13:36:55.000000000 +0100
--- trunk/gcc/tree-mudflap.c	2010-03-22 13:40:14.000000000 +0100
*************** mf_xform_derefs_1 (gimple_stmt_iterator
*** 814,820 ****
                }
              else if (TREE_CODE (var) == COMPONENT_REF)
                var = TREE_OPERAND (var, 0);
!             else if (INDIRECT_REF_P (var))
                {
  		base = TREE_OPERAND (var, 0);
                  break;
--- 814,821 ----
                }
              else if (TREE_CODE (var) == COMPONENT_REF)
                var = TREE_OPERAND (var, 0);
!             else if (INDIRECT_REF_P (var)
! 		     || TREE_CODE (var) == MEM_REF)
                {
  		base = TREE_OPERAND (var, 0);
                  break;
*************** mf_xform_derefs_1 (gimple_stmt_iterator
*** 887,892 ****
--- 888,907 ----
        base = addr;
        limit = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node,
  			   fold_build2_loc (location,
+ 					POINTER_PLUS_EXPR, ptr_type_node, base,
+ 					size),
+ 			   size_int (-1));
+       break;
+ 
+     case MEM_REF:
+       addr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (TREE_OPERAND (t, 1)),
+ 		     TREE_OPERAND (t, 0),
+ 		     build_int_cst_wide_type (sizetype,
+ 					      TREE_INT_CST_LOW (TREE_OPERAND (t, 1)),
+ 					      TREE_INT_CST_HIGH (TREE_OPERAND (t, 1))));
+       base = addr;
+       limit = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node,
+ 			   fold_build2_loc (location,
  					POINTER_PLUS_EXPR, ptr_type_node, base,
  					size),
  			   size_int (-1));
Index: trunk/gcc/testsuite/gcc.c-torture/execute/20100316-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.c-torture/execute/20100316-1.c	2010-03-22 13:40:14.000000000 +0100
***************
*** 0 ****
--- 1,24 ----
+ struct Foo {
+   int i;
+   unsigned precision : 10;
+   unsigned blah : 3;
+ } f;
+ 
+ int __attribute__((noinline,noclone))
+ foo (struct Foo *p)
+ {
+   struct Foo *q = p;
+   return (*q).precision;
+ }
+ 
+ extern void abort (void);
+ 
+ int main()
+ {
+   f.i = -1;
+   f.precision = 0;
+   f.blah = -1;
+   if (foo (&f) != 0)
+     abort ();
+   return 0;
+ }


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