Code iterators operate in a similar way to mode iterators. See Mode Iterators.
The construct:
(define_code_iterator name [(code1 "cond1") … (coden "condn")])
defines a pseudo rtx code name that can be instantiated as codei if condition condi is true. Each codei must have the same rtx format. See RTL Classes and Formats.
As with mode iterators, each pattern that uses name will be expanded n times, once with all uses of name replaced by code1, once with all uses replaced by code2, and so on. See Defining Mode Iterators.
It is possible to define attributes for codes as well as for modes.
There are two standard code attributes: code
, the name of the
code in lower case, and CODE
, the name of the code in upper case.
Other attributes are defined using:
(define_code_attr name [(code1 "value1") … (coden "valuen")])
Instruction patterns can use code attributes as rtx codes, which can be
useful if two sets of codes act in tandem. For example, the following
define_insn
defines two patterns, one calculating a signed absolute
difference and another calculating an unsigned absolute difference:
(define_code_iterator any_max [smax umax]) (define_code_attr paired_min [(smax "smin") (umax "umin")]) (define_insn … [(set (match_operand:SI 0 …) (minus:SI (any_max:SI (match_operand:SI 1 …) (match_operand:SI 2 …)) (<paired_min>:SI (match_dup 1) (match_dup 2))))] …)
The signed version of the instruction uses smax
and smin
while the unsigned version uses umax
and umin
. There
are no versions that pair smax
with umin
or umax
with smin
.
It is also possible to use other types of attributes as codes,
in a similar way. For example, an int iterator could be used to
iterate over unspec
numbers, with an int attribute specifying
an associated rtx code. See Int Iterators.
Here’s an example of code iterators in action, taken from the MIPS port:
(define_code_iterator any_cond [unordered ordered unlt unge uneq ltgt unle ungt eq ne gt ge lt le gtu geu ltu leu]) (define_expand "b<code>" [(set (pc) (if_then_else (any_cond:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "")) (pc)))] "" { gen_conditional_branch (operands, <CODE>); DONE; })
This is equivalent to:
(define_expand "bunordered" [(set (pc) (if_then_else (unordered:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "")) (pc)))] "" { gen_conditional_branch (operands, UNORDERED); DONE; }) (define_expand "bordered" [(set (pc) (if_then_else (ordered:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "")) (pc)))] "" { gen_conditional_branch (operands, ORDERED); DONE; }) …