Patchwork [mem-ref2] Rewrite get_addr_base_and_offset

login
register
mail settings
Submitter Richard Guenther
Date June 17, 2010, 2:30 p.m.
Message ID <alpine.LNX.2.00.1006171628470.1429@zhemvz.fhfr.qr>
Download mbox | patch
Permalink /patch/56055/
State New
Headers show

Comments

Richard Guenther - June 17, 2010, 2:30 p.m.
This rewrites get_addr_base_and_offset to be independent of
get_inner_reference and provide a unit offset as needed everywhere.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the 
branch.

Richard.

2010-06-17  Richard Guenther  <rguenther@suse.de>

	* tree-flow.h (get_addr_base_and_offset): Rename to ...
	(get_addr_base_and_unit_offset): ... this.
	* tree-dfa.c (get_addr_base_and_offset): Rename to ...
	(get_addr_base_and_unit_offset): ... this.  Rewrite.
	* tree.c (build_simple_mem_ref_loc): Adjust.
	* fold-const.c: Include tree-flow.h.
	(fold_binary_loc): Adjust.
	* tree-ssa-sccvn.c (vn_reference_fold_indirect): Adjust.
	* expr.c (expand_expr_real_1): Adjust.
	* tree-ssa-pre.c (create_component_ref_by_pieces_1): Adjust.
	* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Adjust.
	* Makefile.in (tree-dfa.o): Add $(TOPLEV_H).
	(fold-const.o): Add $(TREE_FLOW_H).

Patch

Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 160880)
+++ gcc/tree.c	(working copy)
@@ -3835,9 +3835,8 @@  build_simple_mem_ref_loc (location_t loc
       && (handled_component_p (TREE_OPERAND (ptr, 0))
 	  || TREE_CODE (TREE_OPERAND (ptr, 0)) == MEM_REF))
     {
-      ptr = get_addr_base_and_offset (TREE_OPERAND (ptr, 0), &offset);
-      gcc_assert (offset % BITS_PER_UNIT == 0);
-      offset = offset / BITS_PER_UNIT;
+      ptr = get_addr_base_and_unit_offset (TREE_OPERAND (ptr, 0), &offset);
+      gcc_assert (ptr);
       ptr = build_fold_addr_expr (ptr);
       gcc_assert (is_gimple_reg (ptr) || is_gimple_min_invariant (ptr));
     }
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 160880)
+++ gcc/fold-const.c	(working copy)
@@ -65,6 +65,7 @@  along with GCC; see the file COPYING3.
 #include "langhooks.h"
 #include "md5.h"
 #include "gimple.h"
+#include "tree-flow.h"
 
 /* Nonzero if we are folding constants inside an initializer; zero
    otherwise.  */
@@ -9596,27 +9597,15 @@  fold_binary_loc (location_t loc,
 	  && handled_component_p (TREE_OPERAND (arg0, 0)))
 	{
 	  tree base;
-	  HOST_WIDE_INT size, coffset;
-	  tree ncoffset;
-	  enum machine_mode mode;
-	  int dummy;
-
-	  base = get_inner_reference (TREE_OPERAND (arg0, 0), &size,
-				      &coffset, &ncoffset,
-				      &mode, &dummy, &dummy, false);
-	  if (coffset % BITS_PER_UNIT != 0
-	      || (ncoffset != NULL_TREE
-		  && TREE_CODE (ncoffset) != INTEGER_CST))
+	  HOST_WIDE_INT coffset;
+	  base = get_addr_base_and_unit_offset (TREE_OPERAND (arg0, 0),
+						&coffset);
+	  if (!base)
 	    return NULL_TREE;
-	  if (!ncoffset)
-	    ncoffset = size_int (coffset / BITS_PER_UNIT);
-	  else
-	    ncoffset = int_const_binop (PLUS_EXPR, ncoffset,
-					size_int (coffset / BITS_PER_UNIT), 0);
-
 	  return fold_build2 (MEM_REF, type,
 			      build_fold_addr_expr (base),
-			      int_const_binop (PLUS_EXPR, arg1, ncoffset, 0));
+			      int_const_binop (PLUS_EXPR, arg1,
+					       size_int (coffset), 0));
 	}
 
       return NULL_TREE;
Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c	(revision 160880)
+++ gcc/tree-ssa-sccvn.c	(working copy)
@@ -962,15 +962,14 @@  vn_reference_fold_indirect (VEC (vn_refe
   /* The only thing we have to do is from &OBJ.foo.bar add the offset
      from .foo.bar to the preceeding MEM_REF offset and replace the
      address with &OBJ.  */
-  addr_base = get_addr_base_and_offset (TREE_OPERAND (op->op0, 0),
-					&addr_offset);
+  addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (op->op0, 0),
+					     &addr_offset);
   gcc_checking_assert (addr_base && TREE_CODE (addr_base) != MEM_REF);
   if (addr_base != op->op0)
     {
       double_int off = tree_to_double_int (mem_op->op0);
       off = double_int_sext (off, TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
-      off = double_int_add (off, shwi_to_double_int (addr_offset
-						     / BITS_PER_UNIT));
+      off = double_int_add (off, shwi_to_double_int (addr_offset));
       mem_op->op0 = double_int_to_tree (TREE_TYPE (mem_op->op0), off);
       op->op0 = build_fold_addr_expr (addr_base);
     }
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 160880)
+++ gcc/expr.c	(working copy)
@@ -8802,17 +8813,15 @@  expand_expr_real_1 (tree exp, rtx target
 	   might end up in a register.  */
 	if (TREE_CODE (base) == ADDR_EXPR)
 	  {
-	    tree offset = TREE_OPERAND (exp, 1);
+	    HOST_WIDE_INT offset = mem_ref_offset (exp).low;
+	    tree bit_offset;
 	    base = TREE_OPERAND (base, 0);
-	    offset = fold_convert (bitsizetype, 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);
+		base = get_addr_base_and_unit_offset (base, &off);
 		gcc_assert (base);
-		offset = size_binop (PLUS_EXPR, offset, bitsize_int (off));
+		offset += off;
 	      }
 	    /* If we are expanding a MEM_REF of a non-BLKmode non-addressable
 	       decl we must use bitfield operations.  */
@@ -8821,7 +8830,7 @@  expand_expr_real_1 (tree exp, rtx target
 		&& DECL_MODE (base) != BLKmode)
 	      {
 		tree bftype;
-		if (integer_zerop (offset)
+		if (offset == 0
 		    && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
 		    && (GET_MODE_BITSIZE (DECL_MODE (base))
 			== TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))
@@ -8831,13 +8840,14 @@  expand_expr_real_1 (tree exp, rtx target
 		gcc_assert (!DECL_RTL_SET_P (base)
 			    || REG_P (DECL_RTL (base))
 			    || GET_CODE (DECL_RTL (base)) == CONCAT);
+		bit_offset = bitsize_int (offset * BITS_PER_UNIT);
 		bftype = TREE_TYPE (base);
 		if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
 		  bftype = TREE_TYPE (exp);
 		return expand_expr (build3 (BIT_FIELD_REF, bftype,
 					    base,
 					    TYPE_SIZE (TREE_TYPE (exp)),
-					    offset),
+					    bit_offset),
 				    target, tmode, modifier);
 	      }
 	  }
@@ -8847,9 +8857,7 @@  expand_expr_real_1 (tree exp, rtx target
 	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);
+	    off = immed_double_int_const (mem_ref_offset (exp), address_mode);
 	    op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
 	  }
 	op0 = memory_address_addr_space (mode, op0, as);
Index: gcc/tree-dfa.c
===================================================================
--- gcc/tree-dfa.c	(revision 160880)
+++ gcc/tree-dfa.c	(working copy)
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "toplev.h"
 #include "hashtab.h"
 #include "pointer-set.h"
 #include "tree.h"
@@ -931,25 +947,102 @@  get_ref_base_and_extent (tree exp, HOST_
   return exp;
 }
 
-/* Returns the base object and a constant offset in *POFFSET that
+/* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that
    denotes the starting address of the memory access EXP.
-   Returns NULL_TREE if the offset is not constant.  */
+   Returns NULL_TREE if the offset is not constant or any component
+   is not BITS_PER_UNIT-aligned.  */
 
 tree
-get_addr_base_and_offset (tree exp, HOST_WIDE_INT *poffset)
+get_addr_base_and_unit_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;
+  HOST_WIDE_INT byte_offset = 0;
+
+  /* Compute cumulative byte-offset for nested component-refs and array-refs,
+     and find the ultimate containing object.  */
+  while (1)
+    {
+      switch (TREE_CODE (exp))
+	{
+	case BIT_FIELD_REF:
+	  return NULL_TREE;
+
+	case COMPONENT_REF:
+	  {
+	    tree field = TREE_OPERAND (exp, 1);
+	    tree this_offset = component_ref_field_offset (exp);
+	    HOST_WIDE_INT hthis_offset;
+
+	    if (!this_offset
+		|| TREE_CODE (this_offset) != INTEGER_CST
+		|| (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
+		    % BITS_PER_UNIT))
+	      return NULL_TREE;
+
+	    hthis_offset = TREE_INT_CST_LOW (this_offset);
+	    hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
+			     / BITS_PER_UNIT);
+	    byte_offset += hthis_offset;
+	  }
+	  break;
+
+	case ARRAY_REF:
+	case ARRAY_RANGE_REF:
+	  {
+	    tree index = TREE_OPERAND (exp, 1);
+	    tree low_bound, unit_size;
 
-  return base;
+	    /* If the resulting bit-offset is constant, track it.  */
+	    if (TREE_CODE (index) == INTEGER_CST
+		&& (low_bound = array_ref_low_bound (exp),
+		    TREE_CODE (low_bound) == INTEGER_CST)
+		&& (unit_size = array_ref_element_size (exp),
+		    TREE_CODE (unit_size) == INTEGER_CST))
+	      {
+		HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index);
+
+		hindex -= TREE_INT_CST_LOW (low_bound);
+		hindex *= TREE_INT_CST_LOW (unit_size);
+		byte_offset += hindex;
+	      }
+	    else
+	      return NULL_TREE;
+	  }
+	  break;
+
+	case REALPART_EXPR:
+	  break;
+
+	case IMAGPART_EXPR:
+	  byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp)));
+	  break;
+
+	case VIEW_CONVERT_EXPR:
+	  break;
+
+	case MEM_REF:
+	  /* Hand back the decl for MEM[&decl, off].  */
+	  if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
+	    {
+	      if (!integer_zerop (TREE_OPERAND (exp, 1)))
+		{
+		  double_int off = mem_ref_offset (exp);
+		  gcc_assert (off.high == -1 || off.high == 0);
+		  byte_offset += double_int_to_shwi (off);
+		}
+	      exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+	    }
+	  goto done;
+
+	default:
+	  goto done;
+	}
+
+      exp = TREE_OPERAND (exp, 0);
+    }
+done:
+
+  *poffset = byte_offset;
+  return exp;
 }
 
 /* Returns true if STMT references an SSA_NAME that has
Index: gcc/tree-ssa-pre.c
===================================================================
--- gcc/tree-ssa-pre.c	(revision 160880)
+++ gcc/tree-ssa-pre.c	(working copy)
@@ -2686,11 +2686,12 @@  create_component_ref_by_pieces_1 (basic_
 	  {
 	    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);
+	    base = get_addr_base_and_unit_offset (TREE_OPERAND (baseop, 0),
+						  &off);
+	    gcc_assert (base);
 	    offset = int_const_binop (PLUS_EXPR, offset,
 				      build_int_cst (TREE_TYPE (offset),
-						     off / BITS_PER_UNIT), 0);
+						     off), 0);
 	    baseop = build_fold_addr_expr (base);
 	  }
 	return fold_build2 (MEM_REF, currop->type, baseop, offset);
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c	(revision 160880)
+++ gcc/tree-ssa-forwprop.c	(working copy)
@@ -820,14 +820,13 @@  forward_propagate_addr_expr_1 (tree name
     {
       tree def_rhs_base;
       HOST_WIDE_INT def_rhs_offset;
-      if ((def_rhs_base = get_addr_base_and_offset (TREE_OPERAND (def_rhs, 0),
-						    &def_rhs_offset)))
+      if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0),
+							 &def_rhs_offset)))
 	{
 	  double_int off = mem_ref_offset (lhs);
 	  tree new_ptr;
 	  off = double_int_add (off,
-				shwi_to_double_int (def_rhs_offset
-						    / BITS_PER_UNIT));
+				shwi_to_double_int (def_rhs_offset));
 	  if (TREE_CODE (def_rhs_base) == MEM_REF)
 	    {
 	      off = double_int_add (off, mem_ref_offset (def_rhs_base));
@@ -866,14 +865,13 @@  forward_propagate_addr_expr_1 (tree name
     {
       tree def_rhs_base;
       HOST_WIDE_INT def_rhs_offset;
-      if ((def_rhs_base = get_addr_base_and_offset (TREE_OPERAND (def_rhs, 0),
-						    &def_rhs_offset)))
+      if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0),
+							 &def_rhs_offset)))
 	{
 	  double_int off = mem_ref_offset (rhs);
 	  tree new_ptr;
 	  off = double_int_add (off,
-				shwi_to_double_int (def_rhs_offset
-						    / BITS_PER_UNIT));
+				shwi_to_double_int (def_rhs_offset));
 	  if (TREE_CODE (def_rhs_base) == MEM_REF)
 	    {
 	      off = double_int_add (off, mem_ref_offset (def_rhs_base));
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h	(revision 160880)
+++ gcc/tree-flow.h	(working copy)
@@ -520,7 +520,7 @@  extern tree gimple_default_def (struct f
 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 tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *);
 extern void find_referenced_vars_in (gimple);
 
 /* In tree-phinodes.c  */
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 160880)
+++ gcc/Makefile.in	(working copy)
@@ -2508,7 +2508,7 @@  tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $
    $(TREE_INLINE_H) $(HASHTAB_H) pointer-set.h $(FLAGS_H) $(FUNCTION_H) \
    $(TIMEVAR_H) convert.h $(TM_H) coretypes.h langhooks.h $(TREE_DUMP_H) \
    $(TREE_PASS_H) $(PARAMS_H) $(CGRAPH_H) $(BASIC_BLOCK_H) $(GIMPLE_H) \
-   tree-pretty-print.h
+   tree-pretty-print.h $(TOPLEV_H)
 tree-ssa-operands.o : tree-ssa-operands.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
    $(FLAGS_H) $(FUNCTION_H) $(TM_H) $(TIMEVAR_H) $(TREE_PASS_H) $(TOPLEV_H) \
@@ -2787,7 +2787,7 @@  tree-diagnostic.o : tree-diagnostic.c $(
 fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) $(FLAGS_H) $(TOPLEV_H) $(HASHTAB_H) $(EXPR_H) $(RTL_H) \
    $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h $(TARGET_H) \
-   $(GIMPLE_H) realmpfr.h
+   $(GIMPLE_H) realmpfr.h $(TREE_FLOW_H)
 diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    version.h $(INPUT_H) intl.h $(DIAGNOSTIC_H) diagnostic.def
 opts.o : opts.c opts.h options.h $(TOPLEV_H) $(CONFIG_H) $(SYSTEM_H) \