Hi all,

Some ISAs have instructions to perform a bitwise AND operation with an 
immediate and compare
the result with zero. For example, the aarch64 TST instruction.
This is represented naturally in the MD file as:

(define_insn "*and<mode>3nr_compare0"
  [(set (reg:CC_NZ CC_REGNUM)
    (compare:CC_NZ
     (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
          (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
     (const_int 0)))]
  ""
  "tst\\t%<w>0, %<w>1"
  [(set_attr "type" "logics_reg,logics_imm")]
)

However, when the immediate operand of the AND is all ones, combine transforms 
that
into a zero_extract.
For example, the testcase is on aarch64:
void g ();

void
f1 (int x)
{
  if (x & 15)
    g ();
}

We're trying to combine the insns:
(insn 6 3 7 2 (set (reg:SI 75)
        (and:SI (reg/v:SI 74 [ x ])
            (const_int 15 [0xf]))) cbz.c:7 460 {andsi3}
     (expr_list:REG_DEAD (reg/v:SI 74 [ x ])
        (nil)))
(insn 7 6 8 2 (set (reg:CC 66 cc)
        (compare:CC (reg:SI 75)
            (const_int 0 [0]))) cbz.c:7 385 {*cmpsi}
     (expr_list:REG_DEAD (reg:SI 75)
        (nil)))

followed by a conditional branch:
(jump_insn 8 7 9 2 (set (pc)
        (if_then_else (eq (reg:CC 66 cc)
                (const_int 0 [0]))
            (label_ref:DI 14)
            (pc))) cbz.c:7 7 {condjump}

combine attempts to match the pattern:
(set (reg:CC 66 cc)
    (compare:CC (zero_extract:DI (reg:DI 0 x0 [ x ])
            (const_int 4 [0x4])
            (const_int 0 [0]))
        (const_int 0 [0])))


and fails. This fails, first because our pattern matches the and-immediate 
form, not the zero_extract form.
The change_zero_ext step at the end of combine can't fix the damage because 
earlier in simplify_set when we
called SELECT_CC_MODE on the COMPARE and its use in the conditional branch the 
aarch64 implementation of SELECT_CC_MODE
doesn't handle the ZERO_EXTRACT form to return the CC_NZ form that the pattern 
needs, so the change_zero_ext code can
transform the zero_extract back into the AND-immediate but it doesn't have the 
context to fix the CC mode.

Is there a good way to fix this? It would seem rather weird to have extra MD 
patterns to match the zero_extract forms
explicitly. Maybe teaching the aarch64 implementation of SELECT_CC_MODE to 
handle ZERO_EXTRACTS the same as AND-immediates?
Or is there something that can be done in combine itself?

Thanks,
Kyrill



Reply via email to