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? Segher