On 30/10/15 10:54, Eric Botcazou wrote:
> On 30/10/15 10:44, Richard Biener wrote:
>>
>> I think you want to use wide-ints here and
>>
>> wide_int idx = wi::from (minidx, TYPE_PRECISION (TYPE_DOMAIN
>> (...)), TYPE_SIGN (TYPE_DOMAIN (..)));
>> wide_int maxidx = ...
>>
>> you can then simply iterate minidx with ++ and do the final compare
>> against maxidx
>> with while (++idx <= maxidx). For the array ref index we want to use
>> TYPE_DOMAIN
>> as type as well, not size_int. Thus wide_int_to_tree (TYPE_DOMAIN
>> (...)..idx).
[...]
> But using offset_int should be OK, see for example get_ref_base_and_extent.
>
Here's a patch using offset_int. (Not as easy to construct as wide_int::from,
the sign-extend is what appeared to be done elsewhere that constructs
offset_ints).
Tested by bootstrap+check-{gcc,g++,ada,fortran} with the rest of the patchset
(which causes an array[-1..1] to be completely scalarized, among others), on
x86_64 and ARM.
I don't have a test without all that (such would have to be in Ada, and trigger
SRA of such an array but not involving the constant pool); is it OK without?
gcc/ChangeLog:
* tree-sra.c (completely_scalarize): Properly handle negative array
indices using offset_int.
---
gcc/tree-sra.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index e15df1f..6168a7e 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -1010,18 +1010,25 @@ completely_scalarize (tree base, tree decl_type,
HOST_WIDE_INT offset, tree ref)
if (maxidx)
{
gcc_assert (TREE_CODE (maxidx) == INTEGER_CST);
- /* MINIDX and MAXIDX are inclusive. Try to avoid overflow. */
- unsigned HOST_WIDE_INT lenp1 = tree_to_shwi (maxidx)
- - tree_to_shwi (minidx);
- unsigned HOST_WIDE_INT idx = 0;
- do
+ tree domain = TYPE_DOMAIN (decl_type);
+ /* MINIDX and MAXIDX are inclusive, and must be interpreted in
+ DOMAIN (e.g. signed int, whereas min/max may be size_int). */
+ offset_int idx = wi::to_offset (minidx);
+ offset_int max = wi::to_offset (maxidx);
+ if (!TYPE_UNSIGNED (domain))
{
- tree nref = build4 (ARRAY_REF, elemtype, ref, size_int (idx),
+ idx = wi::sext (idx, TYPE_PRECISION (domain));
+ max = wi::sext (max, TYPE_PRECISION (domain));
+ }
+ for (int el_off = offset; wi::les_p (idx, max); ++idx)
+ {
+ tree nref = build4 (ARRAY_REF, elemtype,
+ ref,
+ wide_int_to_tree (domain, idx),
NULL_TREE, NULL_TREE);
- int el_off = offset + idx * el_size;
scalarize_elem (base, el_off, el_size, nref, elemtype);
+ el_off += el_size;
}
- while (++idx <= lenp1);
}
}
break;
--
1.9.1