https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106590
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Cleaned up testcase: /* { dg-additional-options "-mtune=skylake" { target { i?86-*-* x86_64-*-* } } } */ typedef struct A { short a; } A; typedef A *B; typedef struct C { int c, d; } C; typedef C *D; B foo (void) { static A r = { .a = 1 }; return &r; } D bar (void) { static C r = { .c = 1, .d = 23 }; return &r; } static inline int __attribute__((always_inline)) baz (short a) { int e = 1, f; short g; D h; switch (a) { case 1: f = 23; g = 1; break; case 2: f = 20; g = 2; break; } h = bar (); if (h->d != f || h->c != g) __builtin_abort (); return e; } int qux (void) { B i = foo (); int e = 1; switch (i->a) { case 1: case 2: e = baz (i->a); break; case 3: e = 0; break; } return e; } int main () { qux (); return 0; } I think this is a latent bug in noce_convert_multiple_sets_1. For cond (eq (reg/v:HI 82 [ g ]) (const_int 1 [0x1])) and cc_cmp (eq (reg:CCZ 17 flags) (const_int 0 [0])) when we try_emit_cmove_seq for (insn 3 35 4 7 (set (reg/v:HI 82 [ g ]) (const_int 2 [0x2])) "pr106590.c":37:9 84 {*movhi_internal} (nil)) insn, we get seq1 (insn 65 0 66 (set (reg:CCZ 17 flags) (compare:CCZ (reg/v:HI 82 [ g ]) (const_int 1 [0x1]))) -1 (nil)) (insn 66 65 67 (set (reg:QI 96) (ne:QI (reg:CCZ 17 flags) (const_int 0 [0]))) -1 (nil)) (insn 67 66 68 (set (reg:HI 95) (zero_extend:HI (reg:QI 96))) -1 (nil)) (insn 68 67 0 (parallel [ (set (reg:HI 95) (plus:HI (reg:HI 95) (const_int 1 [0x1]))) (clobber (reg:CC 17 flags)) ]) -1 (nil)) and seq2 (insn 69 0 70 (set (reg:HI 97) (const_int 2 [0x2])) -1 (nil)) (insn 70 69 0 (set (reg:HI 95) (if_then_else:HI (eq (reg:CCZ 17 flags) (const_int 0 [0])) (reg/v:HI 82 [ g ]) (reg:HI 97))) -1 (nil)) and later for (insn 4 3 36 7 (set (reg/v:SI 84 [ f ]) (const_int 20 [0x14])) "pr106590.c":36:9 83 {*movsi_internal} (nil)) we get seq1 (insn 72 0 71 (set (reg:SI 98) (const_int 20 [0x14])) -1 (nil)) (insn 71 72 73 (set (reg:CCZ 17 flags) (compare:CCZ (reg/v:HI 82 [ g ]) (const_int 1 [0x1]))) -1 (nil)) (insn 73 71 0 (set (reg/v:SI 84 [ f ]) (if_then_else:SI (eq (reg:CCZ 17 flags) (const_int 0 [0])) (reg/v:SI 84 [ f ]) (reg:SI 98))) -1 (nil)) and seq2 (insn 74 0 75 (set (reg:SI 99) (const_int 20 [0x14])) -1 (nil)) (insn 75 74 0 (set (reg/v:SI 84 [ f ]) (if_then_else:SI (eq (reg:CCZ 17 flags) (const_int 0 [0])) (reg/v:SI 84 [ f ]) (reg:SI 99))) -1 (nil)) In the former case, cost1 == cost2, in the latter case cost1 > cost2. So, we for the first insn choose seq1 and for the second seq2. That is wrong, because the first seq1 clobbers the (reg 17 flags) register which is used in cc_cmp/rev_cc_cmp. So, if we pick that seq1, we may not use any seq2 afterwards for the latter instructions, need to always select seq1 since then.