re PR middle-end/21291 (can't find a register in class 'GENERAL_REGS' while reloading 'asm')

PR 21291
        * tree-outof-ssa.c (coalesce_asm_operands): New.
        (coalesce_ssa_name): Use it.  Split out ...
        (coalesce_phi_operands, coalesce_result_decls): ... these.

From-SVN: r102751
This commit is contained in:
Richard Henderson 2005-08-04 16:37:00 -07:00 committed by Richard Henderson
parent 27c370005e
commit 5a910e43f5
3 changed files with 156 additions and 41 deletions

View File

@ -1,3 +1,10 @@
2005-08-04 Richard Henderson <rth@redhat.com>
PR 21291
* tree-outof-ssa.c (coalesce_asm_operands): New.
(coalesce_ssa_name): Use it. Split out ...
(coalesce_phi_operands, coalesce_result_decls): ... these.
2005-08-04 Paul Brook <paul@codesourcery.com>
* read-rtl.c (read_quoted_string): Break if EOF.

View File

@ -0,0 +1,31 @@
/* { dg-do compile } */
/* { dg-options "-O" } */
typedef unsigned long bngdigit;
typedef bngdigit *bng;
typedef unsigned int bngcarry;
typedef unsigned long bngsize;
bngdigit
bng_ia32_mult_sub_digit (bng a, bngsize alen, bng b, bngsize blen, bngdigit d)
{
bngdigit out, tmp;
bngcarry carry;
bngdigit a11;
alen -= blen;
out = 0;
asm (""
: "+r" (a), "+r" (b), "+mr" (blen), "+mr" (out), "=&r" (tmp)
: "mr" (d)
: "eax", "edx");
if (alen == 0)
{
a11 = out;
goto t;
}
a11 = 1;
t:
return a11;
}

View File

@ -676,49 +676,26 @@ coalesce_abnormal_edges (var_map map, conflict_graph graph, root_var_p rv)
}
}
/* Coalesce potential copies via PHI arguments. */
/* Reduce the number of live ranges in MAP. Live range information is
returned if FLAGS indicates that we are combining temporaries, otherwise
NULL is returned. The only partitions which are associated with actual
variables at this point are those which are forced to be coalesced for
various reason. (live on entry, live across abnormal edges, etc.). */
static tree_live_info_p
coalesce_ssa_name (var_map map, int flags)
static void
coalesce_phi_operands (var_map map, coalesce_list_p cl)
{
unsigned num, x, i;
sbitmap live;
tree var, phi;
root_var_p rv;
tree_live_info_p liveinfo;
var_ann_t ann;
conflict_graph graph;
basic_block bb;
coalesce_list_p cl = NULL;
sbitmap_iterator sbi;
tree phi;
if (num_var_partitions (map) <= 1)
return NULL;
liveinfo = calculate_live_on_entry (map);
calculate_live_on_exit (liveinfo);
rv = root_var_init (map);
/* Remove single element variable from the list. */
root_var_compact (rv);
cl = create_coalesce_list (map);
/* Add all potential copies via PHI arguments to the list. */
FOR_EACH_BB (bb)
{
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
tree res = PHI_RESULT (phi);
int p = var_to_partition (map, res);
int x;
if (p == NO_PARTITION)
continue;
for (x = 0; x < (unsigned)PHI_NUM_ARGS (phi); x++)
for (x = 0; x < PHI_NUM_ARGS (phi); x++)
{
tree arg = PHI_ARG_DEF (phi, x);
int p2;
@ -739,14 +716,20 @@ coalesce_ssa_name (var_map map, int flags)
}
}
}
}
/* Coalesce all the result decls together. */
var = NULL_TREE;
i = 0;
for (x = 0; x < num_var_partitions (map); x++)
/* Coalesce all the result decls together. */
static void
coalesce_result_decls (var_map map, coalesce_list_p cl)
{
unsigned int i, x;
tree var = NULL;
for (i = x = 0; x < num_var_partitions (map); x++)
{
tree p = partition_to_var (map, x);
if (TREE_CODE (SSA_NAME_VAR(p)) == RESULT_DECL)
if (TREE_CODE (SSA_NAME_VAR (p)) == RESULT_DECL)
{
if (var == NULL_TREE)
{
@ -760,6 +743,100 @@ coalesce_ssa_name (var_map map, int flags)
false));
}
}
}
/* Coalesce matching constraints in asms. */
static void
coalesce_asm_operands (var_map map, coalesce_list_p cl)
{
basic_block bb;
FOR_EACH_BB (bb)
{
block_stmt_iterator bsi;
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt = bsi_stmt (bsi);
unsigned long noutputs, i;
tree *outputs, link;
if (TREE_CODE (stmt) != ASM_EXPR)
continue;
noutputs = list_length (ASM_OUTPUTS (stmt));
outputs = (tree *) alloca (noutputs * sizeof (tree));
for (i = 0, link = ASM_OUTPUTS (stmt); link;
++i, link = TREE_CHAIN (link))
outputs[i] = TREE_VALUE (link);
for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
{
const char *constraint
= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
tree input = TREE_VALUE (link);
char *end;
unsigned long match;
int p1, p2;
if (TREE_CODE (input) != SSA_NAME && !DECL_P (input))
continue;
match = strtoul (constraint, &end, 10);
if (match >= noutputs || end == constraint)
continue;
if (TREE_CODE (outputs[match]) != SSA_NAME
&& !DECL_P (outputs[match]))
continue;
p1 = var_to_partition (map, outputs[match]);
if (p1 == NO_PARTITION)
continue;
p2 = var_to_partition (map, input);
if (p2 == NO_PARTITION)
continue;
add_coalesce (cl, p1, p2, coalesce_cost (REG_BR_PROB_BASE,
maybe_hot_bb_p (bb),
false));
}
}
}
}
/* Reduce the number of live ranges in MAP. Live range information is
returned if FLAGS indicates that we are combining temporaries, otherwise
NULL is returned. The only partitions which are associated with actual
variables at this point are those which are forced to be coalesced for
various reason. (live on entry, live across abnormal edges, etc.). */
static tree_live_info_p
coalesce_ssa_name (var_map map, int flags)
{
unsigned num, x;
sbitmap live;
root_var_p rv;
tree_live_info_p liveinfo;
conflict_graph graph;
coalesce_list_p cl = NULL;
sbitmap_iterator sbi;
if (num_var_partitions (map) <= 1)
return NULL;
liveinfo = calculate_live_on_entry (map);
calculate_live_on_exit (liveinfo);
rv = root_var_init (map);
/* Remove single element variable from the list. */
root_var_compact (rv);
cl = create_coalesce_list (map);
coalesce_phi_operands (map, cl);
coalesce_result_decls (map, cl);
coalesce_asm_operands (map, cl);
/* Build a conflict graph. */
graph = build_tree_conflict_graph (liveinfo, rv, cl);
@ -787,14 +864,14 @@ coalesce_ssa_name (var_map map, int flags)
/* First, coalesce all live on entry variables to their root variable.
This will ensure the first use is coming from the correct location. */
live = sbitmap_alloc (num_var_partitions (map));
num = num_var_partitions (map);
live = sbitmap_alloc (num);
sbitmap_zero (live);
/* Set 'live' vector to indicate live on entry partitions. */
num = num_var_partitions (map);
for (x = 0 ; x < num; x++)
{
var = partition_to_var (map, x);
tree var = partition_to_var (map, x);
if (default_def (SSA_NAME_VAR (var)) == var)
SET_BIT (live, x);
}
@ -809,8 +886,8 @@ coalesce_ssa_name (var_map map, int flags)
partition. */
EXECUTE_IF_SET_IN_SBITMAP (live, 0, x, sbi)
{
var = root_var (rv, root_var_find (rv, x));
ann = var_ann (var);
tree var = root_var (rv, root_var_find (rv, x));
var_ann_t ann = var_ann (var);
/* If these aren't already coalesced... */
if (partition_to_var (map, x) != var)
{