gccint: define_peephole

1 
1 17.18.1 RTL to Text Peephole Optimizers
1 ---------------------------------------
1 
1 A definition looks like this:
1 
1      (define_peephole
1        [INSN-PATTERN-1
1         INSN-PATTERN-2
1         ...]
1        "CONDITION"
1        "TEMPLATE"
1        "OPTIONAL-INSN-ATTRIBUTES")
1 
1 The last string operand may be omitted if you are not using any
1 machine-specific information in this machine description.  If present,
1 it must obey the same rules as in a 'define_insn'.
1 
1  In this skeleton, INSN-PATTERN-1 and so on are patterns to match
1 consecutive insns.  The optimization applies to a sequence of insns when
1 INSN-PATTERN-1 matches the first one, INSN-PATTERN-2 matches the next,
1 and so on.
1 
1  Each of the insns matched by a peephole must also match a
1 'define_insn'.  Peepholes are checked only at the last stage just before
1 code generation, and only optionally.  Therefore, any insn which would
1 match a peephole but no 'define_insn' will cause a crash in code
1 generation in an unoptimized compilation, or at various optimization
1 stages.
1 
1  The operands of the insns are matched with 'match_operands',
1 'match_operator', and 'match_dup', as usual.  What is not usual is that
1 the operand numbers apply to all the insn patterns in the definition.
1 So, you can check for identical operands in two insns by using
1 'match_operand' in one insn and 'match_dup' in the other.
1 
1  The operand constraints used in 'match_operand' patterns do not have
1 any direct effect on the applicability of the peephole, but they will be
1 validated afterward, so make sure your constraints are general enough to
1 apply whenever the peephole matches.  If the peephole matches but the
1 constraints are not satisfied, the compiler will crash.
1 
1  It is safe to omit constraints in all the operands of the peephole; or
1 you can write constraints which serve as a double-check on the criteria
1 previously tested.
1 
1  Once a sequence of insns matches the patterns, the CONDITION is
1 checked.  This is a C expression which makes the final decision whether
1 to perform the optimization (we do so if the expression is nonzero).  If
1 CONDITION is omitted (in other words, the string is empty) then the
1 optimization is applied to every sequence of insns that matches the
1 patterns.
1 
1  The defined peephole optimizations are applied after register
1 allocation is complete.  Therefore, the peephole definition can check
1 which operands have ended up in which kinds of registers, just by
1 looking at the operands.
1 
1  The way to refer to the operands in CONDITION is to write 'operands[I]'
1 for operand number I (as matched by '(match_operand I ...)').  Use the
1 variable 'insn' to refer to the last of the insns being matched; use
1 'prev_active_insn' to find the preceding insns.
1 
1  When optimizing computations with intermediate results, you can use
1 CONDITION to match only when the intermediate results are not used
1 elsewhere.  Use the C expression 'dead_or_set_p (INSN, OP)', where INSN
1 is the insn in which you expect the value to be used for the last time
1 (from the value of 'insn', together with use of 'prev_nonnote_insn'),
1 and OP is the intermediate value (from 'operands[I]').
1 
1  Applying the optimization means replacing the sequence of insns with
1 one new insn.  The TEMPLATE controls ultimate output of assembler code
1 for this combined insn.  It works exactly like the template of a
1 'define_insn'.  Operand numbers in this template are the same ones used
1 in matching the original sequence of insns.
1 
1  The result of a defined peephole optimizer does not need to match any
1 of the insn patterns in the machine description; it does not even have
1 an opportunity to match them.  The peephole optimizer definition itself
1 serves as the insn pattern to control how the insn is output.
1 
1  Defined peephole optimizers are run as assembler code is being output,
1 so the insns they produce are never combined or rearranged in any way.
1 
1  Here is an example, taken from the 68000 machine description:
1 
1      (define_peephole
1        [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4)))
1         (set (match_operand:DF 0 "register_operand" "=f")
1              (match_operand:DF 1 "register_operand" "ad"))]
1        "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
1      {
1        rtx xoperands[2];
1        xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
1      #ifdef MOTOROLA
1        output_asm_insn ("move.l %1,(sp)", xoperands);
1        output_asm_insn ("move.l %1,-(sp)", operands);
1        return "fmove.d (sp)+,%0";
1      #else
1        output_asm_insn ("movel %1,sp@", xoperands);
1        output_asm_insn ("movel %1,sp@-", operands);
1        return "fmoved sp@+,%0";
1      #endif
1      })
1 
1  The effect of this optimization is to change
1 
1      jbsr _foobar
1      addql #4,sp
1      movel d1,sp@-
1      movel d0,sp@-
1      fmoved sp@+,fp0
1 
1 into
1 
1      jbsr _foobar
1      movel d1,sp@
1      movel d0,sp@-
1      fmoved sp@+,fp0
1 
1  INSN-PATTERN-1 and so on look _almost_ like the second operand of
1 'define_insn'.  There is one important difference: the second operand of
1 'define_insn' consists of one or more RTX's enclosed in square brackets.
1 Usually, there is only one: then the same action can be written as an
1 element of a 'define_peephole'.  But when there are multiple actions in
1 a 'define_insn', they are implicitly enclosed in a 'parallel'.  Then you
1 must explicitly write the 'parallel', and the square brackets within it,
1 in the 'define_peephole'.  Thus, if an insn pattern looks like this,
1 
1      (define_insn "divmodsi4"
1        [(set (match_operand:SI 0 "general_operand" "=d")
1              (div:SI (match_operand:SI 1 "general_operand" "0")
1                      (match_operand:SI 2 "general_operand" "dmsK")))
1         (set (match_operand:SI 3 "general_operand" "=d")
1              (mod:SI (match_dup 1) (match_dup 2)))]
1        "TARGET_68020"
1        "divsl%.l %2,%3:%0")
1 
1 then the way to mention this insn in a peephole is as follows:
1 
1      (define_peephole
1        [...
1         (parallel
1          [(set (match_operand:SI 0 "general_operand" "=d")
1                (div:SI (match_operand:SI 1 "general_operand" "0")
1                        (match_operand:SI 2 "general_operand" "dmsK")))
1           (set (match_operand:SI 3 "general_operand" "=d")
1                (mod:SI (match_dup 1) (match_dup 2)))])
1         ...]
1        ...)
1