Commit d8d72314 by Paolo Bonzini Committed by Paolo Bonzini

function.c (match_asm_constraints_1, [...]): New.

2007-07-05  Paolo Bonzini  <bonzini@gnu.org>

	* function.c (match_asm_constraints_1, rest_of_match_asm_constraints,
	pass_match_asm_constraints): New.
	* passes.c (init_optimization_passes): Add new pass.
	* stmt.c (expand_asm_operands): Set cfun->has_asm_statement.
	* function.h (struct function): Add has_asm_statement bit.
	(current_function_has_asm_statement): New.
	* tree-pass.h (pass_match_asm_constraints): New.

From-SVN: r126385
parent 2ab16fe0
2007-07-05 Paolo Bonzini <bonzini@gnu.org>
* function.c (match_asm_constraints_1, rest_of_match_asm_constraints,
pass_match_asm_constraints): New.
* passes.c (init_optimization_passes): Add new pass.
* stmt.c (expand_asm_operands): Set cfun->has_asm_statement.
* function.h (struct function): Add has_asm_statement bit.
(current_function_has_asm_statement): New.
* tree-pass.h (pass_match_asm_constraints): New.
2007-07-05 Richard Sandiford <rsandifo@nildram.co.uk>
* config/mips/mips.c (mips_file_start): Avoid declaration
......
......@@ -5504,6 +5504,143 @@ struct tree_opt_pass pass_thread_prologue_and_epilogue =
TODO_ggc_collect, /* todo_flags_finish */
'w' /* letter */
};
/* This mini-pass fixes fall-out from SSA in asm statements that have
in-out constraints. Say you start with
orig = inout;
asm ("": "+mr" (inout));
use (orig);
which is transformed very early to use explicit output and match operands:
orig = inout;
asm ("": "=mr" (inout) : "0" (inout));
use (orig);
Or, after SSA and copyprop,
asm ("": "=mr" (inout_2) : "0" (inout_1));
use (inout_1);
Clearly inout_2 and inout_1 can't be coalesced easily anymore, as
they represent two separate values, so they will get different pseudo
registers during expansion. Then, since the two operands need to match
per the constraints, but use different pseudo registers, reload can
only register a reload for these operands. But reloads can only be
satisfied by hardregs, not by memory, so we need a register for this
reload, just because we are presented with non-matching operands.
So, even though we allow memory for this operand, no memory can be
used for it, just because the two operands don't match. This can
cause reload failures on register-starved targets.
So it's a symptom of reload not being able to use memory for reloads
or, alternatively it's also a symptom of both operands not coming into
reload as matching (in which case the pseudo could go to memory just
fine, as the alternative allows it, and no reload would be necessary).
We fix the latter problem here, by transforming
asm ("": "=mr" (inout_2) : "0" (inout_1));
back to
inout_2 = inout_1;
asm ("": "=mr" (inout_2) : "0" (inout_2)); */
static void
match_asm_constraints_1 (rtx insn, rtx *p_sets, int noutputs)
{
int i;
bool changed = false;
rtx op = SET_SRC (p_sets[0]);
int ninputs = ASM_OPERANDS_INPUT_LENGTH (op);
rtvec inputs = ASM_OPERANDS_INPUT_VEC (op);
for (i = 0; i < ninputs; i++)
{
rtx input, output, insns;
const char *constraint = ASM_OPERANDS_INPUT_CONSTRAINT (op, i);
char *end;
int match;
match = strtoul (constraint, &end, 10);
if (end == constraint)
continue;
gcc_assert (match < noutputs);
output = SET_DEST (p_sets[match]);
input = RTVEC_ELT (inputs, i);
if (rtx_equal_p (output, input)
|| (GET_MODE (input) != VOIDmode
&& GET_MODE (input) != GET_MODE (output)))
continue;
start_sequence ();
emit_move_insn (copy_rtx (output), input);
RTVEC_ELT (inputs, i) = copy_rtx (output);
insns = get_insns ();
end_sequence ();
emit_insn_before (insns, insn);
changed = true;
}
if (changed)
df_insn_rescan (insn);
}
static unsigned
rest_of_match_asm_constraints (void)
{
basic_block bb;
rtx insn, pat, *p_sets;
int noutputs;
if (!cfun->has_asm_statement)
return 0;
df_set_flags (DF_DEFER_INSN_RESCAN);
FOR_EACH_BB (bb)
{
FOR_BB_INSNS (bb, insn)
{
if (!INSN_P (insn))
continue;
pat = PATTERN (insn);
if (GET_CODE (pat) == PARALLEL)
p_sets = &XVECEXP (pat, 0, 0), noutputs = XVECLEN (pat, 0);
else if (GET_CODE (pat) == SET)
p_sets = &PATTERN (insn), noutputs = 1;
else
continue;
if (GET_CODE (*p_sets) == SET
&& GET_CODE (SET_SRC (*p_sets)) == ASM_OPERANDS)
match_asm_constraints_1 (insn, p_sets, noutputs);
}
}
return TODO_df_finish;
}
struct tree_opt_pass pass_match_asm_constraints =
{
"asmcons", /* name */
NULL, /* gate */
rest_of_match_asm_constraints, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
0, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func, /* todo_flags_finish */
0 /* letter */
};
#include "gt-function.h"
......@@ -414,6 +414,9 @@ struct function GTY(())
/* Nonzero if function being compiled has nonlocal gotos to parent
function. */
unsigned int has_nonlocal_goto : 1;
/* Nonzero if function being compiled has an asm statement. */
unsigned int has_asm_statement : 1;
/* Nonzero if the current function is a thunk, i.e., a lightweight
function implemented by the output_mi_thunk hook) that just
......@@ -517,6 +520,7 @@ extern int trampolines_created;
#define current_function_has_nonlocal_label (cfun->has_nonlocal_label)
#define current_function_calls_unwind_init (cfun->calls_unwind_init)
#define current_function_has_nonlocal_goto (cfun->has_nonlocal_goto)
#define current_function_has_asm_statement (cfun->has_asm_statement)
#define return_label (cfun->x_return_label)
#define naked_return_label (cfun->x_naked_return_label)
......
......@@ -740,6 +740,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_stack_ptr_mod);
NEXT_PASS (pass_mode_switching);
NEXT_PASS (pass_see);
NEXT_PASS (pass_match_asm_constraints);
NEXT_PASS (pass_sms);
NEXT_PASS (pass_sched);
NEXT_PASS (pass_subregs_of_mode_init);
......
......@@ -1078,6 +1078,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
if (real_output_rtx[i])
emit_move_insn (real_output_rtx[i], output_rtx[i]);
cfun->has_asm_statement = 1;
free_temp_slots ();
}
......
......@@ -3,7 +3,7 @@
6 registers that must not conflict. Add to that the PIC register,
the frame pointer, and the stack pointer, and we've run out of
registers on 32-bit targets. */
/* { dg-do compile { target { { ! ilp32 } || nonpic } } } */
/* { dg-do compile } */
/* { dg-options "-O" } */
typedef unsigned long bngdigit;
......
......@@ -390,6 +390,7 @@ extern struct tree_opt_pass pass_initialize_regs;
extern struct tree_opt_pass pass_combine;
extern struct tree_opt_pass pass_if_after_combine;
extern struct tree_opt_pass pass_partition_blocks;
extern struct tree_opt_pass pass_match_asm_constraints;
extern struct tree_opt_pass pass_regmove;
extern struct tree_opt_pass pass_split_all_insns;
extern struct tree_opt_pass pass_lower_subreg2;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment