17.24.2 Code Iterators

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;
})

…