Define Subst Example (GNU Compiler Collection (GCC) Internals)

#### 18.22.1 `define_subst` Example ¶

To illustrate how `define_subst` works, let us examine a simple template transformation.

Suppose there are two kinds of instructions: one that touches flags and the other that does not. The instructions of the second type could be generated with the following `define_subst`:

    (define_subst "add_clobber_subst"
      [(set (match_operand:SI 0 "" "")
            (match_operand:SI 1 "" ""))]
      ""
      [(set (match_dup 0)
            (match_dup 1))
       (clobber (reg:CC FLAGS_REG))])

This `define_subst` can be applied to any RTL pattern containing `set` of mode SI and generates a copy with clobber when it is applied.

Assume there is an RTL template for a `max` instruction to be used in `define_subst` mentioned above:

    (define_insn "maxsi"
      [(set (match_operand:SI 0 "register_operand" "=r")
            (max:SI
              (match_operand:SI 1 "register_operand" "r")
              (match_operand:SI 2 "register_operand" "r")))]
      ""
      "max\t{%2, %1, %0|%0, %1, %2}"
     [...])

To mark the RTL template for `define_subst` application, subst-attributes are used. They should be declared in advance:

    (define_subst_attr "add_clobber_name" "add_clobber_subst" "_noclobber" "_clobber")

Here ‘`add_clobber_name`’ is the attribute name, ‘`add_clobber_subst`’ is the name of the corresponding `define_subst`, the third argument (‘`_noclobber`’) is the attribute value that would be substituted into the unchanged version of the source RTL template, and the last argument (‘`_clobber`’) is the value that would be substituted into the second, transformed, version of the RTL template.

Once the subst-attribute has been defined, it should be used in RTL templates which need to be processed by the `define_subst`. So, the original RTL template should be changed:

    (define_insn "maxsi<add_clobber_name>"
      [(set (match_operand:SI 0 "register_operand" "=r")
            (max:SI
              (match_operand:SI 1 "register_operand" "r")
              (match_operand:SI 2 "register_operand" "r")))]
      ""
      "max\t{%2, %1, %0|%0, %1, %2}"
     [...])

The result of the `define_subst` usage would look like the following:

    (define_insn "maxsi_noclobber"
      [(set (match_operand:SI 0 "register_operand" "=r")
            (max:SI
              (match_operand:SI 1 "register_operand" "r")
              (match_operand:SI 2 "register_operand" "r")))]
      ""
      "max\t{%2, %1, %0|%0, %1, %2}"
     [...])
    (define_insn "maxsi_clobber"
      [(set (match_operand:SI 0 "register_operand" "=r")
            (max:SI
              (match_operand:SI 1 "register_operand" "r")
              (match_operand:SI 2 "register_operand" "r")))
       (clobber (reg:CC FLAGS_REG))]
      ""
      "max\t{%2, %1, %0|%0, %1, %2}"
     [...])