This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Call for testers: fix PR 16194
- From: Joern RENNECKE <joern dot rennecke at st dot com>
- To: Hans-Peter Nilsson <hans-peter dot nilsson at axis dot com>
- Cc: gcc-patches at gcc dot gnu dot org, janis187 at us dot ibm dot com, Richard Henderson <rth at redhat dot com>
- Date: Wed, 08 Feb 2006 18:57:52 +0000
- Subject: Re: Call for testers: fix PR 16194
- References: <200602081756.k18Hu58n023558@ignucius.se.axis.com>
Here is my updated version. Currently testing on i686-pc-linux-gnu
native, X sh-elf, X sh64-elf, X arm-elf and X cris-elf .
However, I am still testing with revision 110439 as base version,
because of the bootstrap failure on i686 with more recent sources.
2006-01-31 J"orn Rennecke <joern.rennecke@st.com>
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.
Index: doc/tm.texi
===================================================================
/usr/bin/diff -p -d -F^( -u -L doc/tm.texi (revision 110439) -L doc/tm.texi (working copy) doc/.svn/text-base/tm.texi.svn-base doc/tm.texi
--- doc/tm.texi (revision 110439)
+++ doc/tm.texi (working copy)
@@ -9337,7 +9337,7 @@ It should return the result of the last
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
Index: tree.h
===================================================================
/usr/bin/diff -p -d -F^( -u -L tree.h (revision 110439) -L tree.h (working copy) .svn/text-base/tree.h.svn-base tree.h
--- tree.h (revision 110439)
+++ tree.h (working copy)
@@ -4384,7 +4384,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. */
Index: testsuite/gcc.dg/pr16194.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L testsuite/gcc.dg/pr16194.c (revision 0) -L testsuite/gcc.dg/pr16194.c (revision 0) testsuite/gcc.dg/.svn/empty-file testsuite/gcc.dg/pr16194.c
--- testsuite/gcc.dg/pr16194.c (revision 0)
+++ testsuite/gcc.dg/pr16194.c (revision 0)
@@ -0,0 +1,67 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-bogus "internal compiler error" "ICE" { target *-*-* } 0 } */
+
+#define ASMDECL __asm (REG);
+#if defined (__alpha__)
+# define REG "$1"
+# define CLOBBER_LIST : REG
+# define INP_CLOBBER_LIST : CLOBBER_LIST
+#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);
+}
Index: config/cris/cris.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/cris/cris.c (revision 110439) -L config/cris/cris.c (working copy) config/cris/.svn/text-base/cris.c.svn-base config/cris/cris.c
--- config/cris/cris.c (revision 110439)
+++ config/cris/cris.c (working copy)
@@ -3462,7 +3462,7 @@ cris_md_asm_clobbers (tree outputs, tree
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
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;
}
Index: stmt.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L stmt.c (revision 110439) -L stmt.c (working copy) .svn/text-base/stmt.c.svn-base stmt.c
--- stmt.c (revision 110439)
+++ stmt.c (working copy)
@@ -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 **con
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 o
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 o
= 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;
}