Defining Predicates (GNU Compiler Collection (GCC) Internals)

#### 18.8.2 Defining Machine-Specific Predicates ¶

Many machines have requirements for their operands that cannot be expressed precisely using the generic predicates. You can define additional predicates using `define_predicate` and `define_special_predicate` expressions. These expressions have three operands:

- The name of the predicate, as it will be referred to in `match_operand` or `match_operator` expressions.
- An RTL expression which evaluates to true if the predicate allows the operand op, false if it does not. This expression can only use the following RTL codes:
  `MATCH_OPERAND`

    When written inside a predicate expression, a `MATCH_OPERAND` expression evaluates to true if the predicate it names would allow op. The operand number and constraint are ignored. Due to limitations in `genrecog`, you can only refer to generic predicates and predicates that have already been defined.

  `MATCH_CODE`

    This expression evaluates to true if op or a specified subexpression of op has one of a given list of RTX codes.

    The first operand of this expression is a string constant containing a comma-separated list of RTX code names (in lower case). These are the codes for which the `MATCH_CODE` will be true.

    The second operand is a string constant which indicates what subexpression of op to examine. If it is absent or the empty string, op itself is examined. Otherwise, the string constant must be a sequence of digits and/or lowercase letters. Each character indicates a subexpression to extract from the current expression; for the first character this is op, for the second and subsequent characters it is the result of the previous character. A digit n extracts ‘`XEXP (e, n)`’; a letter l extracts ‘`XVECEXP (e, 0, n)`’ where n is the alphabetic ordinal of l (0 for ‘a’, 1 for ’b’, and so on). The `MATCH_CODE` then examines the RTX code of the subexpression extracted by the complete string. It is not possible to extract components of an `rtvec` that is not at position 0 within its RTX object.

  `MATCH_TEST`

    This expression has one operand, a string constant containing a C expression. The predicate’s arguments, op and mode, are available with those names in the C expression. The `MATCH_TEST` evaluates to true if the C expression evaluates to a nonzero value. `MATCH_TEST` expressions must not have side effects.

  `AND`
  `IOR`
  `NOT`
  `IF_THEN_ELSE`

    The basic ‘`MATCH_`’ expressions can be combined using these logical operators, which have the semantics of the C operators ‘`&&`’, ‘`||`’, ‘`!`’, and ‘`? :`’ respectively. As in Common Lisp, you may give an `AND` or `IOR` expression an arbitrary number of arguments; this has exactly the same effect as writing a chain of two-argument `AND` or `IOR` expressions.

- An optional block of C code, which should execute ‘`return true`’ if the predicate is found to match and ‘`return false`’ if it does not. It must not have any side effects. The predicate arguments, op and mode, are available with those names.

  If a code block is present in a predicate definition, then the RTL expression must evaluate to true and the code block must execute ‘`return true`’ for the predicate to allow the operand. The RTL expression is evaluated first; do not re-check anything in the code block that was checked in the RTL expression.

The program `genrecog` scans `define_predicate` and `define_special_predicate` expressions to determine which RTX codes are possibly allowed. You should always make this explicit in the RTL predicate expression, using `MATCH_OPERAND` and `MATCH_CODE`.

Here is an example of a simple predicate definition, from the IA64 machine description:

    ;; True if op is a SYMBOL_REF which refers to the sdata section.
    (define_predicate "small_addr_symbolic_operand"
      (and (match_code "symbol_ref")
           (match_test "SYMBOL_REF_SMALL_ADDR_P (op)")))

And here is another, showing the use of the C block.

    ;; True if op is a register operand that is (or could be) a GR reg.
    (define_predicate "gr_register_operand"
      (match_operand 0 "register_operand")
    {
      unsigned int regno;
      if (GET_CODE (op) == SUBREG)
        op = SUBREG_REG (op);

      regno = REGNO (op);
      return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno));
    })

Predicates written with `define_predicate` automatically include a test that mode is `VOIDmode`, or op has the same mode as mode, or op is a `CONST_INT` or `CONST_DOUBLE`. They do not check specifically for integer `CONST_DOUBLE`, nor do they test that the value of either kind of constant fits in the requested mode. This is because target-specific predicates that take constants usually have to do more stringent value checks anyway. If you need the exact same treatment of `CONST_INT` or `CONST_DOUBLE` that the generic predicates provide, use a `MATCH_OPERAND` subexpression to call `const_int_operand`, `const_double_operand`, or `immediate_operand`.

Predicates written with `define_special_predicate` do not get any automatic mode checks, and are treated as having special mode handling by `genrecog`.

The program `genpreds` is responsible for generating code to test predicates. It also writes a header file containing function declarations for all machine-specific predicates. It is not necessary to declare these predicates in `cpu-protos.h`.