When using the C++ frontend to build gcc.dg/fold-bitand-4.c it currently
fails to optimize because we don't handle &a[i] properly in
get_pointer_modulus_and_residue.  We do have nice conservative code
in get_object_alignment that just needs splitting out.  Which is
what the following patch does.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2011-04-14  Richard Guenther  <rguent...@suse.de>

        * tree.h (get_object_alignment_1): Declare.
        * builtins.c (get_object_alignment_1): Split out worker from ...
        (get_object_alignment): ... here.
        * fold-const.c (get_pointer_modulus_and_residue): Use
        get_object_alignment_1.

        * gcc.dg/fold-bitand-4.c: Move ...
        * c-c++-common/fold-bitand-4.c: ... here.  Adjust slightly.

Index: gcc/tree.h
===================================================================
*** gcc/tree.h  (revision 172416)
--- gcc/tree.h  (working copy)
*************** extern bool can_trust_pointer_alignment
*** 5224,5229 ****
--- 5224,5230 ----
  extern unsigned int get_pointer_alignment (tree, unsigned int);
  extern bool is_builtin_name (const char *);
  extern bool is_builtin_fn (tree);
+ extern unsigned int get_object_alignment_1 (tree, unsigned HOST_WIDE_INT *);
  extern unsigned int get_object_alignment (tree, unsigned int);
  extern tree fold_call_stmt (gimple, bool);
  extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum 
built_in_function);
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c      (revision 172416)
--- gcc/builtins.c      (working copy)
*************** called_as_built_in (tree node)
*** 268,274 ****
     Don't return more than MAX_ALIGN no matter what.  */
  
  unsigned int
! get_object_alignment (tree exp, unsigned int max_align)
  {
    HOST_WIDE_INT bitsize, bitpos;
    tree offset;
--- 268,274 ----
     Don't return more than MAX_ALIGN no matter what.  */
  
  unsigned int
! get_object_alignment_1 (tree exp, unsigned HOST_WIDE_INT *bitposp)
  {
    HOST_WIDE_INT bitsize, bitpos;
    tree offset;
*************** get_object_alignment (tree exp, unsigned
*** 320,327 ****
          align = MAX (pi->align * BITS_PER_UNIT, align);
        }
        else if (TREE_CODE (addr) == ADDR_EXPR)
!       align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0),
!                                                 max_align));
        bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
      }
    else if (TREE_CODE (exp) == TARGET_MEM_REF)
--- 320,326 ----
          align = MAX (pi->align * BITS_PER_UNIT, align);
        }
        else if (TREE_CODE (addr) == ADDR_EXPR)
!       align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0), ~0U));
        bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
      }
    else if (TREE_CODE (exp) == TARGET_MEM_REF)
*************** get_object_alignment (tree exp, unsigned
*** 345,352 ****
          align = MAX (pi->align * BITS_PER_UNIT, align);
        }
        else if (TREE_CODE (addr) == ADDR_EXPR)
!       align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0),
!                                                 max_align));
        if (TMR_OFFSET (exp))
        bitpos += TREE_INT_CST_LOW (TMR_OFFSET (exp)) * BITS_PER_UNIT;
        if (TMR_INDEX (exp) && TMR_STEP (exp))
--- 344,350 ----
          align = MAX (pi->align * BITS_PER_UNIT, align);
        }
        else if (TREE_CODE (addr) == ADDR_EXPR)
!       align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0), ~0U));
        if (TMR_OFFSET (exp))
        bitpos += TREE_INT_CST_LOW (TMR_OFFSET (exp)) * BITS_PER_UNIT;
        if (TMR_INDEX (exp) && TMR_STEP (exp))
*************** get_object_alignment (tree exp, unsigned
*** 364,370 ****
  
    /* If there is a non-constant offset part extract the maximum
       alignment that can prevail.  */
!   inner = max_align;
    while (offset)
      {
        tree next_offset;
--- 362,368 ----
  
    /* If there is a non-constant offset part extract the maximum
       alignment that can prevail.  */
!   inner = ~0U;
    while (offset)
      {
        tree next_offset;
*************** get_object_alignment (tree exp, unsigned
*** 411,416 ****
--- 409,429 ----
    align = MIN (align, inner);
    bitpos = bitpos & (align - 1);
  
+   *bitposp = bitpos;
+   return align;
+ }
+ 
+ /* Return the alignment in bits of EXP, an object.
+    Don't return more than MAX_ALIGN no matter what.  */
+ 
+ unsigned int
+ get_object_alignment (tree exp, unsigned int max_align)
+ {
+   unsigned HOST_WIDE_INT bitpos = 0;
+   unsigned int align;
+ 
+   align = get_object_alignment_1 (exp, &bitpos);
+ 
    /* align and bitpos now specify known low bits of the pointer.
       ptr & (align - 1) == bitpos.  */
  
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c    (revision 172416)
--- gcc/fold-const.c    (working copy)
*************** get_pointer_modulus_and_residue (tree ex
*** 9230,9259 ****
    code = TREE_CODE (expr);
    if (code == ADDR_EXPR)
      {
!       expr = TREE_OPERAND (expr, 0);
!       if (handled_component_p (expr))
!       {
!         HOST_WIDE_INT bitsize, bitpos;
!         tree offset;
!         enum machine_mode mode;
!         int unsignedp, volatilep;
! 
!         expr = get_inner_reference (expr, &bitsize, &bitpos, &offset,
!                                     &mode, &unsignedp, &volatilep, false);
!         *residue = bitpos / BITS_PER_UNIT;
!         if (offset)
!           {
!             if (TREE_CODE (offset) == INTEGER_CST)
!               *residue += TREE_INT_CST_LOW (offset);
!             else
!               /* We don't handle more complicated offset expressions.  */
!               return 1;
!           }
!       }
! 
!       if (DECL_P (expr)
!         && (allow_func_align || TREE_CODE (expr) != FUNCTION_DECL))
!       return DECL_ALIGN_UNIT (expr);
      }
    else if (code == POINTER_PLUS_EXPR)
      {
--- 9230,9239 ----
    code = TREE_CODE (expr);
    if (code == ADDR_EXPR)
      {
!       unsigned int bitalign;
!       bitalign = get_object_alignment_1 (TREE_OPERAND (expr, 0), residue);
!       *residue /= BITS_PER_UNIT;
!       return bitalign / BITS_PER_UNIT;
      }
    else if (code == POINTER_PLUS_EXPR)
      {
*************** get_pointer_modulus_and_residue (tree ex
*** 9298,9306 ****
        }
      }
  
!     /* If we get here, we were unable to determine anything useful about the
!        expression.  */
!     return 1;
  }
  
  
--- 9278,9286 ----
        }
      }
  
!   /* If we get here, we were unable to determine anything useful about the
!      expression.  */
!   return 1;
  }
  
  
Index: gcc/testsuite/c-c++-common/fold-bitand-4.c
===================================================================
*** gcc/testsuite/c-c++-common/fold-bitand-4.c  (revision 0)
--- gcc/testsuite/c-c++-common/fold-bitand-4.c  (revision 0)
***************
*** 0 ****
--- 1,45 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fdump-tree-original" } */
+ /* { dg-options "-fdump-tree-original -fno-common" { target hppa*-*-hpux* } } 
*/
+ 
+ typedef char char4[4] __attribute__ ((aligned (4)));
+ char4 c4[4] __attribute__ ((aligned (16)));
+ 
+ typedef char char16[16] __attribute__ ((aligned (16)));
+ char16 c16[4] __attribute__ ((aligned (4)));
+ 
+ int f1 (void)
+ {
+   /* 12 */
+   return 15 & (__SIZE_TYPE__)&c4[3];
+ }
+ 
+ int f2 (int i)
+ {
+   /* Indeterminate */
+   return 15 & (__SIZE_TYPE__)&c4[i];
+ }
+ 
+ int f3 (int i)
+ {
+   /* 0 */
+   return 3 & (__SIZE_TYPE__)&c4[i];
+ }
+ 
+ int f4 (int i)
+ {
+   /* Indeterminate */
+   return 7 & (__SIZE_TYPE__)&c16[i];
+ }
+ 
+ int f5 (int i)
+ {
+   /* 0 */
+   return 3 & (__SIZE_TYPE__)&c16[i];
+ }
+ 
+ /* { dg-final { scan-tree-dump-times "return \[^\n0-9\]*12;" 1 "original" } } 
*/
+ /* { dg-final { scan-tree-dump-times "\& 15" 1 "original" } } */
+ /* { dg-final { scan-tree-dump-times "return \[^\n0-9\]*0;" 2 "original" } } 
*/
+ /* { dg-final { scan-tree-dump-times "\& 7" 1 "original" } } */
+ /* { dg-final { cleanup-tree-dump "original" } } */

Reply via email to