Hi Richard,
On Tue, Aug 06, 2019 at 04:35:04PM +0100, Richard Earnshaw (lists) wrote:
Arm has an instruction that performs the following operation:
(parallel [
(set (reg:CC 100 cc)
(compare:CC (const_int 0 [0])
(reg:SI 121)))
(set (reg:SI 113)
(neg:SI (reg:SI 121)))
])
This is simply a reverse subtract from the constant zero, and setting
the condition flags. It's the low part of a negdi2 expansion.
However, combine will rip this up and try to transform the compare into
'canonical' form, ie
(parallel [
(set (reg:CC 100 cc)
(compare:CC (reg:SI 121)
(const_int 0 [0])))
(set (reg:SI 113)
(neg:SI (reg:SI 121)))
])
(and obviously swapping the condition on the instruction that uses the
comparison result).
This, of course, doesn't match the behaviour of the instruction and
no-longer matches the pattern in the md file.
It is, however, canonical RTL:
(from md.texi:)
In addition to algebraic simplifications, following canonicalizations
are performed:
@itemize @bullet
@item
For commutative and comparison operators, a constant is always made the
second operand. If a machine only supports a constant as the second
operand, only patterns that match a constant in the second operand need
be supplied.
Putting the constant first is non-canonical RTL and will in general not
match any instructions generated by GCC.
So is there a way to describe this instruction within the compiler, or a
way to stop simplify_set from making this sort of simplification?
What's wrong with describing the canonical form in your MD? You'll need
some reversed condition code thingy, but that's it?