[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.
This commit is contained in:
Vladimir N. Makarov
2020-11-13 12:45:59 -05:00
parent 67100cb50e
commit e3b3b59683
20 changed files with 455 additions and 59 deletions

View File

@@ -7144,10 +7144,7 @@ c_parser_asm_statement (c_parser *parser)
switch (section)
{
case 0:
/* For asm goto, we don't allow output operands, but reserve
the slot for a future extension that does allow them. */
if (!is_goto)
outputs = c_parser_asm_operands (parser);
outputs = c_parser_asm_operands (parser);
break;
case 1:
inputs = c_parser_asm_operands (parser);

View File

@@ -10666,10 +10666,6 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
TREE_VALUE (tail) = input;
}
/* ASMs with labels cannot have outputs. This should have been
enforced by the parser. */
gcc_assert (outputs == NULL || labels == NULL);
args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, labels);
/* asm statements without outputs, including simple ones, are treated

View File

@@ -3371,20 +3371,21 @@ expand_asm_stmt (gasm *stmt)
ARGVEC CONSTRAINTS OPNAMES))
If there is more than one, put them inside a PARALLEL. */
if (nlabels > 0 && nclobbers == 0)
{
gcc_assert (noutputs == 0);
emit_jump_insn (body);
}
else if (noutputs == 0 && nclobbers == 0)
if (noutputs == 0 && nclobbers == 0)
{
/* No output operands: put in a raw ASM_OPERANDS rtx. */
emit_insn (body);
if (nlabels > 0)
emit_jump_insn (body);
else
emit_insn (body);
}
else if (noutputs == 1 && nclobbers == 0)
{
ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = constraints[0];
emit_insn (gen_rtx_SET (output_rvec[0], body));
if (nlabels > 0)
emit_jump_insn (gen_rtx_SET (output_rvec[0], body));
else
emit_insn (gen_rtx_SET (output_rvec[0], body));
}
else
{
@@ -3461,7 +3462,27 @@ expand_asm_stmt (gasm *stmt)
if (after_md_seq)
emit_insn (after_md_seq);
if (after_rtl_seq)
emit_insn (after_rtl_seq);
{
if (nlabels == 0)
emit_insn (after_rtl_seq);
else
{
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs)
{
start_sequence ();
for (rtx_insn *curr = after_rtl_seq;
curr != NULL_RTX;
curr = NEXT_INSN (curr))
emit_insn (copy_insn (PATTERN (curr)));
rtx_insn *copy = get_insns ();
end_sequence ();
insert_insn_on_edge (copy, e);
}
}
}
free_temp_slots ();
crtl->has_asm_statement = 1;

View File

@@ -20534,8 +20534,7 @@ cp_parser_asm_definition (cp_parser* parser)
&& cp_lexer_next_token_is_not (parser->lexer,
CPP_SCOPE)
&& cp_lexer_next_token_is_not (parser->lexer,
CPP_CLOSE_PAREN)
&& !goto_p)
CPP_CLOSE_PAREN))
{
outputs = cp_parser_asm_operand_list (parser);
if (outputs == error_mark_node)

View File

@@ -9566,7 +9566,7 @@ asm @var{asm-qualifiers} ( @var{AssemblerTemplate}
@r{[} : @var{Clobbers} @r{]} @r{]})
asm @var{asm-qualifiers} ( @var{AssemblerTemplate}
:
: @var{OutputOperands}
: @var{InputOperands}
: @var{Clobbers}
: @var{GotoLabels})
@@ -9673,7 +9673,7 @@ there is no need for the output variables. Also, the optimizers may move
code out of loops if they believe that the code will always return the same
result (i.e.@: none of its input values change between calls). Using the
@code{volatile} qualifier disables these optimizations. @code{asm} statements
that have no output operands, including @code{asm goto} statements,
that have no output operands and @code{asm goto} statements,
are implicitly volatile.
This i386 code demonstrates a case that does not use (or require) the
@@ -10532,9 +10532,6 @@ case, consider using the @code{__builtin_unreachable} intrinsic after the
using the @code{hot} and @code{cold} label attributes (@pxref{Label
Attributes}).
An @code{asm goto} statement cannot have outputs.
This is due to an internal restriction of
the compiler: control transfer instructions cannot have outputs.
If the assembler code does modify anything, use the @code{"memory"} clobber
to force the
optimizers to flush all register values to memory and reload them if
@@ -10543,6 +10540,13 @@ necessary after the @code{asm} statement.
Also note that an @code{asm goto} statement is always implicitly
considered volatile.
Be careful when you set output operands inside @code{asm goto} only on
some possible control flow paths. If you don't set up the output on
given path and never use it on this path, it is okay. Otherwise, you
should use @samp{+} constraint modifier meaning that the operand is
input and output one. With this modifier you will have the correct
values on all possible paths from the @code{asm goto}.
To reference a label in the assembler template,
prefix it with @samp{%l} (lowercase @samp{L}) followed
by its (zero-based) position in @var{GotoLabels} plus the number of input
@@ -10588,6 +10592,41 @@ error:
@}
@end example
The following example shows an @code{asm goto} that uses an output.
@example
int foo(int count)
@{
asm goto ("dec %0; jb %l[stop]"
: "+r" (count)
:
:
: stop);
return count;
stop:
return 0;
@}
@end example
The following artificial example shows an @code{asm goto} that sets
up an output only on one path inside the @code{asm goto}. Usage of
constraint modifier @code{=} instead of @code{+} would be wrong as
@code{factor} is used on all paths from the @code{asm goto}.
@example
int foo(int inp)
@{
int factor = 0;
asm goto ("cmp %1, 10; jb %l[lab]; mov 2, %0"
: "+r" (factor)
: "r" (inp)
:
: lab);
lab:
return inp * factor; /* return 2 * inp or 0 if inp < 10 */
@}
@end example
@anchor{x86Operandmodifiers}
@subsubsection x86 Operand Modifiers

View File

@@ -611,10 +611,6 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
gasm *p;
int size = strlen (string);
/* ASMs with labels cannot have outputs. This should have been
enforced by the front end. */
gcc_assert (nlabels == 0 || noutputs == 0);
p = as_a <gasm *> (
gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
ninputs + noutputs + nclobbers + nlabels));

View File

@@ -4025,7 +4025,7 @@ static inline tree
gimple_asm_label_op (const gasm *asm_stmt, unsigned index)
{
gcc_gimple_checking_assert (index < asm_stmt->nl);
return asm_stmt->op[index + asm_stmt->ni + asm_stmt->nc];
return asm_stmt->op[index + asm_stmt->no + asm_stmt->ni + asm_stmt->nc];
}
/* Set LABEL_OP to be label operand INDEX in GIMPLE_ASM ASM_STMT. */
@@ -4035,7 +4035,7 @@ gimple_asm_set_label_op (gasm *asm_stmt, unsigned index, tree label_op)
{
gcc_gimple_checking_assert (index < asm_stmt->nl
&& TREE_CODE (label_op) == TREE_LIST);
asm_stmt->op[index + asm_stmt->ni + asm_stmt->nc] = label_op;
asm_stmt->op[index + asm_stmt->no + asm_stmt->ni + asm_stmt->nc] = label_op;
}
/* Return the string representing the assembly instruction in

View File

@@ -5401,6 +5401,48 @@ ira (FILE *f)
int ira_max_point_before_emit;
bool saved_flag_caller_saves = flag_caller_saves;
enum ira_region saved_flag_ira_region = flag_ira_region;
basic_block bb;
edge_iterator ei;
edge e;
bool output_jump_reload_p = false;
if (ira_use_lra_p)
{
/* First put potential jump output reloads on the output edges
as USE which will be removed at the end of LRA. The major
goal is actually to create BBs for critical edges for LRA and
populate them later by live info. In LRA it will be
difficult to do this. */
FOR_EACH_BB_FN (bb, cfun)
{
rtx_insn *end = BB_END (bb);
if (!JUMP_P (end))
continue;
extract_insn (end);
for (int i = 0; i < recog_data.n_operands; i++)
if (recog_data.operand_type[i] != OP_IN)
{
output_jump_reload_p = true;
FOR_EACH_EDGE (e, ei, bb->succs)
if (EDGE_CRITICAL_P (e)
&& e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
{
ira_assert (!(e->flags & EDGE_ABNORMAL));
start_sequence ();
/* We need to put some no-op insn here. We can
not put a note as commit_edges insertion will
fail. */
emit_insn (gen_rtx_USE (VOIDmode, const1_rtx));
rtx_insn *insns = get_insns ();
end_sequence ();
insert_insn_on_edge (insns, e);
}
break;
}
}
if (output_jump_reload_p)
commit_edge_insertions ();
}
if (flag_ira_verbose < 10)
{
@@ -5709,6 +5751,21 @@ ira (FILE *f)
}
}
/* Modify asm goto to avoid further trouble with this insn. We can
not replace the insn by USE as in other asm insns as we still
need to keep CFG consistency. */
void
ira_nullify_asm_goto (rtx_insn *insn)
{
ira_assert (JUMP_P (insn) && INSN_CODE (insn) < 0);
rtx tmp = extract_asm_operands (PATTERN (insn));
PATTERN (insn) = gen_rtx_ASM_OPERANDS (VOIDmode, ggc_strdup (""), "", 0,
rtvec_alloc (0),
rtvec_alloc (0),
ASM_OPERANDS_LABEL_VEC (tmp),
ASM_OPERANDS_SOURCE_LOCATION(tmp));
}
static void
do_reload (void)
{

View File

@@ -213,6 +213,7 @@ extern void ira_register_new_scratch_op (rtx_insn *insn, int nop, int icode);
extern bool ira_remove_insn_scratches (rtx_insn *insn, bool all_p, FILE *dump_file,
rtx (*get_reg) (rtx original));
extern void ira_restore_scratches (FILE *dump_file);
extern void ira_nullify_asm_goto (rtx_insn *insn);
/* ira-costs.c */
extern void ira_costs_c_finalize (void);

View File

@@ -1715,8 +1715,8 @@ find_reload_regno_insns (int regno, rtx_insn * &start, rtx_insn * &finish)
start_insn = lra_insn_recog_data[uid]->insn;
n++;
}
/* For reload pseudo we should have at most 3 insns referring for it:
input/output reload insns and the original insn. */
/* For reload pseudo we should have at most 3 insns referring for
it: input/output reload insns and the original insn. */
if (n > 3)
return false;
if (n > 1)
@@ -1792,7 +1792,8 @@ lra_split_hard_reg_for (void)
{
if (! find_reload_regno_insns (i, first, last))
continue;
if (spill_hard_reg_in_range (i, rclass, first, last))
if (BLOCK_FOR_INSN (first) == BLOCK_FOR_INSN (last)
&& spill_hard_reg_in_range (i, rclass, first, last))
{
bitmap_clear (&failed_reload_pseudos);
return true;
@@ -1817,16 +1818,10 @@ lra_split_hard_reg_for (void)
lra_asm_error_p = asm_p = true;
error_for_asm (insn,
"%<asm%> operand has impossible constraints");
/* Avoid further trouble with this insn.
For asm goto, instead of fixing up all the edges
just clear the template and clear input operands
(asm goto doesn't have any output operands). */
/* Avoid further trouble with this insn. */
if (JUMP_P (insn))
{
rtx asm_op = extract_asm_operands (PATTERN (insn));
ASM_OPERANDS_TEMPLATE (asm_op) = ggc_strdup ("");
ASM_OPERANDS_INPUT_VEC (asm_op) = rtvec_alloc (0);
ASM_OPERANDS_INPUT_CONSTRAINT_VEC (asm_op) = rtvec_alloc (0);
ira_nullify_asm_goto (insn);
lra_update_insn_regno_info (insn);
}
else

View File

@@ -3954,10 +3954,10 @@ curr_insn_transform (bool check_only_p)
no_input_reloads_p = no_output_reloads_p = false;
goal_alt_number = -1;
change_p = sec_mem_p = false;
/* JUMP_INSNs and CALL_INSNs are not allowed to have any output
reloads; neither are insns that SET cc0. Insns that use CC0 are
not allowed to have any input reloads. */
if (JUMP_P (curr_insn) || CALL_P (curr_insn))
/* CALL_INSNs are not allowed to have any output reloads; neither
are insns that SET cc0. Insns that use CC0 are not allowed to
have any input reloads. */
if (CALL_P (curr_insn))
no_output_reloads_p = true;
if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (curr_insn)))

View File

@@ -788,6 +788,14 @@ lra_final_code_change (void)
{
rtx pat = PATTERN (insn);
if (GET_CODE (pat) == USE && XEXP (pat, 0) == const1_rtx)
{
/* Remove markers to eliminate critical edges for jump insn
output reloads (see code in ira.c::ira). */
lra_invalidate_insn_data (insn);
delete_insn (insn);
continue;
}
if (GET_CODE (pat) == CLOBBER && LRA_TEMP_CLOBBER_P (pat))
{
/* Remove clobbers temporarily created in LRA. We don't

View File

@@ -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);

View File

@@ -2656,6 +2656,22 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
hard_regs_live_known = live_known;
static_reload_reg_p = reload_reg_p;
if (JUMP_P (insn) && INSN_CODE (insn) < 0)
{
extract_insn (insn);
for (i = 0; i < recog_data.n_operands; i++)
if (recog_data.operand_type[i] != OP_IN)
break;
if (i < recog_data.n_operands)
{
error_for_asm (insn,
"the target does not support asm goto "
"with outputs in %<asm%>");
ira_nullify_asm_goto (insn);
return 0;
}
}
/* JUMP_INSNs and CALL_INSNs are not allowed to have any output reloads;
neither are insns that SET cc0. Insns that use CC0 are not allowed
to have any input reloads. */

View File

@@ -7,7 +7,7 @@ foo (void)
__label__ lab;
int i = 0;
asm goto ("" : : : : lab);
asm goto ("" : "=r" (i) : : : lab); /* { dg-error "expected" } */
asm goto ("" : "=r" (i) : : : lab);
asm goto ("" : : : : ); /* { dg-error "expected" } */
asm goto ("" : : : "memory"); /* { dg-error "expected" } */
asm goto ("" : : : ); /* { dg-error "expected" } */

View File

@@ -0,0 +1,65 @@
/* This test should be switched off for a new target with less than 4 allocatable registers */
/* { dg-do compile } */
int
foo (void)
{
int x, y, z, v;
asm goto ("": "=r" (x), "=r" (y), "=r" (z), "=r" (v) : : : lab, lab2, lab3, lab4);
lab:
return x;
lab2:
return y;
lab3:
return z;
lab4:
return v;
}
int
foo2 (void)
{
int x = 0, y = 1, z = 2, v = 3;
asm goto ("": "+r" (x), "+r" (y), "+r" (z), "+r" (v) : : : lab, lab2, lab3, lab4);
lab:
return x;
lab2:
return y;
lab3:
return z;
lab4:
return v;
}
int
foo3 (void)
{
int x, y, z, v;
asm goto ("": "=rm" (x), "=mr" (y), "=rm" (z), "=mr" (v) : : : lab, lab2, lab3, lab4);
lab:
return x;
lab2:
return y;
lab3:
return z;
lab4:
return v;
}
int
foo4 (void)
{
int x, y, z, v;
asm goto ("": "=r,m" (x), "=m,r" (y), "=r,m" (z), "=m,r" (v) : : : lab, lab2, lab3, lab4);
lab:
return x;
lab2:
return y;
lab3:
return z;
lab4:
return v;
}

View File

@@ -0,0 +1,89 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
int
foo (void)
{
int x;
asm goto ("": "=a" (x) : : : lab);
lab:
return x;
}
int
foo2 (void)
{
int x, y;
asm goto ("": "=a" (x), "=d" (y) : : : lab, lab2);
lab:
return x;
lab2:
return y;
}
int
foo3 (void)
{
int x, y, z;
asm goto ("": "=a" (x), "=d" (y), "=c" (z) : : : lab, lab2, lab3);
lab:
return x;
lab2:
return y;
lab3:
return z;
}
int
foo4 (void)
{
int x, y, z, v;
asm goto ("": "=a" (x), "=d" (y), "=c" (z) , "=b" (v) : : : lab, lab2, lab3, lab4);
lab:
return x;
lab2:
return y;
lab3:
return z;
lab4:
return v;
}
int
foo5 (void)
{
int x, y, z, v, w;
asm goto ("": "=a" (x), "=d" (y), "=c" (z), "=b" (v), "=S" (w) : : : lab, lab2, lab3, lab4, lab5);
lab:
return x;
lab2:
return y;
lab3:
return z;
lab4:
return v;
lab5:
return w;
}
int
foo6 (void)
{
int x = 0, y = 1, z = 2, v = 3, w = 4;
asm goto ("": "+a" (x), "+d" (y), "+c" (z), "+b" (v), "+S" (w) : : : lab, lab2, lab3, lab4, lab5);
lab:
return x;
lab2:
return y;
lab3:
return z;
lab4:
return v;
lab5:
return w;
}

View File

@@ -0,0 +1,14 @@
/* Check that LRA really puts output reloads for p4 in two successors blocks */
/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */
/* { dg-options "-O0 -fdump-rtl-reload" } */
int f (int *p1, int *p2, int *p3, int *p4) {
asm volatile goto (
""
: "=r" (*p2), "=a" (p4)
: "r" (*p2), "r" (p2)
: "r8", "r9" : lab, lab2);
lab: return p2 - p4;
lab2: return p3 - p4;
}
/* { dg-final { scan-rtl-dump-times "Inserting insn reload after in bb" 2 "reload" } } */

View File

@@ -0,0 +1,56 @@
/* Test to generate output reload in asm goto on x86_64. */
/* { dg-do compile } */
/* { dg-skip-if "no O0" { { i?86-*-* x86_64-*-* } && { ! ia32 } } { "-O0" } { "" } } */
#if defined __x86_64__
#define ASM(s) asm (s)
#else
#define ASM(s)
#endif
int
foo (int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8,
int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16)
{
register int v0 ASM ("rax") = a3;
register int v1 ASM ("rbx") = a4;
register int v2 ASM ("rcx") = a5;
register int v3 ASM ("rdx") = a6;
register int v4 ASM ("rsi") = a7;
register int v5 ASM ("rdi") = a8;
register int v6 ASM ("r8") = a9;
register int v7 ASM ("r9") = a10;
register int v8 ASM ("r10") = a11;
register int v9 ASM ("r11") = a12;
register int v10 ASM ("r12") = a13;
register int v11 ASM ("r13") = a14;
register int v12 ASM ("r14") = a15;
register int v13 ASM ("r15") = a16;
int x;
v0 += a0;
v1 += a1;
v2 += a2;
v0 |= a0;
v1 |= a1;
v2 |= a2;
v0 ^= a0;
v1 ^= a1;
v2 ^= a2;
v0 &= a0;
v1 &= a1;
v2 &= a2;
asm goto ("": "=r" (x) : : : lab);
a1 ^= a0;
a2 = a1;
a0 |= a2;
a0 |= x;
lab:
v0 += x + a0 + a1 + a2;
v1 -= a0 - a1 - a2;
v2 |= a0 | a1 | a2;
v3 |= a0 & a1 & a2;
v4 ^= a0 ^ a1 ^ a2;
return v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10 + v11 + v12 + v13 + a0 + a1 + a2;
}

View File

@@ -1412,6 +1412,10 @@ rewrite_stmt (gimple_stmt_iterator *si)
SET_DEF (def_p, name);
register_new_def (DEF_FROM_PTR (def_p), var);
/* Do not insert debug stmts if the stmt ends the BB. */
if (stmt_ends_bb_p (stmt))
continue;
tracked_var = target_for_debug_bind (var);
if (tracked_var)
{