[arm] Handle some constant comparisons using rsbs+rscs
authorRichard Earnshaw <rearnsha@arm.com>
Fri, 18 Oct 2019 19:03:50 +0000 (19:03 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Fri, 18 Oct 2019 19:03:50 +0000 (19:03 +0000)
commitaf74bfeee1faccef25dc0086d4249eb0f127c820
treee038f765785dd4e3aa0e7cbc4f11f1e69e7488eb
parent8b8ab8f473b42933b9c1e292c4b1ab02adf1863a
[arm] Handle some constant comparisons using rsbs+rscs

In a small number of cases it is preferable to handle comparisons with
constants using the sequence

RSBS tmp, Xlo, constlo
RSCS tmp, Xhi, consthi

which allows us to handle a small number of LE/GT/LEU/GEU cases when
changing the code to use LT/GE/LTU/GEU would make the constant more
expensive.  Sadly, we cannot do this on Thumb, since we need RSC, so we
now always use the incremented constant in that case since normally that
still works out cheaper than forcing the entire constant into a register.

Further investigation has also shown that the canonicalization of a
reverse subtract and compare is valid for signed as well as unsigned value,
so we relax the restriction on selecting CC_RSBmode to allow all types
of compare.

* config/arm/arm.c (arm_const_double_prefer_rsbs_rsc): New function.
(arm_canonicalize_comparison): For GT/LE/GTU/GEU, use the constant
unchanged only if that will be cheaper.
(arm_select_cc_mode): Recognize a swapped comparison that will
be regenerated using RSBS or RSCS.  Relax restriction on selecting
CC_RSBmode.
(arm_gen_dicompare_reg): Handle LE/GT/LEU/GEU comparisons against
a constant.
(arm_gen_compare_reg): Handle compare (CONST, X) when the mode
is CC_RSBmode.
(maybe_get_arm_condition_code): CC_RSBmode now returns the same codes
as CCmode.
* config/arm/arm.md (rsb_imm_compare_scratch): New pattern.
(rscsi3_<CC_EXTEND>out_scratch): New pattern.

From-SVN: r277180
gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.md