https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119071
--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
cse1 optimizes insn optimizes insn 15 away in:
(insn 10 9 11 2 (parallel [
(set (reg:SI 84 [ _3 ])
(plus:SI (reg:SI 96)
(reg:SI 92 [ _18 ])))
(clobber (reg:CC 17 flags))
]) 185 {*addsi_1}
(nil))
(insn 11 10 12 2 (set (reg:CCZ 17 flags)
(compare:CCZ (reg:SI 84 [ _3 ])
(const_int 1 [0x1]))) 11 {*cmpsi_1}
(nil))
(insn 12 11 13 2 (set (reg:QI 98)
(ne:QI (reg:CCZ 17 flags)
(const_int 0 [0]))) 732 {*setcc_qi}
(nil))
(insn 13 12 14 2 (set (reg:SI 97)
(zero_extend:SI (reg:QI 98))) 119 {*zero_extendqisi2}
(nil))
(insn 14 13 15 2 (set (reg:SI 89 [ _15 ])
(reg:SI 97)) 67 {*movsi_internal}
(nil))
(insn 15 14 16 2 (set (reg:CCZ 17 flags)
(compare:CCZ (reg:SI 84 [ _3 ])
(const_int 1 [0x1]))) 11 {*cmpsi_1}
(nil))
(insn 16 15 17 2 (set (reg:QI 100)
(eq:QI (reg:CCZ 17 flags)
(const_int 0 [0]))) 732 {*setcc_qi}
(nil))
which looks reasonable, nothing clobbers flags in between and insn 11 sets it
to the same value.
I think things go wrong during combine.
Before that revision we have
(insn 5 2 6 2 (set (reg:CCZ 17 flags)
(compare:CCZ (mem/c:SI (symbol_ref:DI ("a") [flags 0x2] <var_decl
0x7fc3d8edfb40 a>) [1 a+0 S4 A32])
(const_int -2 [0xfffffffffffffffe]))) 11 {*cmpsi_1}
(nil))
...
(insn 18 17 19 2 (set (reg:SI 97)
(eq:SI (reg:CCZ 17 flags)
(const_int 0 [0]))) 731 {*setcc_si_1_movzbl}
(expr_list:REG_DEAD (reg:CC 17 flags)
(nil)))
(insn 19 18 20 2 (set (reg:SI 102)
(ne:SI (reg:CCZ 17 flags)
(const_int 0 [0]))) 731 {*setcc_si_1_movzbl}
(expr_list:REG_DEAD (reg:CC 17 flags)
(nil)))
(insn 20 19 21 2 (parallel [
(set (reg:SI 93 [ <retval> ])
(minus:SI (reg:SI 102)
(reg:SI 97)))
(clobber (reg:CC 17 flags))
]) 254 {*subsi_1}
(expr_list:REG_DEAD (reg:SI 102)
(expr_list:REG_DEAD (reg:SI 97)
(expr_list:REG_UNUSED (reg:CC 17 flags)
(nil)))))
(insn 21 20 25 2 (set (mem/c:SI (symbol_ref:DI ("b") [flags 0x2] <var_decl
0x7fc3d8edfbd0 b>) [1 b+0 S4 A32])
(reg:SI 93 [ <retval> ])) 67 {*movsi_internal}
(nil))
which feels reasonable. The testcase has UB when a == -2 (left shift by -1)
and otherwise sets b to 1.
But starting with r10-7268 combiner combines this into
(insn 5 2 6 2 (set (reg:CCZ 17 flags)
(compare:CCZ (mem/c:SI (symbol_ref:DI ("a") [flags 0x2] <var_decl
0x7f2bc69b4b40 a>) [1 a+0 S4 A32])
(const_int -2 [0xfffffffffffffffe]))) 11 {*cmpsi_1}
(expr_list:REG_UNUSED (reg:CC 17 flags)
(nil)))
...
(insn 20 19 21 2 (set (reg:SI 93 [ <retval> ])
(const_int 0 [0])) 67 {*movsi_internal}
(nil))
(insn 21 20 25 2 (set (mem/c:SI (symbol_ref:DI ("b") [flags 0x2] <var_decl
0x7f2bc69b4bd0 b>) [1 b+0 S4 A32])
(reg:SI 93 [ <retval> ])) 67 {*movsi_internal}
(nil))
which is wrong for the non-UB case of a not being -2.