gccint: Insn Canonicalizations
1
1 17.14 Canonicalization of Instructions
1 ======================================
1
1 There are often cases where multiple RTL expressions could represent an
1 operation performed by a single machine instruction. This situation is
1 most commonly encountered with logical, branch, and multiply-accumulate
1 instructions. In such cases, the compiler attempts to convert these
1 multiple RTL expressions into a single canonical form to reduce the
1 number of insn patterns required.
1
1 In addition to algebraic simplifications, following canonicalizations
1 are performed:
1
1 * For commutative and comparison operators, a constant is always made
1 the second operand. If a machine only supports a constant as the
1 second operand, only patterns that match a constant in the second
1 operand need be supplied.
1
1 * For associative operators, a sequence of operators will always
1 chain to the left; for instance, only the left operand of an
1 integer 'plus' can itself be a 'plus'. 'and', 'ior', 'xor',
1 'plus', 'mult', 'smin', 'smax', 'umin', and 'umax' are associative
1 when applied to integers, and sometimes to floating-point.
1
1 * For these operators, if only one operand is a 'neg', 'not', 'mult',
1 'plus', or 'minus' expression, it will be the first operand.
1
1 * In combinations of 'neg', 'mult', 'plus', and 'minus', the 'neg'
1 operations (if any) will be moved inside the operations as far as
1 possible. For instance, '(neg (mult A B))' is canonicalized as
1 '(mult (neg A) B)', but '(plus (mult (neg B) C) A)' is
1 canonicalized as '(minus A (mult B C))'.
1
1 * For the 'compare' operator, a constant is always the second operand
1 if the first argument is a condition code register or '(cc0)'.
1
1 * For instructions that inherently set a condition code register, the
1 'compare' operator is always written as the first RTL expression of
1 the 'parallel' instruction pattern. For example,
1
1 (define_insn ""
1 [(set (reg:CCZ FLAGS_REG)
1 (compare:CCZ
1 (plus:SI
1 (match_operand:SI 1 "register_operand" "%r")
1 (match_operand:SI 2 "register_operand" "r"))
1 (const_int 0)))
1 (set (match_operand:SI 0 "register_operand" "=r")
1 (plus:SI (match_dup 1) (match_dup 2)))]
1 ""
1 "addl %0, %1, %2")
1
1 * An operand of 'neg', 'not', 'mult', 'plus', or 'minus' is made the
1 first operand under the same conditions as above.
1
1 * '(ltu (plus A B) B)' is converted to '(ltu (plus A B) A)'.
1 Likewise with 'geu' instead of 'ltu'.
1
1 * '(minus X (const_int N))' is converted to '(plus X (const_int
1 -N))'.
1
1 * Within address computations (i.e., inside 'mem'), a left shift is
1 converted into the appropriate multiplication by a power of two.
1
1 * De Morgan's Law is used to move bitwise negation inside a bitwise
1 logical-and or logical-or operation. If this results in only one
1 operand being a 'not' expression, it will be the first one.
1
1 A machine that has an instruction that performs a bitwise
1 logical-and of one operand with the bitwise negation of the other
1 should specify the pattern for that instruction as
1
1 (define_insn ""
1 [(set (match_operand:M 0 ...)
1 (and:M (not:M (match_operand:M 1 ...))
1 (match_operand:M 2 ...)))]
1 "..."
1 "...")
1
1 Similarly, a pattern for a "NAND" instruction should be written
1
1 (define_insn ""
1 [(set (match_operand:M 0 ...)
1 (ior:M (not:M (match_operand:M 1 ...))
1 (not:M (match_operand:M 2 ...))))]
1 "..."
1 "...")
1
1 In both cases, it is not necessary to include patterns for the many
1 logically equivalent RTL expressions.
1
1 * The only possible RTL expressions involving both bitwise
1 exclusive-or and bitwise negation are '(xor:M X Y)' and '(not:M
1 (xor:M X Y))'.
1
1 * The sum of three items, one of which is a constant, will only
1 appear in the form
1
1 (plus:M (plus:M X Y) CONSTANT)
1
1 * Equality comparisons of a group of bits (usually a single bit) with
1 zero will be written using 'zero_extract' rather than the
1 equivalent 'and' or 'sign_extract' operations.
1
1 * '(sign_extend:M1 (mult:M2 (sign_extend:M2 X) (sign_extend:M2 Y)))'
1 is converted to '(mult:M1 (sign_extend:M1 X) (sign_extend:M1 Y))',
1 and likewise for 'zero_extend'.
1
1 * '(sign_extend:M1 (mult:M2 (ashiftrt:M2 X S) (sign_extend:M2 Y)))'
1 is converted to '(mult:M1 (sign_extend:M1 (ashiftrt:M2 X S))
1 (sign_extend:M1 Y))', and likewise for patterns using 'zero_extend'
1 and 'lshiftrt'. If the second operand of 'mult' is also a shift,
1 then that is extended also. This transformation is only applied
1 when it can be proven that the original operation had sufficient
1 precision to prevent overflow.
1
1 Further canonicalization rules are defined in the function
1 'commutative_operand_precedence' in 'gcc/rtlanal.c'.
1