This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [patch] Fix ICE on unaligned record field
- From: Martin Jambor <mjambor at suse dot cz>
- To: Richard Biener <richard dot guenther at gmail dot com>
- Cc: Eric Botcazou <ebotcazou at adacore dot com>, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 3 Dec 2014 15:02:07 +0100
- Subject: Re: [patch] Fix ICE on unaligned record field
- Authentication-results: sourceware.org; auth=none
- References: <3887233 dot jQSJCmu5YU at polaris> <CAFiYyc1S==cr8Aq_YxCmFfcCDE21eH8AnO4n1Ri8F-K7_y8_yg at mail dot gmail dot com>
Hi,
On Mon, Dec 01, 2014 at 12:00:14PM +0100, Richard Biener wrote:
> On Fri, Nov 28, 2014 at 5:20 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> > Hi,
> >
> > the attached Ada testcase triggers an assertion in the RTL expander for the
> > address operator because the operator has been applied to a non-byte-aligned
> > record field. The problematic ADDR_EXPR is built by ipa_modify_call_arguments
> > which has a hole when get_addr_base_and_unit_offset returns NULL_TREE: the
> > variable offset case is handled but not the non-byte-aligned case, which can
> > rountinely happen in Ada, hence the proposed fix.
> >
> > Tested on x86_64-suse-linux, OK for the mainline?
>
> Umm. So you are doing a possibly aggregate copy here? Or how
> are we sure we are dealing with a register op only? (the function
> is always a twisted maze to me...)
>
> That said - I suppose this is called from IPA-SRA? In that case,
> can't we please avoid doing the transform in the first place?
>
I suppose that could be done by something like the following, which I
have tested only very mildly so far, in particular I have not double
checked that get_inner_reference is cfun-agnostic.
Hope it helps,
Martin
2014-12-03 Martin Jambor <mjambor@suse.cz>
* 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.
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index f213c80..900f3c3 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -4977,13 +4977,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;
}
@@ -5038,14 +5079,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)
@@ -5064,6 +5097,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;
}