Hi,
this test started to fail very recently on 32-bit platforms with 64-bit HWI.
Not sure exactly why, but the issue is straightforward and was latent.
For the following reference, a call to ao_ref_init_from_ptr_and_size yields:
(gdb) p debug_generic_expr((tree_node *) 0x7ffff6e01200)
&a[0 ...]{lb: 4294967292 sz: 4}
(gdb) p debug_generic_expr(size)
20
(gdb) p dref
$36 = {ref = 0x0, base = 0x7ffff6dfd260, offset = -137438953344, size = 160,
max_size = 160, ref_alias_set = 0, base_alias_set = 0, volatile_p = false}
The offset is bogus. 'a' is an array with lower bound -4 so {lb: 4294967292
sz: 4} is actually {lb: -4 sz: 4}. The computation of the offset goes wrong
in get_addr_base_and_unit_offset_1 because it is not done in sizetype.
Fixed by copying the relevant bits from get_ref_base_and_extent, where the
computation is correctly done in sizetype.
Tested on x86_64-suse-linux, OK for the mainline?
2013-11-30 Eric Botcazou <ebotca...@adacore.com>
* tree-dfa.h (get_addr_base_and_unit_offset_1) <case ARRAY_REF>: Do the
offset computation using the precision of the index type.
2013-11-30 Eric Botcazou <ebotca...@adacore.com>
* gnat.dg/opt30.adb: New test.
--
Eric Botcazou
Index: tree-dfa.h
===================================================================
--- tree-dfa.h (revision 205547)
+++ tree-dfa.h (working copy)
@@ -102,11 +102,11 @@ get_addr_base_and_unit_offset_1 (tree ex
&& (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;
+ double_int doffset
+ = (TREE_INT_CST (index) - TREE_INT_CST (low_bound))
+ .sext (TYPE_PRECISION (TREE_TYPE (index)));
+ doffset *= tree_to_double_int (unit_size);
+ byte_offset += doffset.to_shwi ();
}
else
return NULL_TREE;
-- { dg-do run }
-- { dg-options "-O" }
procedure Opt30 is
function Id_I (I : Integer) return Integer is
begin
return I;
end;
A : array (Integer range -4..4) of Integer;
begin
A := (-ID_I(4), -ID_I(3), -ID_I(2), -ID_I(1), ID_I(100),
ID_I(1), ID_I(2), ID_I(3), ID_I(4));
A(-4..0) := A(0..4);
if A /= (100, 1, 2, 3, 4, 1, 2, 3, 4) then
raise Program_Error;
end if;
end;