https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61225
--- Comment #32 from rguenther at suse dot de <rguenther at suse dot de> --- On Mon, 13 Feb 2017, ubizjak at gmail dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61225 > > Uroš Bizjak <ubizjak at gmail dot com> changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > CC| |rguenth at gcc dot gnu.org > > --- Comment #31 from Uroš Bizjak <ubizjak at gmail dot com> --- > What I find interesting here is, that following testcase: > > --cut here-- > void foo (void *); > > #define F(T, OP, OPN) \ > T * \ > f##T##OPN (T *x, T y) \ > { \ > *x OP y; \ > if (!*x) \ > foo (x); \ > return x; \ > } > > #define G(T) \ > F (T, |=, or) \ > F (T, ^=, xor) > > G (int) > --cut here-- > > in fact also fails on x86_64 (-Os, -O2): > > fintxor: > .LFB1: > movl (%rdi), %eax > pushq %rbx > .LCFI2: > movq %rdi, %rbx > movl %eax, %edx > xorl %esi, %edx > cmpl %esi, %eax > movl %edx, (%rdi) > jne .L6 > call foo > .L6: > movq %rbx, %rax > popq %rbx > .LCFI3: > ret > > The failure is not detected, since the test scans only for TEST insn, not also > for CMP. > > The difference between these two functions is already in the .optimized tree > dump between fintor (good): > > fintor (int * x, int y) > { > int _1; > int _2; > > <bb 2> [100.00%]: > _1 = *x_5(D); > _2 = _1 | y_6(D); > *x_5(D) = _2; > if (_2 == 0) > goto <bb 3>; [36.64%] > else > goto <bb 4>; [63.36%] > > <bb 3> [36.64%]: > foo (x_5(D)); > > <bb 4> [100.00%]: > return x_5(D); > > } > > and fintxor (bad): > > fintxor (int * x, int y) > { > int _1; > int _2; > > <bb 2> [100.00%]: > _1 = *x_5(D); > _2 = _1 ^ y_6(D); > *x_5(D) = _2; > if (_1 == y_6(D)) That's from /* Equality compare simplifications from fold_binary */ (for cmp (eq ne) ... /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y. */ (simplify (cmp (bit_xor @0 @1) integer_zerop) (cmp @0 @1)) not considering other uses.