summaryrefslogtreecommitdiff
path: root/gcc/tree-sra.c
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2017-09-26 19:15:29 +0200
committerMartin Jambor <jamborm@gcc.gnu.org>2017-09-26 19:15:29 +0200
commit973c150c2d564fbe077f14cb80c17da175c89323 (patch)
tree8608b6c9baa1858a00c6b1d4c38c4a409a782802 /gcc/tree-sra.c
parent5714abfff8a8b04cdd294bd9968bcc72924213ec (diff)
Make SRA qsort comparator transitive
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
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r--gcc/tree-sra.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 163b7a2d03b..f5675edc7f1 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -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++;
}