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.