From patchwork Thu Jun 17 14:30:03 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [mem-ref2] Rewrite get_addr_base_and_offset Date: Thu, 17 Jun 2010 04:30:03 -0000 From: Richard Guenther X-Patchwork-Id: 56055 Message-Id: To: gcc-patches@gcc.gnu.org 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 * 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) \