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

Reply via email to