Next: Expander Definitions, Previous: Looping Patterns, Up: Machine Desc
14.14 Canonicalization of Instructions
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 associative operators, a sequence of operators will always chain
to the left; for instance, only the left operand of an integer
pluscan itself be aplus.and,ior,xor,plus,mult,smin,smax,umin, andumaxare associative when applied to integers, and sometimes to floating-point. - For these operators, if only one operand is a
neg,not,mult,plus, orminusexpression, it will be the first operand. - In combinations of
neg,mult,plus, andminus, thenegoperations (if any) will be moved inside the operations as far as possible. For instance,(neg (mult A B))is canonicalized as(mult (neg A) B), but(plus (mult (neg A) B) C)is canonicalized as(minus A (mult B C)). - For the
compareoperator, a constant is always the second operand on machines wherecc0is used (see Jump Patterns). On other machines, there are rare cases where the compiler might want to construct acomparewith 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, orminusis made the first operand under the same conditions as above. (minusx(const_intn))is converted to(plusx(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
notexpression, 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,(comparex(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_extractrather than the equivalentandorsign_extractoperations.
Further canonicalization rules are defined in the function
commutative_operand_precedence in gcc/rtlanal.c.