re PR inline-asm/16194 (global register with inline-asm and clobered)
PR inline-asm/16194 gcc: * tree.h (decl_overlaps_hard_reg_set_p) Don't declare. (tree_overlaps_hard_reg_set): Declare. * stmt.c (decl_overlaps_hard_reg_set_p): Now static. Change return type and signature to match function type expected by walk_tree. (tree_overlaps_hard_reg_set): New function. (decl_conflicts_with_clobbers_p): Rename to: (tree_conflicts_with_clobbers_p). Take HARD_REG_SET * argument. Use tree_overlaps_hard_reg_set. Changed caller. * doc/tm.texi (TARGET_MD_ASM_CLOBBERS): Replace decl_overlaps_hard_reg_set_p with tree_overlaps_hard_reg_set. * cris.c (cris_md_asm_clobbers): Likewise. gcc/testsuite: * gcc.dg/pr16194.c: New test. From-SVN: r110810
This commit is contained in:
parent
0e692cc0bf
commit
91b4415af4
|
@ -1,3 +1,18 @@
|
|||
2006-02-09 J"orn Rennecke <joern.rennecke@st.com>
|
||||
|
||||
PR inline-asm/16194
|
||||
* tree.h (decl_overlaps_hard_reg_set_p) Don't declare.
|
||||
(tree_overlaps_hard_reg_set): Declare.
|
||||
* stmt.c (decl_overlaps_hard_reg_set_p): Now static. Change return
|
||||
type and signature to match function type expected by walk_tree.
|
||||
(tree_overlaps_hard_reg_set): New function.
|
||||
(decl_conflicts_with_clobbers_p): Rename to:
|
||||
(tree_conflicts_with_clobbers_p). Take HARD_REG_SET * argument.
|
||||
Use tree_overlaps_hard_reg_set. Changed caller.
|
||||
* doc/tm.texi (TARGET_MD_ASM_CLOBBERS): Replace
|
||||
decl_overlaps_hard_reg_set_p with tree_overlaps_hard_reg_set.
|
||||
* cris.c (cris_md_asm_clobbers): Likewise.
|
||||
|
||||
2006-02-09 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
|
||||
* reload1.c (emit_input_reload_insns): Delete code that tries to
|
||||
|
|
|
@ -3462,7 +3462,7 @@ cris_md_asm_clobbers (tree outputs, tree inputs, tree in_clobbers)
|
|||
impossible constraints. */
|
||||
if (strchr (TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))),
|
||||
'h') != NULL
|
||||
|| decl_overlaps_hard_reg_set_p (val, mof_set))
|
||||
|| tree_overlaps_hard_reg_set (val, &mof_set) != NULL_TREE)
|
||||
return clobbers;
|
||||
}
|
||||
|
||||
|
@ -3472,7 +3472,7 @@ cris_md_asm_clobbers (tree outputs, tree inputs, tree in_clobbers)
|
|||
|
||||
if (strchr (TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))),
|
||||
'h') != NULL
|
||||
|| decl_overlaps_hard_reg_set_p (val, mof_set))
|
||||
|| tree_overlaps_hard_reg_set (val, &mof_set) != NULL_TREE)
|
||||
return clobbers;
|
||||
}
|
||||
|
||||
|
|
|
@ -9337,7 +9337,7 @@ It should return the result of the last @code{tree_cons} used to add a
|
|||
clobber. The @var{outputs}, @var{inputs} and @var{clobber} lists are the
|
||||
corresponding parameters to the asm and may be inspected to avoid
|
||||
clobbering a register that is an input or output of the asm. You can use
|
||||
@code{decl_overlaps_hard_reg_set_p}, declared in @file{tree.h}, to test
|
||||
@code{tree_overlaps_hard_reg_set}, declared in @file{tree.h}, to test
|
||||
for overlap with regards to asm-declared registers.
|
||||
@end deftypefn
|
||||
|
||||
|
|
71
gcc/stmt.c
71
gcc/stmt.c
|
@ -105,7 +105,7 @@ static int cost_table_initialized;
|
|||
#define COST_TABLE(I) cost_table_[(unsigned HOST_WIDE_INT) ((I) + 1)]
|
||||
|
||||
static int n_occurrences (int, const char *);
|
||||
static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET);
|
||||
static bool tree_conflicts_with_clobbers_p (tree, HARD_REG_SET *);
|
||||
static void expand_nl_goto_receiver (void);
|
||||
static bool check_operand_nalternatives (tree, tree);
|
||||
static bool check_unique_operand_names (tree, tree);
|
||||
|
@ -558,49 +558,66 @@ parse_input_constraint (const char **constraint_p, int input_num,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Return true iff there's an overlap between REGS and DECL, where DECL
|
||||
can be an asm-declared register. */
|
||||
/* Return DECL iff there's an overlap between *REGS and DECL, where DECL
|
||||
can be an asm-declared register. Called via walk_tree. */
|
||||
|
||||
bool
|
||||
decl_overlaps_hard_reg_set_p (tree decl, const HARD_REG_SET regs)
|
||||
static tree
|
||||
decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees ATTRIBUTE_UNUSED,
|
||||
void *data)
|
||||
{
|
||||
if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
|
||||
&& DECL_REGISTER (decl)
|
||||
&& REG_P (DECL_RTL (decl))
|
||||
&& REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
|
||||
tree decl = *declp;
|
||||
const HARD_REG_SET *regs = data;
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
|
||||
{
|
||||
rtx reg = DECL_RTL (decl);
|
||||
unsigned int regno;
|
||||
if (DECL_REGISTER (decl)
|
||||
&& REG_P (DECL_RTL (decl))
|
||||
&& REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
rtx reg = DECL_RTL (decl);
|
||||
unsigned int regno;
|
||||
|
||||
for (regno = REGNO (reg);
|
||||
regno < (REGNO (reg)
|
||||
+ hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
|
||||
regno++)
|
||||
if (TEST_HARD_REG_BIT (regs, regno))
|
||||
return true;
|
||||
for (regno = REGNO (reg);
|
||||
regno < (REGNO (reg)
|
||||
+ hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
|
||||
regno++)
|
||||
if (TEST_HARD_REG_BIT (*regs, regno))
|
||||
return decl;
|
||||
}
|
||||
walk_subtrees = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
else if (TYPE_P (decl))
|
||||
walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* If there is an overlap between *REGS and DECL, return the first overlap
|
||||
found. */
|
||||
tree
|
||||
tree_overlaps_hard_reg_set (tree decl, HARD_REG_SET *regs)
|
||||
{
|
||||
return walk_tree (&decl, decl_overlaps_hard_reg_set_p, regs, NULL);
|
||||
}
|
||||
|
||||
/* Check for overlap between registers marked in CLOBBERED_REGS and
|
||||
anything inappropriate in DECL. Emit error and return TRUE for error,
|
||||
FALSE for ok. */
|
||||
anything inappropriate in T. Emit error and return the register
|
||||
variable definition for error, NULL_TREE for ok. */
|
||||
|
||||
static bool
|
||||
decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs)
|
||||
tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
|
||||
{
|
||||
/* Conflicts between asm-declared register variables and the clobber
|
||||
list are not allowed. */
|
||||
if (decl_overlaps_hard_reg_set_p (decl, clobbered_regs))
|
||||
tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs);
|
||||
|
||||
if (overlap)
|
||||
{
|
||||
error ("asm-specifier for variable %qs conflicts with asm clobber list",
|
||||
IDENTIFIER_POINTER (DECL_NAME (decl)));
|
||||
IDENTIFIER_POINTER (DECL_NAME (overlap)));
|
||||
|
||||
/* Reset registerness to stop multiple errors emitted for a single
|
||||
variable. */
|
||||
DECL_REGISTER (decl) = 0;
|
||||
DECL_REGISTER (overlap) = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -827,7 +844,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
|
|||
inout_opnum[ninout++] = i;
|
||||
}
|
||||
|
||||
if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
|
||||
if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
|
||||
clobber_conflict_found = 1;
|
||||
}
|
||||
|
||||
|
@ -923,7 +940,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
|
|||
= gen_rtx_ASM_INPUT (TYPE_MODE (type),
|
||||
ggc_strdup (constraints[i + noutputs]));
|
||||
|
||||
if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
|
||||
if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
|
||||
clobber_conflict_found = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2006-02-09 J"orn Rennecke <joern.rennecke@st.com>
|
||||
|
||||
PR inline-asm/16194
|
||||
* gcc.dg/pr16194.c: New test.
|
||||
|
||||
2006-02-09 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
|
||||
|
||||
* ada/acats/run_acats: Use portable variant of "$@".
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O" } */
|
||||
/* { dg-bogus "internal compiler error" "ICE" { target *-*-* } 0 } */
|
||||
|
||||
#define ASMDECL __asm (REG);
|
||||
#define CLOBBER_LIST : REG
|
||||
#define INP_CLOBBER_LIST : CLOBBER_LIST
|
||||
#if defined (__alpha__)
|
||||
# define REG "$1"
|
||||
#elif defined (__CRIS__) || defined (__sh__)
|
||||
# define REG "r10"
|
||||
#elif defined (__i386__)
|
||||
# define REG "%eax"
|
||||
#elif defined (__MMIX__)
|
||||
# define REG "$8"
|
||||
#elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) \
|
||||
|| defined (__POWERPC__) || defined (PPC) || defined (_IBMR2)
|
||||
# define REG "6"
|
||||
#elif defined (__x86_64__)
|
||||
# define REG "rax"
|
||||
#else
|
||||
/* Make this test harmless for any target not recognized above. */
|
||||
# undef ASMDECL
|
||||
# define ASMDECL
|
||||
# define REG "conflict"
|
||||
# undef CLOBBER_LIST
|
||||
# define CLOBBER_LIST
|
||||
# undef INP_CLOBBER_LIST
|
||||
# define INP_CLOBBER_LIST
|
||||
#endif
|
||||
|
||||
struct A
|
||||
{
|
||||
int a;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
struct A b[3];
|
||||
};
|
||||
|
||||
struct C
|
||||
{
|
||||
struct B c;
|
||||
};
|
||||
|
||||
void bug (void)
|
||||
{
|
||||
register char* dst ASMDECL;
|
||||
__asm__ ("":"=g"(*dst): : REG); /* { dg-error "conflict" } */
|
||||
}
|
||||
|
||||
/* The tree optimizers currently prevent us from finding an overlap -
|
||||
we end up using a copy of dst rather than dst.
|
||||
But at least make sure we don't get an ICE. */
|
||||
void bug2 (void)
|
||||
{
|
||||
register char* dst ASMDECL;
|
||||
__asm__ ("": :"g"(*dst) CLOBBER_LIST);
|
||||
}
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
register struct C *dst ASMDECL;
|
||||
__asm__ ("" : "=g"(dst->c.b[1].a) INP_CLOBBER_LIST);
|
||||
}
|
|
@ -4382,7 +4382,7 @@ extern void expand_decl (tree);
|
|||
extern void expand_anon_union_decl (tree, tree, tree);
|
||||
#ifdef HARD_CONST
|
||||
/* Silly ifdef to avoid having all includers depend on hard-reg-set.h. */
|
||||
extern bool decl_overlaps_hard_reg_set_p (tree, const HARD_REG_SET);
|
||||
extern tree tree_overlaps_hard_reg_set (tree, HARD_REG_SET *);
|
||||
#endif
|
||||
|
||||
/* In gimplify.c. */
|
||||
|
|
Loading…
Reference in New Issue