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:
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.
For these operators, if only one operand is a neg
, not
, mult
, plus
, or minus
expression, it will be the first operand.
For the compare
operator, a constant is always the second operand on machines where cc0
is used (see Jump 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))
.
Within address computations (i.e., inside 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.
The only possible RTL expressions involving both bitwise exclusive-or and bitwise negation are (xor:m x y)
and (not:m (xor:m x y))
.
The sum of three items, one of which is a constant, will only appear in the form
(plus:m (plus:m x y) constant)
On machines that do not use cc0
, (compare x (const_int 0))
will be converted to x.
Equality comparisons of a group of bits (usually a single bit) with zero will be written using zero_extract
rather than the equivalent and
or sign_extract
operations.