http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58805
--- Comment #14 from vries at gcc dot gnu.org --- > No it shouldn't. It should return true if the stmt has side-effects that > are _not_ explicit in the statement. This side-effect is explicitely there. Hmm, a rather deceptive name then, if gimple_stmt_has_side_effects does not in fact tell whether a gimple statement has side-effects or not. I wonder if any other use sites are mistaken in the semantics, and what could be a better name. A better name according to your description could be gimple_stmt_has_implicit_side_effects, but I'm not sure I understand how to differentiate between implicit and explicit here. Marking an asm with volatile, is that implicit or explicit, and why? AFAIU, the name gimple_stmt_has_call_or_volatile_side_effects reflects what the implementation does. Anyways, this tentative patch fixes the problem in tail-merge: ... Author: Tom de Vries <t...@codesourcery.com> Date: Mon Oct 21 13:40:28 2013 +0200 * tree-ssa-tail-merge.c (stmt_local_def): Improve side-effect check. diff --git a/gcc/testsuite/gcc.dg/pr58805.c b/gcc/testsuite/gcc.dg/pr58805.c new file mode 100644 index 0000000..6e6eba5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr58805.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-tail-merge -fdump-tree-pre" } */ + +static inline void bar(unsigned long *r) +{ + unsigned long t; + __asm__ ( + "movq $42, %[t]\n\t" + "movq %[t], %[r]\n\t" + : [t] "=&r" (t), [r] "=r" (*r) + ); +} + +void foo(int n, unsigned long *x, unsigned long *y) +{ + if (n == 0) + bar(x); + else + bar(y); +} + +/* { dg-final { scan-tree-dump-times "__asm__" 2 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c index 9094935..0090da6 100644 --- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -300,7 +300,8 @@ stmt_local_def (gimple stmt) tree val; def_operand_p def_p; - if (gimple_has_side_effects (stmt)) + if (gimple_has_side_effects (stmt) + || gimple_vdef (stmt) != NULL_TREE) return false; def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF); ... I'll test this one.