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