From: J"orn Rennecke Date: Thu, 9 Feb 2006 19:17:09 +0000 (+0000) Subject: re PR inline-asm/16194 (global register with inline-asm and clobered) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=91b4415af4fafcd53f44b671003e917dd7ec0cfd;p=platform%2Fupstream%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 31ab02d..763e081 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2006-02-09 J"orn Rennecke + + 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 * reload1.c (emit_input_reload_insns): Delete code that tries to diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index 01b9b15..dc0c163 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -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; } diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index d60fc13..5a04430 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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 diff --git a/gcc/stmt.c b/gcc/stmt.c index da2f750..3bb4f42 100644 --- a/gcc/stmt.c +++ b/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; - - 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; + 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 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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8be7f5d..59778df 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-02-09 J"orn Rennecke + + PR inline-asm/16194 + * gcc.dg/pr16194.c: New test. + 2006-02-09 Rainer Orth * ada/acats/run_acats: Use portable variant of "$@". diff --git a/gcc/testsuite/gcc.dg/pr16194.c b/gcc/testsuite/gcc.dg/pr16194.c new file mode 100644 index 0000000..44f34a4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr16194.c @@ -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); +} diff --git a/gcc/tree.h b/gcc/tree.h index b4e390d..7d17daf 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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. */