Uros Bizjak <ubiz...@gmail.com> writes:
> Hello!
>>> gcc/testsuite/
>>> Changelog for gcc/testsuite/Changelog
>>> 2018-08-14  Vlad Lazar  <vlad.la...@arm.com>
>>>
>>>     * gcc.target/aarch64/imm_choice_comparison.c: New.
>>>
>>> gcc/
>>> Changelog for gcc/Changelog
>>> 2018-08-14  Vlad Lazar  <vlad.la...@arm.com>
>>>     * expmed.h (canonicalize_comparison): New declaration.
>>>     * expmed.c (canonicalize_comparison, equivalent_cmp_code): New.
>>>     * expmed.c (emit_store_flag_1): Add call to canonicalize_comparison.
>>>     * optabs.c (prepare_cmp_insn): Likewise.
>>>     * rtl.h (unsigned_condition_p): New function which checks if a
>>> comparison operator is unsigned.
>> Thanks.  I fixed up the ChangeLog entry and installed this on the trunk.
>>
>> Richard S -- thanks for working with Vlad to push this forward.
>
> This patch caused
>
> +FAIL: gcc.target/i386/20040112-1.c scan-assembler testb
>
> on x86 targets, reported in PR86994 [1].
>
> The compiler now expands with:
>
> (insn 12 8 13 4 (set (reg:CCGC 17 flags)
>         (compare:CCGC (reg/v:QI 87 [ status ])
>             (const_int -1 [0xffffffffffffffff]))) "20040112-1.c":13 9 
> {*cmpqi_1}
>      (nil))
>
> instead of:
>
> (insn 10 8 11 4 (set (reg:CCGOC 17 flags)
>         (compare:CCGOC (reg/v:QI 87 [ status ])
>             (const_int 0 [0]))) "20040112-1.c":13 5 {*cmpqi_ccno_1}
>      (nil))
>
> The canonicalization, introduced in r263591 does not universally
> benefit all targets.

The patch does ask the target which immediate is cheaper though.
Even for AArch64 it's only a conditional canoicalisation: sometimes
the original value is cheaper, sometimes the new one is.

The problem in this case is that insn_cost says:

  (set (reg:QI X) (const_int 0))

has a cost of 4 but:

  (set (reg:QI X) (const_int -1))

has a cost of 2.  So the costs make -1 seem like the cheaper immediate.

This in turn seems to be a bad interaction between ix86_rtx_costs and:

  cost = set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)), speed);
  return cost > 0 ? cost : COSTS_N_INSNS (1);

in pattern_cost.  ix86_rtx_costs returns 0 for 0 and 2 for -1, where 2
is a sub-insn cost.  But pattern_cost converts the 0 cost into the cost
of a full instruction, making 0 seem more expensive than -1.

I wonder whether we should change the return to:

  return MAX (cost, 1);

or even:

  return cost + 1;

Who knows what will break if we do that though...

This of course is why Segher added the insn_cost hook.

> I wonder why TARGET_CANONICALIZE_COMPARISON target hook was not used
> instead.

The idea is that this is a target-independent technique that needs
target-specific costs, a bit like open-coding multiplication using
shifts and adds.  The code to do the transformation itself should be
target-independent and only the cost decision should be target-specific.

Thanks,
Richard

Reply via email to