summaryrefslogtreecommitdiff
path: root/gcc/tree-sra.c
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2015-03-03 14:58:15 +0100
committerMartin Jambor <jamborm@gcc.gnu.org>2015-03-03 14:58:15 +0100
commitebde4f8e394d77663f500360e7f20a42cc471f85 (patch)
treeb1959337d9cc7caa96e5b56c85185acc75837d71 /gcc/tree-sra.c
parent21ce14d309100d40a7f0340b66af22bf28f5ef5b (diff)
downloadgcc-ebde4f8e394d77663f500360e7f20a42cc471f85.tar.gz
tree-sra.c (ipa_sra_check_caller_data): New type.
2015-03-03 Martin Jambor <mjambor@suse.cz> Eric Botcazou <ebotcazou@adacore.com> gcc/ * tree-sra.c (ipa_sra_check_caller_data): New type. (has_caller_p): Removed. (ipa_sra_check_caller): New function. (ipa_sra_preliminary_function_checks): Use it. gcc/changelog/ * gnat.dg/specs/pack12.ads: New test. Co-Authored-By: Eric Botcazou <ebotcazou@adacore.com> From-SVN: r221148
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r--gcc/tree-sra.c76
1 files changed, 64 insertions, 12 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 023b8172300..a6cddafe44b 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -5009,13 +5009,54 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
return cfg_changed;
}
-/* If NODE has a caller, return true. */
+/* Means of communication between ipa_sra_check_caller and
+ ipa_sra_preliminary_function_checks. */
+
+struct ipa_sra_check_caller_data
+{
+ bool has_callers;
+ bool bad_arg_alignment;
+};
+
+/* If NODE has a caller, mark that fact in DATA which is pointer to
+ ipa_sra_check_caller_data. Also check all aggregate arguments in all known
+ calls if they are unit aligned and if not, set the appropriate flag in DATA
+ too. */
static bool
-has_caller_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+ipa_sra_check_caller (struct cgraph_node *node, void *data)
{
- if (node->callers)
- return true;
+ if (!node->callers)
+ return false;
+
+ struct ipa_sra_check_caller_data *iscc;
+ iscc = (struct ipa_sra_check_caller_data *) data;
+ iscc->has_callers = true;
+
+ for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
+ {
+ gimple call_stmt = cs->call_stmt;
+ unsigned count = gimple_call_num_args (call_stmt);
+ for (unsigned i = 0; i < count; i++)
+ {
+ tree arg = gimple_call_arg (call_stmt, i);
+ if (is_gimple_reg (arg))
+ continue;
+
+ tree offset;
+ HOST_WIDE_INT bitsize, bitpos;
+ machine_mode mode;
+ int unsignedp, volatilep = 0;
+ get_inner_reference (arg, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &volatilep, false);
+ if (bitpos % BITS_PER_UNIT)
+ {
+ iscc->bad_arg_alignment = true;
+ return true;
+ }
+ }
+ }
+
return false;
}
@@ -5070,14 +5111,6 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node)
return false;
}
- if (!node->call_for_symbol_thunks_and_aliases (has_caller_p, NULL, true))
- {
- if (dump_file)
- fprintf (dump_file,
- "Function has no callers in this compilation unit.\n");
- return false;
- }
-
if (cfun->stdarg)
{
if (dump_file)
@@ -5096,6 +5129,25 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node)
return false;
}
+ struct ipa_sra_check_caller_data iscc;
+ memset (&iscc, 0, sizeof(iscc));
+ node->call_for_symbol_thunks_and_aliases (ipa_sra_check_caller, &iscc, true);
+ if (!iscc.has_callers)
+ {
+ if (dump_file)
+ fprintf (dump_file,
+ "Function has no callers in this compilation unit.\n");
+ return false;
+ }
+
+ if (iscc.bad_arg_alignment)
+ {
+ if (dump_file)
+ fprintf (dump_file,
+ "A function call has an argument with non-unit alignemnt.\n");
+ return false;
+ }
+
return true;
}