https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63783
--- Comment #10 from Michael Karcher <gcc-bugzilla at mkarcher dot dialup.fu-berlin.de> --- Created attachment 33991 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33991&action=edit Fix logical negation of registers, SImode only In fact, it turns out, you were right. I implemented the solution you suggest (quite hacky, as I only implemented it for SImode, I was too lazy to look up whether there are nice patterns for testing DImode operands into T), and compared assembler outputs. In fact, the duplicate test instruction is NOT eliminated in my first patch, but it is with your code after fixing. So the approach of special-casing compare-to-zero seems to have a positive effect. Assembler output: buggy: tst r4,r4 bf .L2 ; initial if, jumps if "flag" is nonzero ; Branch for zero "flag" mov.l .L10,r1 ; loads address of val mov.l @r1,r1 ; loads value of val ; Common code for zero or non-zero flag .L3: tst r1,r1 ; combined test bt .L8 ; if zero, skip increment mov.l .L11,r2 ; load address of true_count mov.l @r2,r1 ; load, increment, store true_count add #1,r1 mov.l r1,@r2 ; Label for skipping increment of true_count .L8: rts .align 1 ; branch for non-zero "flag" .L2: mov.l .L12,r1 ; load address of decision_result mov.l @r1,r1 ; load data of decision_result tst r1,r1 ; tst/movt logical negation before bra .L3 ; jumping to common code movt r1 With my earlier patch removing the "compare-to-zero" logic completely, the assembler output changes as following (CAPS comments on changes): ... mov.l @r1,r1 ; loads value of val tst r1,r1 ; TEST ONLY FOR FLAG == 0 ; Common code for zero or non-zero flag .L3: bt .L8 ; if zero, skip increment ... tst r1,r1 ; tst/movt logical negation before movt r1 bra .L3 ; jumping to common code tst r1,r1 ; TEST ONLY FOR FLAG != 0