Make SRA qsort comparator transitive
authorMartin Jambor <mjambor@suse.cz>
Tue, 26 Sep 2017 17:15:29 +0000 (19:15 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Tue, 26 Sep 2017 17:15:29 +0000 (19:15 +0200)
2017-09-26  Martin Jambor  <mjambor@suse.cz>

* tree-sra.c (compare_access_positions): Put integral types first,
stabilize sorting of integral types, remove conditions putting
non-full-precision integers last.
(sort_and_splice_var_accesses): Disable scalarization if a
non-integert would be represented by a non-full-precision integer.

From-SVN: r253207

gcc/ChangeLog
gcc/tree-sra.c

index 916a33ad2e3a940ffd4e65afd41ad6d5ef4c1548..b2a2755dcf4072bbed8ba5f29031cbd31bb2fe53 100644 (file)
@@ -1,3 +1,11 @@
+2017-09-26  Martin Jambor  <mjambor@suse.cz>
+
+       * tree-sra.c (compare_access_positions): Put integral types first,
+       stabilize sorting of integral types, remove conditions putting
+       non-full-precision integers last.
+       (sort_and_splice_var_accesses): Disable scalarization if a
+       non-integert would be represented by a non-full-precision integer.
+
 2017-09-26  Joseph Myers  <joseph@codesourcery.com>
 
        * config/microblaze/linux.h (TARGET_ASM_FILE_END): Likewise.
index 163b7a2d03b27a6527c735019b9812e58419b982..f5675edc7f1090d79e04398c6707c4af60f78454 100644 (file)
@@ -1542,19 +1542,20 @@ compare_access_positions (const void *a, const void *b)
               && TREE_CODE (f2->type) != COMPLEX_TYPE
               && TREE_CODE (f2->type) != VECTOR_TYPE)
        return -1;
-      /* Put the integral type with the bigger precision first.  */
+      /* Put any integral type before any non-integral type.  When splicing, we
+        make sure that those with insufficient precision and occupying the
+        same space are not scalarized.  */
       else if (INTEGRAL_TYPE_P (f1->type)
+              && !INTEGRAL_TYPE_P (f2->type))
+       return -1;
+      else if (!INTEGRAL_TYPE_P (f1->type)
               && INTEGRAL_TYPE_P (f2->type))
-       return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
-      /* Put any integral type with non-full precision last.  */
-      else if (INTEGRAL_TYPE_P (f1->type)
-              && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
-                  != TYPE_PRECISION (f1->type)))
        return 1;
-      else if (INTEGRAL_TYPE_P (f2->type)
-              && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
-                  != TYPE_PRECISION (f2->type)))
-       return -1;
+      /* Put the integral type with the bigger precision first.  */
+      else if (INTEGRAL_TYPE_P (f1->type)
+              && INTEGRAL_TYPE_P (f2->type)
+              && (TYPE_PRECISION (f2->type) != TYPE_PRECISION (f1->type)))
+       return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
       /* Stabilize the sort.  */
       return TYPE_UID (f1->type) - TYPE_UID (f2->type);
     }
@@ -2055,6 +2056,11 @@ sort_and_splice_var_accesses (tree var)
       bool grp_partial_lhs = access->grp_partial_lhs;
       bool first_scalar = is_gimple_reg_type (access->type);
       bool unscalarizable_region = access->grp_unscalarizable_region;
+      bool bf_non_full_precision
+       = (INTEGRAL_TYPE_P (access->type)
+          && TYPE_PRECISION (access->type) != access->size
+          && TREE_CODE (access->expr) == COMPONENT_REF
+          && DECL_BIT_FIELD (TREE_OPERAND (access->expr, 1)));
 
       if (first || access->offset >= high)
        {
@@ -2102,6 +2108,22 @@ sort_and_splice_var_accesses (tree var)
             this combination of size and offset, the comparison function
             should have put the scalars first.  */
          gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
+         /* It also prefers integral types to non-integral.  However, when the
+            precision of the selected type does not span the entire area and
+            should also be used for a non-integer (i.e. float), we must not
+            let that happen.  Normally analyze_access_subtree expands the type
+            to cover the entire area but for bit-fields it doesn't.  */
+         if (bf_non_full_precision && !INTEGRAL_TYPE_P (ac2->type))
+           {
+             if (dump_file && (dump_flags & TDF_DETAILS))
+               {
+                 fprintf (dump_file, "Cannot scalarize the following access "
+                          "because insufficient precision integer type was "
+                          "selected.\n  ");
+                 dump_access (dump_file, access, false);
+               }
+             unscalarizable_region = true;
+           }
          ac2->group_representative = access;
          j++;
        }