This fixes PR52720.

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

Richard.

2012-03-27  Richard Guenther  <rguent...@suse.de>

        PR middle-end/52720
        * fold-const.c (try_move_mult_to_index): Handle &x.array more
        explicitely.

        * gcc.dg/torture/pr52720.c: New testcase.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c    (revision 185725)
--- gcc/fold-const.c    (working copy)
*************** try_move_mult_to_index (location_t loc,
*** 6850,6913 ****
        s = integer_one_node;
      }
  
!   for (;; ref = TREE_OPERAND (ref, 0))
      {
!       if (TREE_CODE (ref) == ARRAY_REF)
!       {
!         tree domain;
  
!         /* Remember if this was a multi-dimensional array.  */
!         if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
!           mdim = true;
  
!         domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
!         if (! domain)
!           continue;
!         itype = TREE_TYPE (domain);
  
!         step = array_ref_element_size (ref);
!         if (TREE_CODE (step) != INTEGER_CST)
!           continue;
  
!         if (s)
!           {
!             if (! tree_int_cst_equal (step, s))
!                 continue;
!           }
!         else
!           {
!             /* Try if delta is a multiple of step.  */
!             tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, op1, step);
!             if (! tmp)
!               continue;
!             delta = tmp;
!           }
  
!         /* Only fold here if we can verify we do not overflow one
!            dimension of a multi-dimensional array.  */
!         if (mdim)
!           {
!             tree tmp;
  
!             if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST
!                 || !TYPE_MAX_VALUE (domain)
!                 || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
!               continue;
  
!             tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
!                                    fold_convert_loc (loc, itype,
!                                                      TREE_OPERAND (ref, 1)),
!                                    fold_convert_loc (loc, itype, delta));
!             if (!tmp
!                 || TREE_CODE (tmp) != INTEGER_CST
!                 || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
!               continue;
!           }
  
!         break;
!       }
!       else if (TREE_CODE (ref) == COMPONENT_REF
!              && TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
        {
          tree domain;
  
--- 6850,6930 ----
        s = integer_one_node;
      }
  
!   /* Handle &x.array the same as we would handle &x.array[0].  */
!   if (TREE_CODE (ref) == COMPONENT_REF
!       && TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
      {
!       tree domain;
  
!       /* Remember if this was a multi-dimensional array.  */
!       if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
!       mdim = true;
! 
!       domain = TYPE_DOMAIN (TREE_TYPE (ref));
!       if (! domain)
!       goto cont;
!       itype = TREE_TYPE (domain);
! 
!       step = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
!       if (TREE_CODE (step) != INTEGER_CST)
!       goto cont;
  
!       if (s)
!       {
!         if (! tree_int_cst_equal (step, s))
!           goto cont;
!       }
!       else
!       {
!         /* Try if delta is a multiple of step.  */
!         tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, op1, step);
!         if (! tmp)
!           goto cont;
!         delta = tmp;
!       }
  
!       /* Only fold here if we can verify we do not overflow one
!        dimension of a multi-dimensional array.  */
!       if (mdim)
!       {
!         tree tmp;
  
!         if (!TYPE_MIN_VALUE (domain)
!             || !TYPE_MAX_VALUE (domain)
!             || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
!           goto cont;
! 
!         tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
!                                fold_convert_loc (loc, itype,
!                                                  TYPE_MIN_VALUE (domain)),
!                                fold_convert_loc (loc, itype, delta));
!         if (TREE_CODE (tmp) != INTEGER_CST
!             || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
!           goto cont;
!       }
  
!       /* We found a suitable component reference.  */
  
!       pref = TREE_OPERAND (addr, 0);
!       ret = copy_node (pref);
!       SET_EXPR_LOCATION (ret, loc);
  
!       ret = build4_loc (loc, ARRAY_REF, TREE_TYPE (TREE_TYPE (ref)), ret,
!                       fold_build2_loc
!                         (loc, PLUS_EXPR, itype,
!                          fold_convert_loc (loc, itype,
!                                            TYPE_MIN_VALUE
!                                              (TYPE_DOMAIN (TREE_TYPE (ref)))),
!                          fold_convert_loc (loc, itype, delta)),
!                       NULL_TREE, NULL_TREE);
!       return build_fold_addr_expr_loc (loc, ret);
!     }
  
! cont:
! 
!   for (;; ref = TREE_OPERAND (ref, 0))
!     {
!       if (TREE_CODE (ref) == ARRAY_REF)
        {
          tree domain;
  
*************** try_move_mult_to_index (location_t loc,
*** 6915,6926 ****
          if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
            mdim = true;
  
!         domain = TYPE_DOMAIN (TREE_TYPE (ref));
          if (! domain)
            continue;
          itype = TREE_TYPE (domain);
  
!         step = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
          if (TREE_CODE (step) != INTEGER_CST)
            continue;
  
--- 6932,6943 ----
          if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
            mdim = true;
  
!         domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
          if (! domain)
            continue;
          itype = TREE_TYPE (domain);
  
!         step = array_ref_element_size (ref);
          if (TREE_CODE (step) != INTEGER_CST)
            continue;
  
*************** try_move_mult_to_index (location_t loc,
*** 6944,6959 ****
            {
              tree tmp;
  
!             if (!TYPE_MIN_VALUE (domain)
                  || !TYPE_MAX_VALUE (domain)
                  || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
                continue;
  
              tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
                                     fold_convert_loc (loc, itype,
!                                                      TYPE_MIN_VALUE (domain)),
                                     fold_convert_loc (loc, itype, delta));
!             if (TREE_CODE (tmp) != INTEGER_CST
                  || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
                continue;
            }
--- 6961,6977 ----
            {
              tree tmp;
  
!             if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST
                  || !TYPE_MAX_VALUE (domain)
                  || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
                continue;
  
              tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
                                     fold_convert_loc (loc, itype,
!                                                      TREE_OPERAND (ref, 1)),
                                     fold_convert_loc (loc, itype, delta));
!             if (!tmp
!                 || TREE_CODE (tmp) != INTEGER_CST
                  || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
                continue;
            }
*************** try_move_mult_to_index (location_t loc,
*** 6982,7010 ****
        pos = TREE_OPERAND (pos, 0);
      }
  
!   if (TREE_CODE (ref) == ARRAY_REF)
!     {
!       TREE_OPERAND (pos, 1)
!       = fold_build2_loc (loc, PLUS_EXPR, itype,
!                          fold_convert_loc (loc, itype, TREE_OPERAND (pos, 1)),
!                          fold_convert_loc (loc, itype, delta));
!       return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret);
!     }
!   else if (TREE_CODE (ref) == COMPONENT_REF)
!     {
!       gcc_assert (ret == pos);
!       ret = build4_loc (loc, ARRAY_REF, TREE_TYPE (TREE_TYPE (ref)), ret,
!                       fold_build2_loc
!                         (loc, PLUS_EXPR, itype,
!                          fold_convert_loc (loc, itype,
!                                            TYPE_MIN_VALUE
!                                              (TYPE_DOMAIN (TREE_TYPE (ref)))),
!                          fold_convert_loc (loc, itype, delta)),
!                       NULL_TREE, NULL_TREE);
!       return build_fold_addr_expr_loc (loc, ret);
!     }
!   else
!     gcc_unreachable ();
  }
  
  
--- 7000,7010 ----
        pos = TREE_OPERAND (pos, 0);
      }
  
!   TREE_OPERAND (pos, 1)
!     = fold_build2_loc (loc, PLUS_EXPR, itype,
!                      fold_convert_loc (loc, itype, TREE_OPERAND (pos, 1)),
!                      fold_convert_loc (loc, itype, delta));
!   return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret);
  }
  
  
Index: gcc/testsuite/gcc.dg/torture/pr52720.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr52720.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr52720.c      (revision 0)
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=k8-sse3" { target x86_64-*-* } } */
+ 
+ struct alu_bank_swizzle {
+     int hw_gpr[3][4];
+     int hw_cfile_addr[4];
+ };
+ static void init_bank_swizzle(struct alu_bank_swizzle *bs)
+ {
+   int i, cycle, component;
+   for (cycle = 0; cycle < 3; cycle++)
+     for (component = 0; component < 4; component++)
+       bs->hw_gpr[cycle][component] = -1;
+   for (i = 0; i < 4; i++) 
+     bs->hw_cfile_addr[i] = -1;
+ }
+ int check_and_set_bank_swizzle(int max_slots, int *slots)
+ {
+   struct alu_bank_swizzle bs;
+   int i;
+   for (i = 0; i < max_slots; i++)
+     {
+       init_bank_swizzle(&bs);
+       if (slots[i])
+       check_vector(&bs); 
+     }
+ }
+ 

Reply via email to