[arm] Improve handling of DImode comparisions against constants.
In almost all cases it is better to handle inequality handling against constants
by transforming comparisons of the form (reg <GE/LT/GEU/LTU> const) into
(reg <GT/LE/GTU/LEU> (const+1)). However, there are many cases that we could
handle but currently failed to do so because we forced the constant into a
register too early in the pattern expansion. To permit this to be done we need
to defer forcing the constant into a register until after we've had the chance
to do the transform - in some cases that may even mean that we no-longer need
to force the constant into a register at all. For example, on Arm, the case:
_Bool f8 (unsigned long long a) { return a > 0xffffffff; }
previously compiled to
mov r3, #0
cmp r1, r3
mvn r2, #0
cmpeq r0, r2
movhi r0, #1
movls r0, #0
bx lr
But now compiles to
cmp r1, #1
cmpeq r0, #0
movcs r0, #1
movcc r0, #0
bx lr
Which although not yet completely optimal, is certainly better than
previously.
* config/arm/arm.md (cbranchdi4): Accept reg_or_int_operand for
operand 2.
(cstoredi4): Similarly, but for operand 3.
* config/arm/arm.c (arm_canoncialize_comparison): Allow canonicalization
of unsigned compares with a constant on Arm. Prefer using const+1 and
adjusting the comparison over swapping the operands whenever the
original constant was not valid.
(arm_gen_dicompare_reg): If Y is not a valid operand, force it to a
register here.
(arm_validize_comparison): Do not force invalid DImode operands to
registers here.
From-SVN: r277178