> -----Original Message-----
> From: Richard Biener [mailto:richard.guent...@gmail.com]
> Sent: Friday, September 27, 2013 4:30 PM
> To: Bin Cheng
> Cc: GCC Patches
> Subject: Re: [PATCH]Fix computation of offset in ivopt
> 
> On Fri, Sep 27, 2013 at 7:07 AM, bin.cheng <bin.ch...@arm.com> wrote:
> >
> >
> >   case INTEGER_CST:
> >       //.......
> >       *offset = int_cst_value (expr);
> > change to
> >   case INTEGER_CST:
> >       //.......
> >       *offset = sext_hwi (int_cst_value (expr), type);
> >
> > and
> >   case MULT_EXPR:
> >       //.......
> >       *offset = sext_hwi (int_cst_value (expr), type); to
> >   case MULT_EXPR:
> >       //.......
> >      HOST_WIDE_INT xxx = (HOST_WIDE_INT)off0 * int_cst_value (op1);
> >       *offset = sext_hwi (xxx, type);
> >
> > Any comments?
> 
> The issue is of course that we end up converting offsets to sizetype at
some
> point which makes them all appear unsigned.  The fix for this is to simply
> interpret them as signed ... but it's really a mess ;)
> 

Hi,  this is updated patch which calculates signed offset in strip_offset_1
then sign extend it in strip_offset.

Bootstrap and test on x86_64/x86/arm. Is it OK?

Thanks.
bin

2013-09-30  Bin Cheng  <bin.ch...@arm.com>

        * tree-ssa-loop-ivopts.c (strip_offset_1): Change parameter type.
        Count DECL_FIELD_BIT_OFFSET when computing offset for COMPONENT_REF.
        (strip_offset): Sign extend before return.
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c  (revision 202599)
+++ gcc/tree-ssa-loop-ivopts.c  (working copy)
@@ -2037,12 +2037,12 @@ find_interesting_uses (struct ivopts_data *data)
 
 static tree
 strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
-               unsigned HOST_WIDE_INT *offset)
+               HOST_WIDE_INT *offset)
 {
   tree op0 = NULL_TREE, op1 = NULL_TREE, tmp, step;
   enum tree_code code;
   tree type, orig_type = TREE_TYPE (expr);
-  unsigned HOST_WIDE_INT off0, off1, st;
+  HOST_WIDE_INT off0, off1, st;
   tree orig_expr = expr;
 
   STRIP_NOPS (expr);
@@ -2133,19 +2133,26 @@ 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;
-       }
+       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)))
+         {
+           /* Strip the component reference completely.  */
+           op0 = TREE_OPERAND (expr, 0);
+           op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
+           boffset = int_cst_value (DECL_FIELD_BIT_OFFSET (field));
+           *offset = off0 + int_cst_value (tmp) + boffset / BITS_PER_UNIT;
+           return op0;
+         }
+      }
       break;
 
     case ADDR_EXPR:
@@ -2196,7 +2203,16 @@ strip_offset_1 (tree expr, bool inside_addr, bool
 static tree
 strip_offset (tree expr, unsigned HOST_WIDE_INT *offset)
 {
-  return strip_offset_1 (expr, false, false, offset);
+  HOST_WIDE_INT off;
+  tree core = strip_offset_1 (expr, false, false, &off);
+
+  /* Sign extend off if expr is in type which has lower precision
+     than HOST_WIDE_INT.  */
+  if (TYPE_PRECISION (TREE_TYPE (expr)) <= HOST_BITS_PER_WIDE_INT)
+    off = sext_hwi (off, TYPE_PRECISION (TREE_TYPE (expr)));
+
+  *offset = off;
+  return core;
 }
 
 /* Returns variant of TYPE that can be used as base for different uses.

Reply via email to