aboutsummaryrefslogtreecommitdiff
path: root/gcc/lra.c
diff options
context:
space:
mode:
authorVladimir N. Makarov <vmakarov@redhat.com>2020-11-13 12:45:59 -0500
committerVladimir N. Makarov <vmakarov@redhat.com>2020-11-13 13:01:51 -0500
commite3b3b59683c1e7d31a9d313dd97394abebf644be (patch)
tree34a176a8e704a5a27a214f391da1c5ca041a2462 /gcc/lra.c
parent67100cb50ea22e1fc855360b887959f874fafe2c (diff)
downloadgcc-e3b3b59683c1e7d31a9d313dd97394abebf644be.zip
gcc-e3b3b59683c1e7d31a9d313dd97394abebf644be.tar.gz
gcc-e3b3b59683c1e7d31a9d313dd97394abebf644be.tar.bz2
[PATCH] Implementation of asm goto outputs
gcc/ * cfgexpand.c (expand_asm_stmt): Output asm goto with outputs too. Place insns after asm goto on edges. * doc/extend.texi: Reflect the changes in asm goto documentation. * gimple.c (gimple_build_asm_1): Remove an assert checking output absence for asm goto. * gimple.h (gimple_asm_label_op, gimple_asm_set_label_op): Take possible asm goto outputs into account. * ira.c (ira): Remove critical edges for potential asm goto output reloads. (ira_nullify_asm_goto): New function. * ira.h (ira_nullify_asm_goto): New prototype. * lra-assigns.c (lra_split_hard_reg_for): Use ira_nullify_asm_goto. Check that splitting is done inside a basic block. * lra-constraints.c (curr_insn_transform): Permit output reloads for any jump insn. * lra-spills.c (lra_final_code_change): Remove USEs added in ira for asm gotos. * lra.c (lra_process_new_insns): Place output reload insns after jumps in the beginning of destination BBs. * reload.c (find_reloads): Report error for asm gotos with outputs. Modify them to keep CFG consistency to avoid crashes. * tree-into-ssa.c (rewrite_stmt): Don't put debug stmt after asm goto. gcc/c/ * c-parser.c (c_parser_asm_statement): Parse outputs for asm goto too. * c-typeck.c (build_asm_expr): Remove an assert checking output absence for asm goto. gcc/cp * parser.c (cp_parser_asm_definition): Parse outputs for asm goto too. gcc/testsuite/ * c-c++-common/asmgoto-2.c: Permit output in asm goto. * gcc.c-torture/compile/asmgoto-2.c: New. * gcc.c-torture/compile/asmgoto-3.c: New. * gcc.c-torture/compile/asmgoto-4.c: New. * gcc.c-torture/compile/asmgoto-5.c: New.
Diffstat (limited to 'gcc/lra.c')
-rw-r--r--gcc/lra.c69
1 files changed, 56 insertions, 13 deletions
diff --git a/gcc/lra.c b/gcc/lra.c
index 664f1b5..673554d 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -1852,8 +1852,6 @@ void
lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
const char *title)
{
- rtx_insn *last;
-
if (before == NULL_RTX && after == NULL_RTX)
return;
if (lra_dump_file != NULL)
@@ -1864,12 +1862,6 @@ lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
fprintf (lra_dump_file," %s before:\n", title);
dump_rtl_slim (lra_dump_file, before, NULL, -1, 0);
}
- if (after != NULL_RTX)
- {
- fprintf (lra_dump_file, " %s after:\n", title);
- dump_rtl_slim (lra_dump_file, after, NULL, -1, 0);
- }
- fprintf (lra_dump_file, "\n");
}
if (before != NULL_RTX)
{
@@ -1883,12 +1875,63 @@ lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
{
if (cfun->can_throw_non_call_exceptions)
copy_reg_eh_region_note_forward (insn, after, NULL);
- for (last = after; NEXT_INSN (last) != NULL_RTX; last = NEXT_INSN (last))
- ;
- emit_insn_after (after, insn);
- push_insns (last, insn);
- setup_sp_offset (after, last);
+ if (! JUMP_P (insn))
+ {
+ rtx_insn *last;
+
+ if (lra_dump_file != NULL)
+ {
+ fprintf (lra_dump_file, " %s after:\n", title);
+ dump_rtl_slim (lra_dump_file, after, NULL, -1, 0);
+ }
+ for (last = after;
+ NEXT_INSN (last) != NULL_RTX;
+ last = NEXT_INSN (last))
+ ;
+ emit_insn_after (after, insn);
+ push_insns (last, insn);
+ setup_sp_offset (after, last);
+ }
+ else
+ {
+ /* Put output reload insns on successor BBs: */
+ edge_iterator ei;
+ edge e;
+
+ FOR_EACH_EDGE (e, ei, BLOCK_FOR_INSN (insn)->succs)
+ if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
+ {
+ /* We already made the edge no-critical in ira.c::ira */
+ lra_assert (!EDGE_CRITICAL_P (e));
+ rtx_insn *tmp = BB_HEAD (e->dest);
+ if (LABEL_P (tmp))
+ tmp = NEXT_INSN (tmp);
+ if (NOTE_INSN_BASIC_BLOCK_P (tmp))
+ tmp = NEXT_INSN (tmp);
+ start_sequence ();
+ for (rtx_insn *curr = after;
+ curr != NULL_RTX;
+ curr = NEXT_INSN (curr))
+ emit_insn (copy_insn (PATTERN (curr)));
+ rtx_insn *copy = get_insns (), *last = get_last_insn ();
+ end_sequence ();
+ if (lra_dump_file != NULL)
+ {
+ fprintf (lra_dump_file, " %s after in bb%d:\n", title,
+ e->dest->index);
+ dump_rtl_slim (lra_dump_file, copy, NULL, -1, 0);
+ }
+ emit_insn_before (copy, tmp);
+ push_insns (last, PREV_INSN (copy));
+ setup_sp_offset (copy, last);
+ /* We can ignore BB live info here as it and reg notes
+ will be updated before the next assignment
+ sub-pass. */
+ }
+ }
}
+ if (lra_dump_file != NULL)
+ fprintf (lra_dump_file, "\n");
if (cfun->can_throw_non_call_exceptions)
{
rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);