https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118623
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #13 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So, there is the cmov splitter added in r12-1525 and extended in r12-7751. The r12-1525 version of this was: ;; Help combine recognize bt followed by cmov (define_split [(set (match_operand:SWI248 0 "register_operand") (if_then_else:SWI248 (ne (zero_extract:SWI48 (match_operand:SWI48 1 "register_operand") (const_int 1) (zero_extend:SI (match_operand:QI 2 "register_operand"))) (const_int 0)) (match_operand:SWI248 3 "nonimmediate_operand") (match_operand:SWI248 4 "nonimmediate_operand")))] "TARGET_USE_BT && TARGET_CMOVE && !(MEM_P (operands[3]) && MEM_P (operands[4])) && ix86_pre_reload_split ()" [(set (reg:CCC FLAGS_REG) (compare:CCC (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2)) (const_int 0))) (set (match_dup 0) (if_then_else:SWI248 (eq (reg:CCC FLAGS_REG) (const_int 0)) (match_dup 3) (match_dup 4)))] { operands[2] = lowpart_subreg (SImode, operands[2], QImode); }) So, in my reading, op0 = (op1 & (1 << op2)) ? op3 : op4 is what is being matched. And by purely reading the RTL the replacement is the other way around, flags is set to comparison of the zero extraction (i.e. 1 or 0) against 0 and if it is 0, op3 is used, otherwise op4. But %C1 actually prints for (eq (reg:CCC flags) (const_int 0)) c rather than nc and for ne nc rather than c.