#### 17.8.6 Disable insn alternatives using the `enabled` attribute

There are three insn attributes that may be used to selectively disable instruction alternatives:

`enabled`

  Says whether an alternative is available on the current subtarget.

`preferred_for_size`

  Says whether an enabled alternative should be used in code that is optimized for size.

`preferred_for_speed`

  Says whether an enabled alternative should be used in code that is optimized for speed.

All these attributes should use `(const_int 1)` to allow an alternative or `(const_int 0)` to disallow it. The attributes must be a static property of the subtarget; they cannot for example depend on the current operands, on the current optimization level, on the location of the insn within the body of a loop, on whether register allocation has finished, or on the current compiler pass.

The `enabled` attribute is a correctness property. It tells GCC to act as though the disabled alternatives were never defined in the first place. This is useful when adding new instructions to an existing pattern in cases where the new instructions are only available for certain cpu architecture levels (typically mapped to the `-march=` command-line option).

In contrast, the `preferred_for_size` and `preferred_for_speed` attributes are strong optimization hints rather than correctness properties. `preferred_for_size` tells GCC which alternatives to consider when adding or modifying an instruction that GCC wants to optimize for size. `preferred_for_speed` does the same thing for speed. Note that things like code motion can lead to cases where code optimized for size uses alternatives that are not preferred for size, and similarly for speed.

Although `define_insn`s can in principle specify the `enabled` attribute directly, it is often clearer to have subsiduary attributes for each architectural feature of interest. The `define_insn`s can then use these subsiduary attributes to say which alternatives require which features. The example below does this for `cpu_facility`.

E.g. the following two patterns could easily be merged using the `enabled` attribute:

    (define_insn "*movdi_old"
      [(set (match_operand:DI 0 "register_operand" "=d")
            (match_operand:DI 1 "register_operand" " d"))]
      "!TARGET_NEW"
      "lgr %0,%1")

    (define_insn "*movdi_new"
      [(set (match_operand:DI 0 "register_operand" "=d,f,d")
            (match_operand:DI 1 "register_operand" " d,d,f"))]
      "TARGET_NEW"
      "@
       lgr  %0,%1
       ldgr %0,%1
       lgdr %0,%1")

to:

    (define_insn "*movdi_combined"
      [(set (match_operand:DI 0 "register_operand" "=d,f,d")
            (match_operand:DI 1 "register_operand" " d,d,f"))]
      ""
      "@
       lgr  %0,%1
       ldgr %0,%1
       lgdr %0,%1"
      [(set_attr "cpu_facility" "*,new,new")])

with the `enabled` attribute defined like this:

    (define_attr "cpu_facility" "standard,new" (const_string "standard"))

    (define_attr "enabled" ""
      (cond [(eq_attr "cpu_facility" "standard") (const_int 1)
             (and (eq_attr "cpu_facility" "new")
                  (ne (symbol_ref "TARGET_NEW") (const_int 0)))
             (const_int 1)]
            (const_int 0)))