gccint: Expander Definitions

1 
1 17.15 Defining RTL Sequences for Code Generation
1 ================================================
1 
1 On some target machines, some standard pattern names for RTL generation
1 cannot be handled with single insn, but a sequence of RTL insns can
1 represent them.  For these target machines, you can write a
1 'define_expand' to specify how to generate the sequence of RTL.
1 
1  A 'define_expand' is an RTL expression that looks almost like a
1 'define_insn'; but, unlike the latter, a 'define_expand' is used only
1 for RTL generation and it can produce more than one RTL insn.
1 
1  A 'define_expand' RTX has four operands:
1 
1    * The name.  Each 'define_expand' must have a name, since the only
1      use for it is to refer to it by name.
1 
1    * The RTL template.  This is a vector of RTL expressions representing
1      a sequence of separate instructions.  Unlike 'define_insn', there
1      is no implicit surrounding 'PARALLEL'.
1 
1    * The condition, a string containing a C expression.  This expression
1      is used to express how the availability of this pattern depends on
1      subclasses of target machine, selected by command-line options when
1      GCC is run.  This is just like the condition of a 'define_insn'
1      that has a standard name.  Therefore, the condition (if present)
1      may not depend on the data in the insn being matched, but only the
1      target-machine-type flags.  The compiler needs to test these
1      conditions during initialization in order to learn exactly which
1      named instructions are available in a particular run.
1 
1    * The preparation statements, a string containing zero or more C
1      statements which are to be executed before RTL code is generated
1      from the RTL template.
1 
1      Usually these statements prepare temporary registers for use as
1      internal operands in the RTL template, but they can also generate
1      RTL insns directly by calling routines such as 'emit_insn', etc.
1      Any such insns precede the ones that come from the RTL template.
1 
11    * Optionally, a vector containing the values of attributes.  ⇒
      Insn Attributes.
1 
1  Every RTL insn emitted by a 'define_expand' must match some
1 'define_insn' in the machine description.  Otherwise, the compiler will
1 crash when trying to generate code for the insn or trying to optimize
1 it.
1 
1  The RTL template, in addition to controlling generation of RTL insns,
1 also describes the operands that need to be specified when this pattern
1 is used.  In particular, it gives a predicate for each operand.
1 
1  A true operand, which needs to be specified in order to generate RTL
1 from the pattern, should be described with a 'match_operand' in its
1 first occurrence in the RTL template.  This enters information on the
1 operand's predicate into the tables that record such things.  GCC uses
1 the information to preload the operand into a register if that is
1 required for valid RTL code.  If the operand is referred to more than
1 once, subsequent references should use 'match_dup'.
1 
1  The RTL template may also refer to internal "operands" which are
1 temporary registers or labels used only within the sequence made by the
1 'define_expand'.  Internal operands are substituted into the RTL
1 template with 'match_dup', never with 'match_operand'.  The values of
1 the internal operands are not passed in as arguments by the compiler
1 when it requests use of this pattern.  Instead, they are computed within
1 the pattern, in the preparation statements.  These statements compute
1 the values and store them into the appropriate elements of 'operands' so
1 that 'match_dup' can find them.
1 
1  There are two special macros defined for use in the preparation
1 statements: 'DONE' and 'FAIL'.  Use them with a following semicolon, as
1 a statement.
1 
1 'DONE'
1      Use the 'DONE' macro to end RTL generation for the pattern.  The
1      only RTL insns resulting from the pattern on this occasion will be
1      those already emitted by explicit calls to 'emit_insn' within the
1      preparation statements; the RTL template will not be generated.
1 
1 'FAIL'
1      Make the pattern fail on this occasion.  When a pattern fails, it
1      means that the pattern was not truly available.  The calling
1      routines in the compiler will try other strategies for code
1      generation using other patterns.
1 
1      Failure is currently supported only for binary (addition,
1      multiplication, shifting, etc.)  and bit-field ('extv', 'extzv',
1      and 'insv') operations.
1 
1  If the preparation falls through (invokes neither 'DONE' nor 'FAIL'),
1 then the 'define_expand' acts like a 'define_insn' in that the RTL
1 template is used to generate the insn.
1 
1  The RTL template is not used for matching, only for generating the
1 initial insn list.  If the preparation statement always invokes 'DONE'
1 or 'FAIL', the RTL template may be reduced to a simple list of operands,
1 such as this example:
1 
1      (define_expand "addsi3"
1        [(match_operand:SI 0 "register_operand" "")
1         (match_operand:SI 1 "register_operand" "")
1         (match_operand:SI 2 "register_operand" "")]
1        ""
1        "
1      {
1        handle_add (operands[0], operands[1], operands[2]);
1        DONE;
1      }")
1 
1  Here is an example, the definition of left-shift for the SPUR chip:
1 
1      (define_expand "ashlsi3"
1        [(set (match_operand:SI 0 "register_operand" "")
1              (ashift:SI
1                (match_operand:SI 1 "register_operand" "")
1                (match_operand:SI 2 "nonmemory_operand" "")))]
1        ""
1        "
1 
1      {
1        if (GET_CODE (operands[2]) != CONST_INT
1            || (unsigned) INTVAL (operands[2]) > 3)
1          FAIL;
1      }")
1 
1 This example uses 'define_expand' so that it can generate an RTL insn
1 for shifting when the shift-count is in the supported range of 0 to 3
1 but fail in other cases where machine insns aren't available.  When it
1 fails, the compiler tries another strategy using different patterns
1 (such as, a library call).
1 
1  If the compiler were able to handle nontrivial condition-strings in
1 patterns with names, then it would be possible to use a 'define_insn' in
1 that case.  Here is another case (zero-extension on the 68000) which
1 makes more use of the power of 'define_expand':
1 
1      (define_expand "zero_extendhisi2"
1        [(set (match_operand:SI 0 "general_operand" "")
1              (const_int 0))
1         (set (strict_low_part
1                (subreg:HI
1                  (match_dup 0)
1                  0))
1              (match_operand:HI 1 "general_operand" ""))]
1        ""
1        "operands[1] = make_safe_from (operands[1], operands[0]);")
1 
1 Here two RTL insns are generated, one to clear the entire output operand
1 and the other to copy the input operand into its low half.  This
1 sequence is incorrect if the input operand refers to [the old value of]
1 the output operand, so the preparation statement makes sure this isn't
1 so.  The function 'make_safe_from' copies the 'operands[1]' into a
1 temporary register if it refers to 'operands[0]'.  It does this by
1 emitting another RTL insn.
1 
1  Finally, a third example shows the use of an internal operand.
1 Zero-extension on the SPUR chip is done by 'and'-ing the result against
1 a halfword mask.  But this mask cannot be represented by a 'const_int'
1 because the constant value is too large to be legitimate on this
1 machine.  So it must be copied into a register with 'force_reg' and then
1 the register used in the 'and'.
1 
1      (define_expand "zero_extendhisi2"
1        [(set (match_operand:SI 0 "register_operand" "")
1              (and:SI (subreg:SI
1                        (match_operand:HI 1 "register_operand" "")
1                        0)
1                      (match_dup 2)))]
1        ""
1        "operands[2]
1           = force_reg (SImode, GEN_INT (65535)); ")
1 
1  _Note:_ If the 'define_expand' is used to serve a standard binary or
1 unary arithmetic operation or a bit-field operation, then the last insn
1 it generates must not be a 'code_label', 'barrier' or 'note'.  It must
1 be an 'insn', 'jump_insn' or 'call_insn'.  If you don't need a real insn
1 at the end, emit an insn to copy the result of the operation into
1 itself.  Such an insn will generate no code, but it can avoid problems
1 in the compiler.
1