[PATCH][mem-ref2] Fix MEM_REF offset extraction
Richard Guenther
rguenther@suse.de
Wed Mar 31 10:24:00 GMT 2010
This fixes offset extraction to properly sign-extend. With
HWI64 and 32bit pointers we otherwise get it wrong.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to
the branch.
Richard.
2010-03-31 Richard Guenther <rguenther@suse.de>
* tree.h (mem_ref_offset): Declare.
* tree.c (mem_ref_offset): New function.
* tree-ssa-alias.c (refs_may_alias_p_1): Use it.
* expr.c (get_inner_reference): Likewise.
(expand_expr_addr_expr_1): Likewise.
* tree-dfa.c (get_ref_base_and_extent): Likewise.
Index: gcc/tree.c
===================================================================
--- gcc/tree.c (revision 157699)
+++ gcc/tree.c (working copy)
@@ -3860,6 +3860,16 @@ build_simple_mem_ref_loc (location_t loc
return tem;
}
+/* Return the constant offset of a MEM_REF tree T. */
+
+double_int
+mem_ref_offset (const_tree t)
+{
+ tree toff = TREE_OPERAND (t, 1);
+ return double_int_sext (tree_to_double_int (toff),
+ TYPE_PRECISION (TREE_TYPE (toff)));
+}
+
/* 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: gcc/tree.h
===================================================================
--- gcc/tree.h (revision 157630)
+++ gcc/tree.h (working copy)
@@ -4889,6 +4889,7 @@ extern tree fold_indirect_ref_loc (locat
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 double_int mem_ref_offset (const_tree);
extern tree constant_boolean_node (int, tree);
extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
Index: gcc/tree-ssa-alias.c
===================================================================
--- gcc/tree-ssa-alias.c (revision 157827)
+++ gcc/tree-ssa-alias.c (working copy)
@@ -870,9 +870,9 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref
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;
+ offset1 += mem_ref_offset (base1).low * BITS_PER_UNIT;
if (TREE_CODE (base2) == MEM_REF)
- offset2 += TREE_INT_CST_LOW (TREE_OPERAND (base2, 1)) * BITS_PER_UNIT;
+ offset2 += mem_ref_offset (base2).low * BITS_PER_UNIT;
/* Canonicalize the pointer-vs-decl case. */
if (ind1_p && var2_p)
Index: gcc/expr.c
===================================================================
--- gcc/expr.c (revision 157630)
+++ gcc/expr.c (working copy)
@@ -6097,10 +6097,10 @@ get_inner_reference (tree exp, HOST_WIDE
tree off = TREE_OPERAND (exp, 1);
if (!integer_zerop (off))
{
+ double_int coff = mem_ref_offset (exp);
unsigned HOST_WIDE_INT boffl;
HOST_WIDE_INT boffh;
- lshift_double (TREE_INT_CST_LOW (off),
- TREE_INT_CST_HIGH (off),
+ lshift_double (coff.low, coff.high,
exact_log2 (BITS_PER_UNIT),
2 * HOST_BITS_PER_WIDE_INT,
&boffl, &boffh, 1);
@@ -6876,7 +6876,8 @@ expand_expr_addr_expr_1 (tree exp, rtx t
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)));
+ tem,
+ double_int_to_tree (sizetype, mem_ref_offset (exp)));
return expand_expr (tem, target, tmode, modifier);
}
Index: gcc/tree-dfa.c
===================================================================
--- gcc/tree-dfa.c (revision 157630)
+++ gcc/tree-dfa.c (working copy)
@@ -884,12 +884,13 @@ get_ref_base_and_extent (tree exp, HOST_
/* 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 ... */
+ bit_offset ...
+ Also we need to treat the pointer constants as
+ sign-extending. */
&& (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;
+ bit_offset += mem_ref_offset (exp).low * BITS_PER_UNIT;
exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
}
goto done;
More information about the Gcc-patches
mailing list