* [PATCH][mem-ref2] Rewrite get_addr_base_and_offset
@ 2010-06-17 14:47 Richard Guenther
0 siblings, 0 replies; only message in thread
From: Richard Guenther @ 2010-06-17 14:47 UTC (permalink / raw)
To: gcc-patches
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).
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) \
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2010-06-17 14:30 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-17 14:47 [PATCH][mem-ref2] Rewrite get_addr_base_and_offset Richard Guenther
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).