On Tue, Sep 24, 2013 at 11:13 AM, bin.cheng <bin.ch...@arm.com> wrote: > 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?
+ 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; + } the failure paths seem mangled, that is, if cst_and_fits_in_hwi is false for either offset part you may end up doing half accounting and not stripping. Btw, DECL_FIELD_BIT_OFFSET is always non-NULL. I suggest to rewrite to if (!inside_addr) return orig_expr; tmp = component_ref_field_offset (expr); field = TREE_OPERAND (expr, 1); if (top_compref && cst_and_fits_in_hwi (tmp) && cst_and_fits_in_hwi (DECL_FIELD_BIT_OFFSET (field))) { ... } note that this doesn't really handle overflows correctly as + *offset = off0 + int_cst_value (tmp) + boffset / BITS_PER_UNIT; may still overflow. @@ -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)); + offset is computed elsewhere in difference_cost and the bug to me seems that it is unsigned. sign-extending it here is odd at least (and the extension should probably happen at sizetype precision, not that of utype). Richard. > 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.