This fixes BIT_FIELD_REF handling in bswap pass where we need to 
distinguish an "operation" vs. a load properly.

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

Richard.

2016-06-07  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/71428
        * tree-ssa-math-opts.c (perform_symbolic_merge): Properly distinguish
        BIT_FIELD_REF op vs. load.

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

Index: gcc/tree-ssa-math-opts.c
===================================================================
*** gcc/tree-ssa-math-opts.c    (revision 237117)
--- gcc/tree-ssa-math-opts.c    (working copy)
*************** perform_symbolic_merge (gimple *source_s
*** 2164,2173 ****
    struct symbolic_number *n_start;
  
    tree rhs1 = gimple_assign_rhs1 (source_stmt1);
!   if (TREE_CODE (rhs1) == BIT_FIELD_REF)
      rhs1 = TREE_OPERAND (rhs1, 0);
    tree rhs2 = gimple_assign_rhs1 (source_stmt2);
!   if (TREE_CODE (rhs2) == BIT_FIELD_REF)
      rhs2 = TREE_OPERAND (rhs2, 0);
  
    /* Sources are different, cancel bswap if they are not memory location with
--- 2164,2175 ----
    struct symbolic_number *n_start;
  
    tree rhs1 = gimple_assign_rhs1 (source_stmt1);
!   if (TREE_CODE (rhs1) == BIT_FIELD_REF
!       && TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME)
      rhs1 = TREE_OPERAND (rhs1, 0);
    tree rhs2 = gimple_assign_rhs1 (source_stmt2);
!   if (TREE_CODE (rhs2) == BIT_FIELD_REF
!       && TREE_CODE (TREE_OPERAND (rhs2, 0)) == SSA_NAME)
      rhs2 = TREE_OPERAND (rhs2, 0);
  
    /* Sources are different, cancel bswap if they are not memory location with
Index: gcc/testsuite/gcc.dg/torture/pr71428.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr71428.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr71428.c      (working copy)
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do run } */
+ /* { dg-additional-options "-fno-tree-forwprop -Wno-psabi -w" } */
+ 
+ typedef unsigned short v64u16 __attribute__ ((vector_size (64)));
+ 
+ v64u16
+ foo (v64u16 p1)
+ {
+   p1[31] |= p1[1];
+   return p1;
+ }
+ 
+ int
+ main ()
+ {
+   v64u16 x = foo ((v64u16){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 });
+   if (x[31] != 1)
+     __builtin_abort();
+   return 0;
+ }

Reply via email to