There are often cases where multiple RTL expressions could represent an operation performed by a single machine instruction. This situation is most commonly encountered with logical, branch, and multiply-accumulate instructions. In such cases, the compiler attempts to convert these multiple RTL expressions into a single canonical form to reduce the number of insn patterns required.
In addition to algebraic simplifications, following canonicalizations are performed:
neg, not,
mult, plus, or minus expression, it will be the
first operand.
compare operator, a constant is always the second operand
on machines where cc0 is used (see section Defining Jump Instruction Patterns). On other
machines, there are rare cases where the compiler might want to construct
a compare with a constant as the first operand. However, these
cases are not common enough for it to be worthwhile to provide a pattern
matching a constant as the first operand unless the machine actually has
such an instruction.
An operand of neg, not, mult, plus, or
minus is made the first operand under the same conditions as
above.
(minus x (const_int n)) is converted to
(plus x (const_int -n)).
mem), a left shift is
converted into the appropriate multiplication by a power of two.
De`Morgan's Law is used to move bitwise negation inside a bitwise
logical-and or logical-or operation. If this results in only one
operand being a not expression, it will be the first one.
A machine that has an instruction that performs a bitwise logical-and of one
operand with the bitwise negation of the other should specify the pattern
for that instruction as
(define_insn ""
[(set (match_operand:m 0 ...)
(and:m (not:m (match_operand:m 1 ...))
(match_operand:m 2 ...)))]
"..."
"...")
Similarly, a pattern for a "NAND" instruction should be written
(define_insn ""
[(set (match_operand:m 0 ...)
(ior:m (not:m (match_operand:m 1 ...))
(not:m (match_operand:m 2 ...))))]
"..."
"...")
In both cases, it is not necessary to include patterns for the many
logically equivalent RTL expressions.
(xor:m x y)
and (not:m (xor:m x y)).
(plus:m (plus:m x y) constant)
cc0,
(compare x (const_int 0)) will be converted to
x.
zero_extract rather than the equivalent
and or sign_extract operations.