Merge expand_asm_operands into expand_asm_stmt

Prepatory to converting from tree chains to vectors.

From-SVN: r223023
This commit is contained in:
Richard Henderson 2015-05-11 16:33:12 -07:00 committed by Richard Henderson
parent 5570ddd5a8
commit 6476a8fde0
2 changed files with 75 additions and 95 deletions

View File

@ -1,5 +1,8 @@
2015-05-11 Richard Henderson <rth@redhat.com>
* cfgexpand.c (expand_asm_operands): Merge into...
(expand_asm_stmt): ... here.
* cfgexpand.c (expand_asm_operands): Don't call
resolve_asm_operand_names.
* stmt.c (resolve_asm_operand_names): Clarify block comment.

View File

@ -2522,22 +2522,78 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
VOL nonzero means the insn is volatile; don't optimize it. */
static void
expand_asm_operands (tree string, tree outputs, tree inputs,
tree clobbers, tree labels, basic_block fallthru_bb,
int vol, location_t locus)
expand_asm_stmt (gasm *stmt)
{
int noutputs, ninputs, nclobbers, nlabels, i;
tree string, outputs, inputs, clobbers, labels, tail, t;
location_t locus = gimple_location (stmt);
basic_block fallthru_bb = NULL;
/* Meh... convert the gimple asm operands into real tree lists.
Eventually we should make all routines work on the vectors instead
of relying on TREE_CHAIN. */
outputs = NULL_TREE;
noutputs = gimple_asm_noutputs (stmt);
if (noutputs > 0)
{
t = outputs = gimple_asm_output_op (stmt, 0);
for (i = 1; i < noutputs; i++)
t = TREE_CHAIN (t) = gimple_asm_output_op (stmt, i);
}
inputs = NULL_TREE;
ninputs = gimple_asm_ninputs (stmt);
if (ninputs > 0)
{
t = inputs = gimple_asm_input_op (stmt, 0);
for (i = 1; i < ninputs; i++)
t = TREE_CHAIN (t) = gimple_asm_input_op (stmt, i);
}
clobbers = NULL_TREE;
nclobbers = gimple_asm_nclobbers (stmt);
if (nclobbers > 0)
{
t = clobbers = gimple_asm_clobber_op (stmt, 0);
for (i = 1; i < nclobbers; i++)
t = TREE_CHAIN (t) = gimple_asm_clobber_op (stmt, i);
}
labels = NULL_TREE;
nlabels = gimple_asm_nlabels (stmt);
if (nlabels > 0)
{
edge fallthru = find_fallthru_edge (gimple_bb (stmt)->succs);
if (fallthru)
fallthru_bb = fallthru->dest;
t = labels = gimple_asm_label_op (stmt, 0);
for (i = 1; i < nlabels; i++)
t = TREE_CHAIN (t) = gimple_asm_label_op (stmt, i);
}
{
const char *s = gimple_asm_string (stmt);
string = build_string (strlen (s), s);
}
if (gimple_asm_input_p (stmt))
{
expand_asm_loc (string, gimple_asm_volatile_p (stmt), locus);
return;
}
/* Record the contents of OUTPUTS before it is modified. */
tree *orig_outputs = XALLOCAVEC (tree, noutputs);
for (i = 0; i < noutputs; ++i)
orig_outputs[i] = TREE_VALUE (gimple_asm_output_op (stmt, i));
bool vol = gimple_asm_volatile_p (stmt);
rtvec argvec, constraintvec, labelvec;
rtx body;
int ninputs = list_length (inputs);
int noutputs = list_length (outputs);
int nlabels = list_length (labels);
int ninout;
int nclobbers;
HARD_REG_SET clobbered_regs;
int clobber_conflict_found = 0;
tree tail;
tree t;
int i;
/* Vector of RTX's of evaluated output operands. */
rtx *output_rtx = XALLOCAVEC (rtx, noutputs);
int *inout_opnum = XALLOCAVEC (int, noutputs);
@ -2994,101 +3050,22 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
if (real_output_rtx[i])
emit_move_insn (real_output_rtx[i], output_rtx[i]);
crtl->has_asm_statement = 1;
free_temp_slots ();
}
static void
expand_asm_stmt (gasm *stmt)
{
int noutputs;
tree outputs, tail, t;
tree *o;
size_t i, n;
const char *s;
tree str, out, in, cl, labels;
location_t locus = gimple_location (stmt);
basic_block fallthru_bb = NULL;
/* Meh... convert the gimple asm operands into real tree lists.
Eventually we should make all routines work on the vectors instead
of relying on TREE_CHAIN. */
out = NULL_TREE;
n = gimple_asm_noutputs (stmt);
if (n > 0)
{
t = out = gimple_asm_output_op (stmt, 0);
for (i = 1; i < n; i++)
t = TREE_CHAIN (t) = gimple_asm_output_op (stmt, i);
}
in = NULL_TREE;
n = gimple_asm_ninputs (stmt);
if (n > 0)
{
t = in = gimple_asm_input_op (stmt, 0);
for (i = 1; i < n; i++)
t = TREE_CHAIN (t) = gimple_asm_input_op (stmt, i);
}
cl = NULL_TREE;
n = gimple_asm_nclobbers (stmt);
if (n > 0)
{
t = cl = gimple_asm_clobber_op (stmt, 0);
for (i = 1; i < n; i++)
t = TREE_CHAIN (t) = gimple_asm_clobber_op (stmt, i);
}
labels = NULL_TREE;
n = gimple_asm_nlabels (stmt);
if (n > 0)
{
edge fallthru = find_fallthru_edge (gimple_bb (stmt)->succs);
if (fallthru)
fallthru_bb = fallthru->dest;
t = labels = gimple_asm_label_op (stmt, 0);
for (i = 1; i < n; i++)
t = TREE_CHAIN (t) = gimple_asm_label_op (stmt, i);
}
s = gimple_asm_string (stmt);
str = build_string (strlen (s), s);
if (gimple_asm_input_p (stmt))
{
expand_asm_loc (str, gimple_asm_volatile_p (stmt), locus);
return;
}
outputs = out;
noutputs = gimple_asm_noutputs (stmt);
/* o[I] is the place that output number I should be written. */
o = (tree *) alloca (noutputs * sizeof (tree));
/* Record the contents of OUTPUTS before it is modified. */
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
o[i] = TREE_VALUE (tail);
/* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
OUTPUTS some trees for where the values were actually stored. */
expand_asm_operands (str, outputs, in, cl, labels, fallthru_bb,
gimple_asm_volatile_p (stmt), locus);
/* Copy all the intermediate outputs into the specified outputs. */
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
{
if (o[i] != TREE_VALUE (tail))
if (orig_outputs[i] != TREE_VALUE (tail))
{
expand_assignment (o[i], TREE_VALUE (tail), false);
expand_assignment (orig_outputs[i], TREE_VALUE (tail), false);
free_temp_slots ();
/* Restore the original value so that it's correct the next
time we expand this function. */
TREE_VALUE (tail) = o[i];
TREE_VALUE (tail) = orig_outputs[i];
}
}
crtl->has_asm_statement = 1;
free_temp_slots ();
}
/* Emit code to jump to the address