https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113576
--- Comment #44 from Hongtao Liu <liuhongt at gcc dot gnu.org> ---
>
> Note the AND is removed by combine if I add it:
>
> Successfully matched this instruction:
> (set (reg:CCZ 17 flags)
> (compare:CCZ (and:HI (not:HI (subreg:HI (reg:QI 102 [ tem_3 ]) 0))
> (const_int 15 [0xf]))
> (const_int 0 [0])))
>
> (*testhi_not)
>
> - 9: {r103:QI=r102:QI&0xf;clobber flags:CC;}
> + REG_DEAD r99:QI
> + 9: NOTE_INSN_DELETED
> + 12: flags:CCZ=cmp(~r102:QI#0&0xf,0)
> REG_DEAD r102:QI
> - REG_UNUSED flags:CC
> - 12: flags:CCZ=cmp(r103:QI,0xf)
> - REG_DEAD r103:QI
>
> and we get
>
> foo:
> .LFB0:
> .cfi_startproc
> notl %esi
> orl %esi, %edi
> notl %edi
> testb $15, %dil
> je .L6
> ret
>
> which I'm not sure is OK?
>
Yes, I think it's on purpose
11508;; Split and;cmp (as optimized by combine) into not;test
11509;; Except when TARGET_BMI provides andn (*andn_<mode>_ccno).
11510(define_insn_and_split "*test<mode>_not"
11511 [(set (reg:CCZ FLAGS_REG)
11512 (compare:CCZ
11513 (and:SWI
11514 (not:SWI (match_operand:SWI 0 "register_operand"))
11515 (match_operand:SWI 1 "<nonmemory_szext_operand>"))
11516 (const_int 0)))]
11517 "ix86_pre_reload_split ()
11518 && (!TARGET_BMI || !REG_P (operands[1]))"
11519 "#"
11520 "&& 1"
11521 [(set (match_dup 2) (not:SWI (match_dup 0)))
11522 (set (reg:CCZ FLAGS_REG)
11523 (compare:CCZ (and:SWI (match_dup 2) (match_dup 1))
11524 (const_int 0)))]
11525 "operands[2] = gen_reg_rtx (<MODE>mode);")
11526
11527;; Split and;cmp (as optimized by combine) into andn;cmp $0
11528(define_insn_and_split "*test<mode>_not_doubleword"