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:
plus
can itself be a plus
. and
, ior
, xor
,
plus
, mult
, smin
, smax
, umin
, and
umax
are associative when applied to integers, and sometimes to
floating-point.
neg
, not
,
mult
, plus
, or minus
expression, it will be the
first operand.
neg
, mult
, plus
, and
minus
, the neg
operations (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))
.
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.
(ltu (plus
a b)
b)
is converted to
(ltu (plus
a b)
a)
. Likewise with geu
instead
of ltu
.
(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.
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.
Further canonicalization rules are defined in the function
commutative_operand_precedence
in gcc/rtlanal.c.