For most machines, GNU CC assumes that the machine has a condition code. A comparison insn sets the condition code, recording the results of both signed and unsigned comparison of the given operands. A separate branch insn tests the condition code and branches or not according its value. The branch insns come in distinct signed and unsigned flavors. Many common machines, such as the Vax, the 68000 and the 32000, work this way.
Some machines have distinct signed and unsigned compare instructions, and
only one set of conditional branch instructions. The easiest way to handle
these machines is to treat them just like the others until the final stage
where assembly code is written. At this time, when outputting code for the
compare instruction, peek ahead at the following branch using
next_cc0_user (insn)
. (The variable insn
refers to the insn
being output, in the output-writing code in an instruction pattern.) If
the RTL says that is an unsigned branch, output an unsigned compare;
otherwise output a signed compare. When the branch itself is output, you
can treat signed and unsigned branches identically.
The reason you can do this is that GNU CC always generates a pair of
consecutive RTL insns, possibly separated by note
insns, one to
set the condition code and one to test it, and keeps the pair inviolate
until the end.
To go with this technique, you must define the machine-description macro
NOTICE_UPDATE_CC
to do CC_STATUS_INIT
; in other words, no
compare instruction is superfluous.
Some machines have compare-and-branch instructions and no condition code. A similar technique works for them. When it is time to ``output'' a compare instruction, record its operands in two static variables. When outputting the branch-on-condition-code instruction that follows, actually output a compare-and-branch instruction that uses the remembered operands.
It also works to define patterns for compare-and-branch instructions. In optimizing compilation, the pair of compare and branch instructions will be combined according to these patterns. But this does not happen if optimization is not requested. So you must use one of the solutions above in addition to any special patterns you define.
In many RISC machines, most instructions do not affect the condition code and there may not even be a separate condition code register. On these machines, the restriction that the definition and use of the condition code be adjacent insns is not necessary and can prevent important optimizations. For example, on the IBM RS/6000, there is a delay for taken branches unless the condition code register is set three instructions earlier than the conditional branch. The instruction scheduler cannot perform this optimization if it is not permitted to separate the definition and use of the condition code register.
On these machines, do not use (cc0)
, but instead use a register
to represent the condition code. If there is a specific condition code
register in the machine, use a hard register. If the condition code or
comparison result can be placed in any general register, or if there are
multiple condition registers, use a pseudo register.
On some machines, the type of branch instruction generated may depend on
the way the condition code was produced; for example, on the 68k and
Sparc, setting the condition code directly from an add or subtract
instruction does not clear the overflow bit the way that a test
instruction does, so a different branch instruction must be used for
some conditional branches. For machines that use (cc0)
, the set
and use of the condition code must be adjacent (separated only by
note
insns) allowing flags in cc_status
to be used.
(See Condition Code.) Also, the comparison and branch insns can be
located from each other by using the functions prev_cc0_setter
and next_cc0_user
.
However, this is not true on machines that do not use (cc0)
. On
those machines, no assumptions can be made about the adjacency of the
compare and branch insns and the above methods cannot be used. Instead,
we use the machine mode of the condition code register to record
different formats of the condition code register.
Registers used to store the condition code value should have a mode that
is in class MODE_CC
. Normally, it will be CCmode
. If
additional modes are required (as for the add example mentioned above in
the Sparc), define the macro EXTRA_CC_MODES
to list the
additional modes required (see Condition Code). Also define
EXTRA_CC_NAMES
to list the names of those modes and
SELECT_CC_MODE
to choose a mode given an operand of a compare.
If it is known during RTL generation that a different mode will be required (for example, if the machine has separate compare instructions for signed and unsigned quantities, like most IBM processors), they can be specified at that time.
If the cases that require different modes would be made by instruction
combination, the macro SELECT_CC_MODE
determines which machine
mode should be used for the comparison result. The patterns should be
written using that mode. To support the case of the add on the Sparc
discussed above, we have the pattern
(define_insn "" [(set (reg:CC_NOOV 0) (compare:CC_NOOV (plus:SI (match_operand:SI 0 "register_operand" "%r") (match_operand:SI 1 "arith_operand" "rI")) (const_int 0)))] "" "...")
The SELECT_CC_MODE
macro on the Sparc returns CC_NOOVmode
for comparisons whose argument is a plus
.