17.24.5 Parameterized Names

Ports sometimes need to apply iterators using C++ code, in order to get the code or RTL pattern for a specific instruction. For example, suppose we have the ‘neon_vq<absneg><mode>’ pattern given above:

(define_int_iterator QABSNEG [UNSPEC_VQABS UNSPEC_VQNEG])

(define_int_attr absneg [(UNSPEC_VQABS "abs") (UNSPEC_VQNEG "neg")])

(define_insn "neon_vq<absneg><mode>"
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
	(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
		       (match_operand:SI 2 "immediate_operand" "i")]
		      QABSNEG))]
  …
)

A port might need to generate this pattern for a variable ‘QABSNEG’ value and a variable ‘VDQIW’ mode. There are two ways of doing this. The first is to build the rtx for the pattern directly from C++ code; this is a valid technique and avoids any risk of combinatorial explosion. The second is to prefix the instruction name with the special character ‘@’, which tells GCC to generate the four additional functions below. In each case, name is the name of the instruction without the leading ‘@’ character, without the ‘<…>’ placeholders, and with any underscore before a ‘<…>’ placeholder removed if keeping it would lead to a double or trailing underscore.

insn_code maybe_code_for_name (i1, i2, …)

See whether replacing the first ‘<…>’ placeholder with iterator value i1, the second with iterator value i2, and so on, gives a valid instruction. Return its code if so, otherwise return CODE_FOR_nothing.

insn_code code_for_name (i1, i2, …)

Same, but abort the compiler if the requested instruction does not exist.

rtx maybe_gen_name (i1, i2, …, op0, op1, …)

Check for a valid instruction in the same way as maybe_code_for_name. If the instruction exists, generate an instance of it using the operand values given by op0, op1, and so on, otherwise return null.

rtx gen_name (i1, i2, …, op0, op1, …)

Same, but abort the compiler if the requested instruction does not exist, or if the instruction generator invoked the FAIL macro.

For example, changing the pattern above to:

(define_insn "@neon_vq<absneg><mode>"
  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
	(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
		       (match_operand:SI 2 "immediate_operand" "i")]
		      QABSNEG))]
  …
)

would define the same patterns as before, but in addition would generate the four functions below:

insn_code maybe_code_for_neon_vq (int, machine_mode);
insn_code code_for_neon_vq (int, machine_mode);
rtx maybe_gen_neon_vq (int, machine_mode, rtx, rtx, rtx);
rtx gen_neon_vq (int, machine_mode, rtx, rtx, rtx);

Calling ‘code_for_neon_vq (UNSPEC_VQABS, V8QImode)’ would then give CODE_FOR_neon_vqabsv8qi.

It is possible to have multiple ‘@’ patterns with the same name and same types of iterator. For example:

(define_insn "@some_arithmetic_op<mode>"
  [(set (match_operand:INTEGER_MODES 0 "register_operand") …)]
  …
)

(define_insn "@some_arithmetic_op<mode>"
  [(set (match_operand:FLOAT_MODES 0 "register_operand") …)]
  …
)

would produce a single set of functions that handles both INTEGER_MODES and FLOAT_MODES.

It is also possible for these ‘@’ patterns to have different numbers of operands from each other. For example, patterns with a binary rtl code might take three operands (one output and two inputs) while patterns with a ternary rtl code might take four operands (one output and three inputs). This combination would produce separate ‘maybe_gen_name’ and ‘gen_name’ functions for each operand count, but it would still produce a single ‘maybe_code_for_name’ and a single ‘code_for_name’.