Hi,
This patch fix two minor bugs when computing offset in IVOPT.
1) Considering below example:
#define MAX 100
struct tag
{
int i;
int j;
}
struct tag arr[MAX]
int foo (int len)
{
int i = 0;
for (; i < len; i++)
{
access arr[i].j;
}
}
Without this patch, the offset computed by strip_offset_1 for address
arr[i].j is ZERO, which is apparently not.
2) Considering below example:
//...
<bb 15>:
KeyIndex_66 = KeyIndex_194 + 4294967295;
if (KeyIndex_66 != 0)
goto <bb 16>;
else
goto <bb 18>;
<bb 16>:
<bb 17>:
# KeyIndex_194 = PHI <KeyIndex_66(16), KeyIndex_180(73)>
_62 = KeyIndex_194 + 1073741823;
_63 = _62 * 4;
_64 = pretmp_184 + _63;
_65 = *_64;
if (_65 == 0)
goto <bb 15>;
else
goto <bb 71>;
//...
There are iv use and candidate like:
use 1
address
in statement _65 = *_64;
at position *_64
type handletype *
base pretmp_184 + ((sizetype) KeyIndex_180 + 1073741823) * 4
step 4294967292
base object (void *) pretmp_184
related candidates
candidate 6
var_before ivtmp.16
var_after ivtmp.16
incremented before use 1
type unsigned int
base (unsigned int) (pretmp_184 + (sizetype) KeyIndex_180 * 4)
step 4294967292
base object (void *) pretmp_184
Candidate 6 is related to use 1
In function get_computation_cost_at for use 1 using cand 6, ubase and cbase
are:
pretmp_184 + ((sizetype) KeyIndex_180 + 1073741823) * 4
pretmp_184 + (sizetype) KeyIndex_180 * 4
The cstepi computed in HOST_WIDE_INT is : 0xfffffffffffffffc, while offset
computed in TYPE(utype) is : 0xfffffffc. Though they both stand for value
"-4" in different precision, statement "offset -= ratio * cstepi" returns
0x100000000, which is wrong.
Tested on x86_64 and arm. Is it OK?
Thanks.
bin
2013-09-24 Bin Cheng <bin.ch...@arm.com>
* tree-ssa-loop-ivopts.c (strip_offset_1): Count
DECL_FIELD_BIT_OFFSET when computing offset for COMPONENT_REF.
(get_computation_cost_at): Sign extend offset.
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c (revision 200774)
+++ gcc/tree-ssa-loop-ivopts.c (working copy)
@@ -2133,19 +2133,28 @@ strip_offset_1 (tree expr, bool inside_addr, bool
break;
case COMPONENT_REF:
- if (!inside_addr)
- return orig_expr;
+ {
+ tree field;
+ HOST_WIDE_INT boffset = 0;
+ if (!inside_addr)
+ return orig_expr;
- tmp = component_ref_field_offset (expr);
- if (top_compref
- && cst_and_fits_in_hwi (tmp))
- {
- /* Strip the component reference completely. */
- op0 = TREE_OPERAND (expr, 0);
- op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
- *offset = off0 + int_cst_value (tmp);
- return op0;
- }
+ field = TREE_OPERAND (expr, 1);
+ if (DECL_FIELD_BIT_OFFSET (field)
+ && cst_and_fits_in_hwi (DECL_FIELD_BIT_OFFSET (field)))
+ boffset = int_cst_value (DECL_FIELD_BIT_OFFSET (field));
+
+ tmp = component_ref_field_offset (expr);
+ if (top_compref
+ && cst_and_fits_in_hwi (tmp))
+ {
+ /* Strip the component reference completely. */
+ op0 = TREE_OPERAND (expr, 0);
+ op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
+ *offset = off0 + int_cst_value (tmp) + boffset / BITS_PER_UNIT;
+ return op0;
+ }
+ }
break;
case ADDR_EXPR:
@@ -4133,6 +4142,9 @@ get_computation_cost_at (struct ivopts_data *data,
bitmap_clear (*depends_on);
}
+ /* Sign-extend offset if utype has lower precision than HOST_WIDE_INT. */
+ offset = sext_hwi (offset, TYPE_PRECISION (utype));
+
/* If we are after the increment, the value of the candidate is higher by
one iteration. */
if (stmt_is_after_inc)