ceriel 38 лет назад
Родитель
Сommit
e5a90d3bd8
3 измененных файлов с 877 добавлено и 0 удалено
  1. 6 0
      doc/top/Makefile
  2. 79 0
      doc/top/refs.top
  3. 792 0
      doc/top/top.n

+ 6 - 0
doc/top/Makefile

@@ -0,0 +1,6 @@
+top.f:
+	refer -sA+T -l4,2 -p refs.top top.n | nroff -ms > top.f
+top.f.35:
+	refer -sA+T -l4,2 -p refs.top top.n | nroff -ms -Thr35 > top.f.35
+top.f.agfa:
+	refer -sA+T -l4,2 -p refs.top top.n | nroff -ms -Tlp > top.f.agfa

+ 79 - 0
doc/top/refs.top

@@ -0,0 +1,79 @@
+%T A Practical Toolkit for Making Portable Compilers
+%A A.S. Tanenbaum
+%A J.M. van Staveren
+%A E.G. Keizer
+%A J.W. Stevenson
+%I Vrije Universiteit, Amsterdam
+%R Rapport nr IR-74
+%D October 1981
+
+%T A Practical Toolkit for Making Portable Compilers
+%A A.S. Tanenbaum
+%A J.M. van Staveren
+%A E.G. Keizer
+%A J.W. Stevenson
+%J CACM
+%V 26
+%N 9
+%P 654-660
+%D September 1983
+
+%T A Unix Toolkit for Making Portable Compilers
+%A A.S. Tanenbaum
+%A J.M. van Staveren
+%A E.G. Keizer
+%A J.W. Stevenson
+%J Proceedings USENIX conf.
+%C Toronto, Canada
+%V 26
+%D July 1983
+%P 255-261
+
+%T Using Peephole Optimization on Intermediate Code
+%A A.S. Tanenbaum
+%A J.M. van Staveren
+%A J.W. Stevenson
+%J TOPLAS
+%V 4
+%N 1
+%P 21-36
+%D January 1982
+
+%T Amsterdam Compiler Kit documentation
+%A A.S. Tanenbaum
+%A E.G. Keizer
+%A J.M. van Staveren
+%A J.W. Stevenson
+%I Vrije Universiteit, Amsterdam
+%R Rapport nr IR-90
+%D June 1984
+
+%T Language- and Machine-independant Global Optimization on
+Intermediate Code
+%A H.E. Bal
+%A A.S. Tanenbaum
+%I Vrije Universiteit, Amsterdam
+%R Rapport IR-98
+%D March 1985
+
+%T The Design and Implementation of the EM Global Optimizer
+%A H.E. Bal
+%I Vrije Universiteit, Amsterdam
+%R Rapport IR-99
+%D March 1985
+
+
+%T The C Programming Language
+%A B.W. Kernighan
+%A D.M. Ritchie
+%I Prentice-Hall, Inc
+%C Englewood Cliffs,NJ
+%D 1978
+
+%T Principles of compiler design
+%A A.V. Aho
+%A J.D. Ullman
+%I Addison-Wesley
+%C Reading, Massachusetts
+%D 1978
+

+ 792 - 0
doc/top/top.n

@@ -0,0 +1,792 @@
+.ND
+.pl 11.7i
+.ll 80m
+.nr LL 80m
+.nr tl 78m
+.tr ~
+.ds >. .
+.TL
+The ACK Target Optimizer
+.AU
+H.E. Bal
+.AI
+Vrije Universiteit
+Wiskundig Seminarium, Amsterdam
+.AB
+The Target Optimizer is one of several optimizers that are part of
+the Amsterdam Compiler Kit.
+It operates directly on assembly code,
+rather than on a higher level intermediate code,
+as the Peephole Optimizer and Global Optimizer do.
+Consequently, the Target Optimizer can do optimizations
+that are highly machine-dependent.
+.PP
+Each target machine has its own Target Optimizer.
+New optimizers are generated by the Target Optimizer Generator,
+which uses a machine-dependent table as input.
+This document contains full information on how to
+write such a table for a new machine.
+It also discusses the implementation of the
+Target Optimizer and its generator.
+.AE
+.bp
+.NH 1
+Introduction
+.PP
+.FS
+This work was supported by the
+Stichting Technische Wetenschappen (STW)
+under grant VWI03.0001.
+.FE
+This document describes the target optimizer component
+of the Amsterdam Compiler Kit (ACK) .
+.[
+tanenbaum staveren amsterdam toolkit
+.]
+.[
+tanenbaum staveren cacm
+.]
+.[
+tanenbaum staveren toronto
+.]
+Optimization takes place in several parts of ACK compilers,
+most notably in the Peephole Optimizer
+.[
+staveren peephole toplas
+.]
+and
+the Global Optimizer,
+.[
+bal tanenbaum global optimization
+.]
+.[
+bal implementation global optimizer
+.]
+which are both language- and machine-independent,
+and in the machine-specific code generators.
+.[
+documentation amsterdam compiler kit
+.]
+The target optimizer is the finishing touch in this sequence of
+optimizers.
+It can be used to capture those optimizations that are hard
+to express in the other parts of ACK.
+These optimizations will typically be very machine-specific.
+.PP
+The target optimizer operates on the assembly code of some target machine.
+Hence there is one target optimizer per machine.
+However, just as for the ACK code generators and assemblers,
+a framework has been build that allows easy generation of
+target optimizers out of machine-independent parts and a
+machine-dependent description table (see figure 1.).
+So the major part of the code of a target optimizer is
+shared among all target optimizers.
+.DS
+
+
+                                       |-------------------------|
+                                       | machine-independent     |
+                                       | code                    |
+                                       |                         |
+          |-----------------|          |-------------------------|
+descrip-  |target optimizer |          | machine-dependent code  |
+ tion --> |generator        | ---->    | + tables                |
+table     |                 |          |                         |
+          |-----------------|          |-------------------------|
+   
+                                              target optimizer
+   
+    Figure 1: Generation of a target optimizer.
+
+.DE
+.PP
+This document focusses on the description of the machine-dependent table.
+In chapter 2 we give an informal introduction to the optimization
+algorithm and to the definition of the table format.
+Chapters 3 and 4 discuss the implementation of the target optimizer
+and the target optimizer generator.
+Appendix A gives full information for writing a description table.
+.bp
+.NH 1
+Global structure of the target optimizer
+.PP
+The target optimizer is based on the well understood model
+of a \fIpeephole optimizer\fR.
+.[
+aho ullman compiler
+.]
+It contains a machine-dependent table
+of (pattern,replacement) pairs.
+Each pattern describes
+a sequence of one or more assembler instructions
+that can be replaced by zero or more equivalent, yet cheaper,
+instructions (the 'replacement').
+The optimizer maintains a \fIwindow\fR that moves over the input.
+At any moment, the window contains some contiguous part of the input.
+If the instructions in the current window match some pattern
+in the table,
+they are replaced by the corresponding replacement;
+else, the window moves one instruction to the right.
+.PP
+In the remainder of this section we will give an informal
+description of the machine-dependent table.
+A more precise definition is given in appendix A.
+We will first discuss the restrictions put on the
+format of the assembly code.
+.NH 2
+Assumptions about the assembly code format
+.PP
+We assume that a line of assembly code begins with an
+instruction \fImnemonic\fR (opcode),
+followed by zero or more \fIoperands\fR.
+The mnemonic and the first operand must be separated by a special
+character (e.g. a space or a tab).
+Likewise, the operands must be separated by a special
+character (e.g. a comma).
+These separators need not be the same for all machines.
+.NH 2
+Informal description of the machine-dependent tables
+.PP
+The major part of the table consists of (pattern,replacement) pairs
+called \fIentries\fR.
+.PP
+A pattern is a list of instruction descriptions.
+Each instruction description describes the instruction mnemonic and
+the operands.
+.PP
+A mnemonic is described either by a string constant or by the
+keyword ANY.
+As all entities dealt with by the target optimizer are strings,
+string constants do not contain quotes.
+A string constant matches only itself.
+ANY matches every instruction mnemonic.
+.nf
+
+Examples of mnemonic descriptions:
+
+        add
+        sub.l
+        mulw3
+        ANY
+.fi
+.PP
+An operand can also be described by a string constant.
+.nf
+
+Examples:
+
+       (sp)+
+       r5
+       -4(r6)
+
+.fi
+Alternatively, it can be described by means of a \fIvariable name\fR.
+Variables have values which are strings.
+They have to be declared in the table before the patterns.
+Each such declaration defines the name of a variable and
+a \fIrestriction\fR to which its value is subjected.
+.nf
+Example of variable declarations:
+
+      CONST       { VAL[0] == '$' };
+      REG         { VAL[0] == 'r' && VAL[1] >= '0' && VAL[1] <= '3' &&
+                    VAL[2] == '\\0' };
+      X           { TRUE };
+
+.fi
+The keyword VAL denotes the value of the variable, which is
+a null-terminated string.
+An operand description given via a variable name matches an
+actual operand if the actual operand obeys the associated restriction.
+.nf
+
+     CONST  matches   $1, $-5, $foo etc.
+     REG    matches   r0, r1, r2 and r3
+     X      matches   anything
+.fi
+The restriction (between curly braces) may be any legal "C"
+.[
+kernighan ritchie c programming
+.]
+expression.
+It may also contain calls to user-defined procedures.
+These procedures must be added to the table after the patterns.
+.nf
+
+Example:
+
+     FERMAT_NUMBER    { VAL[0] == '$' && is_fermat_number(&VAL[1]) };
+
+.fi
+An operand can also be described by a mixture of a string constant
+and a variable name.
+The most general form allowed is:
+.nf
+
+       string_constant1 variable_name string_constant2
+
+Example:
+
+       (REG)+  matches  (r0)+, (r1)+, (r2)+ and (r3)+
+
+.fi
+Any of the three components may be omitted,
+so the first two forms are just special cases of the general form.
+The name of a variable can not be used as a string constant.
+In the above context, it is impossible to define an operand that
+matches the string "REG".
+This limitation is of little consequence,
+as the table writer is free to choose the names of variables.
+This approach, however, avoids the need for awkward escape sequences.
+.PP
+A pattern consists of one or more instruction descriptions
+(separated by a colon)
+followed by an optional constraint.
+A pattern "P1 : P2 : .. : Pn C" matches the sequence of
+instructions "I1 I2 .. In" if:
+.IP (i) 7
+for each i, 1 <= i <= n, Pi matches Ii, as described above;
+.IP (ii)
+multiple occurrences of the same variable name or of
+the keyword ANY stand for the same values throughout the pattern;
+.IP (iii)
+the optional constraint C is satisfied, i.e. it evaluates to TRUE.
+.LP
+.nf
+The pattern:
+
+      dec REG : move.b CONST,(REG)
+
+matches:
+
+      dec r0 : move.b $4,(r0)
+
+but not:
+
+      dec r0 : move.b $4,(r1)
+
+(as the variable REG matches two different strings).
+.fi
+If a pattern containing different registers must be described,
+extra names for a register should be declared, all sharing
+the same restriction.
+.nf
+Example:
+
+     REG1,REG2  { VAL[0] == 'r' &&  .....  };
+
+     addl3 REG1,REG1,REG2 : subl2 REG2,REG1
+.fi
+.PP
+The optional constraint is an auxiliary "C" expression (just like
+the parameter restrictions).
+The expression may refer to the variables and to ANY.
+.nf
+Example:
+
+    move REG1,REG2    { REG1[1] == REG2[1] + 1 }
+
+matches
+
+    move r1,r0
+    move r2,r1
+    move r3,r2
+.fi
+.PP
+The replacement part of a (pattern,replacement) table entry
+has the same structure as a pattern, except that:
+.IP (i)
+it may not contain an additional constraint;
+.IP (ii)
+it may be empty.
+.LP
+A replacement may also refer to the values of variables and ANY.
+.NH 2
+Examples
+.PP
+This section contains some realistic examples for
+optimization on PDP-11 and Vax assembly code.
+.NH 3
+Vax examples
+.PP
+Suppose the table contains the following declarations:
+.nf
+         X, LOG        { TRUE };
+         LAB           { VAL[0] == 'L' };   /* e.g. L0017 */
+         A             { no_side_effects(VAL) };
+         NUM           { is_number(VAL) };
+
+.fi
+The procedure "no_side_effects" checks if its argument
+contains any side effects, i.e. auto increment or auto decrement.
+The procedure "is_number" checks if its argument contains only digits.
+These procedures must be supplied by the table-writer and must be
+included in the table.
+.PP
+.nf
+\fIentry:\fR  addl3 X,A,A    -> addl2 X,A;
+
+.fi
+This entry changes a 3-operand instruction into a cheaper  2-operand
+instruction.
+An optimization like:
+.nf
+
+        addl3 r0,(r2)+,(r2)+   -> addl2 r0,(r2)+
+
+.fi
+is illegal, as r2 should be incremented twice.
+Hence the second argument is required to
+be side-effect free.
+.PP
+.nf
+\fIentry:\fR  addw2 $-NUM,X  -> subw2 $NUM,X;
+
+.fi
+An instruction like "subw2 $5,r0" is cheaper
+than "addw2 $-5,r0",
+because constants in the range 0 to 63 are represented
+very efficiently on the Vax.
+.PP
+.nf
+\fIentry:\fR  bitw $NUM,A : jneq LAB
+                { is_poweroftwo(NUM,LOG) }  -> jbs $LOG,A,LAB;
+
+.fi
+A "bitw x,y" sets the condition codes to the bitwise "and" of
+x and y.
+A "jbs n,x,l" branches to l if bit n of x is set.
+So, for example, the following transformation is possible:
+.nf
+
+      bitw $32,r0 : jneq L0017 ->  jbs $5,r0,L0017
+
+.fi
+The user-defined  procedure "is_poweroftwo" checks if its first argument is
+a power of 2 and, if so, sets its second argument to the logarithm
+of the first argument. (Both arguments are strings).
+Note that the variable LOG is not used in the pattern itself.
+It is assigned a (string) value by "is_poweroftwo" and is used
+in the replacement.
+.NH 3
+PDP-11 examples
+.PP
+Suppose we have the following declarations:
+.nf
+         X             { TRUE };
+         A             { no_side_effects(VAL) };
+         L1, L2        { VAL[0] == 'I' };
+         REG           { VAL[0] == 'r' && VAL[1] >= '0' && VAL[1] <= '5' &&
+                         VAL[2] == '\\0' };
+
+.fi
+The implementation of "no_side_effects" may of course
+differ for the PDP-11 and the Vax.
+.PP
+.nf
+\fIentry:\fR  mov REG,A : ANY A,X  ->  mov REG,A : ANY REG,X ;
+
+.fi
+This entry implements register subsumption.
+If A and REG hold the same value (which is true after "mov REG,A")
+and A is used as source (first) operand, it is cheaper to use REG instead.
+.PP
+.nf
+\fIentry:\fR  jeq L1 : jbr L2 : labdef L1  ->  jne L2 : labdef L1;
+
+.fi
+The "jeq L1" is a "skip over an unconditional jump". "labdef L1"
+denotes the definition (i.e. defining occurrence) of label L1.
+As the target optimizer has to know how such a definition
+looks like, this must be expressed in the table (see Appendix A).
+.PP
+.nf
+\fIentry:\fR  add $01,X { carry_dead(REST) }  -> inc X;
+
+.fi
+On the PDP-11, an add-one is not equivalent to an increment.
+The latter does not set the carry-bit of the condition codes,
+while the former does.
+So a look-ahead is needed to see if the rest of the input uses
+the carry-bit before changing the condition codes.
+A look-ahead of one instruction is provided by
+the target optimizer.
+This will normally be sufficient for compiler-generated code.
+The keyword REST contains the mnemonic of the first instruction of
+the rest of the input.
+If this instruction uses the carry-bit (e.g. an adc, subc, bhis)
+the transformation is not allowed.
+.bp
+.NH 1
+Implementation of the target optimizer
+.PP
+The target optimizer reads one input file of assembler instructions,
+processes it, and writes the optimized code
+to the output file.
+So it performs one pass over the input.
+.NH 2
+The window mechanism
+.PP
+The optimizer uses a \fIwindow\fR that moves over the input.
+It repeatedly tries to match the instructions in the window
+with the patterns in the table.
+If no match is possible, the window moves
+one instruction forwards (to the right).
+After a successful match the matched instructions are
+removed from the window and are replaced by the
+replacement part of the table entry.
+Furthermore, the window is moved a few instructions
+backwards,
+as it is possible that instructions that were rejected earlier now do match.
+For example, consider the following patterns:
+.DS
+cmp $0, X           -> tst X ;
+mov REG,X : tst X   -> move REG.X ;   /* redundant test */
+.DE
+If the input is:
+.DS
+mov r0,foo : cmp $0,foo
+.DE
+then the first instruction is initially rejected.
+However, after the transformation
+.DS
+cmp $0,foo   ->  tst foo
+.DE
+the following optimization is possible:
+.DS
+mov r0,foo : tst foo  ->  mov r0,foo
+.DE
+.PP
+The window is implemented a a \fIqueue\fR.
+Matching takes place at the head of the queue.
+New instructions are added at the tail.
+If the window is moved forwards, the instruction at the head
+is not yet written to the output,
+as it may be needed later on.
+Instead it is added to a second queue,
+the \fIbackup queue\fR.
+After a successful match, the entire backup queue is
+inserted at the front of the window queue,
+which effectively implements the shift backwards.
+.PP
+Both queues have the length of the longest pattern in the table.
+If, as a result of a forward window move,
+the backup queue gets full,
+the instruction at its head is outputted and removed.
+Instructions are read from the input whenever the
+window queue contains fewer elements than the length
+of the longest pattern.
+.NH 2
+Pattern matching
+.PP
+Pattern matching is done in three steps:
+.IP (i) 7
+find patterns in the table whose instruction mnemonics
+match the mnemonics of the instructions in the
+current window;
+.IP (ii)
+check if the operands of the pattern match the operands of the
+instructions in the current window;
+.IP (iii)
+check if the optional constraint is satisfied.
+.LP
+For step (i) hashing is used.
+The mnemonic of the first instruction of the window
+is used to determine a list of possible patterns.
+Patterns starting with ANY are always tried.
+.PP
+Matching of operand descriptions against actual operands
+takes place as follows.
+The general form of an operand description is:
+.DS
+string_constant1 variable_name string_constant2
+.DE
+The actual operand should begin with string_constant1 and end
+on string_constant2.
+If so, these strings are stripped from it and the remaining string is
+matched against the variable.
+Matching a string against a variable is
+defined as follows:
+.IP 1.
+initially (before the entire pattern match)
+all variables are uninstantiated;
+.IP 2.
+matching a string against an uninstantiated variable
+succeeds if the restriction associated with the variable is
+satisfied.
+As a side effect, it causes the variable to be instantiated to
+the string;
+.IP 3.
+matching a string against an instantiated variable succeeds
+only if the variable was instantiated to the same string.
+.LP
+Matching an actual mnemonic against the keyword ANY is defined likewise.
+.PP
+The matching scheme implements the requirement that multiple occurrences
+of the same variable name or of the keyword ANY should
+stand for the same values throughout the entire pattern
+(see section 2.).
+.PP
+Both the parameter restriction of 2. and the constraint of step (iii)
+are checked by executing the "C" expression.
+.NH 2
+Data structures
+.PP
+The most important data structure is the representation
+of the input instructions.
+For every instruction we use two representations:
+.IP (i)
+the textual representation,
+i.e. the exact code as it appeared in the input;
+.IP (ii)
+a structural representation,
+containing the opcode and the operands.
+.LP
+The opcode of an instruction is determined as soon as it is read.
+If the line contains a label definition, the opcode is set
+to "labdef", so a label definition is treated like a normal
+instruction.
+.PP
+The operands of an instruction are not determined until
+they are needed, i.e. until step (i) of the pattern matching
+process has succeeded.
+For every instruction we keep track of a \fIstate\fR.
+After the opcode has successfully been determined,
+the state is OPC_ONLY.
+Once the operands have been recognized, the state is set to DONE.
+If the opcode or operands can not be determined,
+or if the instruction cannot be optimized for any other
+reason (see Appendix A), the state is set to JUNK
+and any attempt to match it will fail.
+.PP
+For each table entry we record the following information:
+.IP (i) 7
+the length of the pattern (i.e. the number of instruction descriptions)
+.IP (ii)
+a description of the instructions of the pattern
+.IP (iii)
+the length of the replacement
+.IP (iv)
+a description of the instructions of the replacement.
+.LP
+The description of an instruction consists of:
+.IP (i)
+the opcode
+.IP (ii)
+for each operand, a description of the operand.
+.LP
+The description of an operand of the form:
+.DS
+string_constant1 variable_name string_constant2
+.DE
+contains:
+.IP (i)
+both string constants
+.IP (ii)
+the number of the variable.
+.LP
+Each declared variable is assigned a unique number.
+For every variable we maintain:
+.IP (i)
+its state (instantiated or not instantiated)
+.IP (ii)
+its current value (a string).
+.LP
+The restrictions on variables and the constraints are stored
+in a switch-statement,
+indexed by variable number and entry number respectively.
+.bp
+.NH 1
+Implementation of the target optimizer generator
+.PP
+The target optimizer generator (\fItopgen\fR)
+reads a target machine description table and produces
+two files:
+.IP gen.h: 9
+contains macro definitions for
+machine parameters that were changed
+in the parameter section of the table (see appendix A)
+and for some attributes derived from the table
+(longest pattern, number of patterns, number
+of variables).
+.IP gen.c:
+contains the entry description tables,
+code for checking the parameter restrictions and constraints
+(switch statements)
+and the user-defined procedures.
+.LP
+These two files are compiled together with some machine-independent
+files to produce a target optimizer.
+.PP
+Topgen is implemented using 
+the LL(1) parser generator system LLgen,
+a powerful tool of the Amsterdam Compiler Kit.
+This system provides a flexible way of describing the syntax of the tables.
+The syntactical description of the table format included
+in Appendix A was derived from the LLgen syntax rules.
+.PP
+The parser uses a simple, hand-written, lexical analyzer (scanner).
+The scanner returns a single character in most cases.
+The recognition of identifiers is left to the parser, as
+this eases the analysis of operand descriptions.
+Comments are removed from the input by the scanner,
+but white space is passed to the parser,
+as it is meaningful in some contexts (it separates the
+opcode description from the description of the first operand).
+.PP
+Topgen maintains two symbol tables, one for variable names and one
+for tunable parameters.
+The symbol tables are organized as binary trees.
+.bp
+.SH
+Appendix A
+.PP
+In this appendix we present a complete definition of the target
+optimizer description table format.
+This appendix is intended for table-writers.
+We use syntax rules for the description of the table format.
+The following notation is used:
+.nf
+      { a }      zero or more of a
+      [ a ]      zero or one of a
+      a b        a followed by b
+      a | b      a or b
+
+.fi
+Terminals are given in quotes, as in ';'.
+.PP
+The table may contain white space and comment at all reasonable places.
+Comments are as in "C", so they begin with /* and end on */.
+Identifiers are sequences of letters, digits and the underscore ('_'),
+beginning with a letter.
+.PP
+.DS
+table   ->   {parameter_line} '%%;' {variable_declaration} '%%;'
+             {entry} '%%;' user_routines.
+
+.DE
+A table consists of four sections, containing machine-dependent
+constants, variable declarations, pattern rules and
+user-supplied subroutines.
+.PP
+.DS
+parameter_line ->  identifier value ';' .
+
+.DE
+A parameter line defines some attributes of the target machines
+assembly code.
+For unspecified parameters default values apply.
+The names of the parameters and the corresponding defaults
+are shown in table 1.
+.DS
+       OPC_TERMINATOR       ' '
+       OP_SEPARATOR         ','
+       LABEL_STARTER        'I'
+       LABEL_TERMINATOR     ':'
+       MAXOP                  2
+       MAXOPLEN              25
+       MAX_OPC_LEN           10
+       MAXVARLEN             25
+       MAXLINELEN           100
+
+       table 1: parameter names and defaults
+.DE
+The OPC_TERMINATOR is the character that separates the instruction
+mnemonic from the first operand (if any).
+The OP_SEPARATOR separates adjacent operands.
+A LABEL_STARTER is the first character of an instruction label.
+(Instruction labels are assumed to start with the same character).
+The LABEL_TERMINATOR is the last character of a label definition.
+It is assumed that this character is not used in an applied
+occurrence of the label identifier.
+For example, the defining occurrence may be "I0017:"
+and the applied occurrence may be "I0017"
+as in "jmp I0017".
+MAXOP defines the maximum number of operands an instruction can have.
+MAXOPLEN is the maximum length (in characters) of an operand.
+MAX_OPC_LEN is the maximum length of an instruction opcode.
+MAXVARLEN is the maximum length of a declared string variable.
+As variables may be set by user routines (see "bitw" example for
+the Vax) the table-writer must have access to this length and
+must be able to change it.
+MAXLINELEN denotes the maximum length of a line of assembly code.
+.PP
+If a line of assembly code violates any of the assumptions or
+exceeds some limit,
+the line is not optimized.
+Optimization does, however, proceed with the rest of the input.
+.PP
+.DS
+variable_declaration  -> identifier {',' identifier} restriction ';' .
+
+restriction           ->  '{' anything '}' .
+.DE
+A variable declaration declares one or more string variables
+that may be used in the patterns and in the replacements.
+If a variable is used as part of an operand description in
+a pattern, the entire pattern can only match if the
+restriction evaluates to TRUE.
+If the pattern does match, the variable is assigned the matching
+part of the actual operand.
+Variables that are not used in a pattern are initialized to
+null-strings and may be assigned a value in the constraint-part of
+the pattern.
+.PP
+The restriction must be a legal "C" expression.
+It may not contain a closing bracket ('}').
+Inside the expression, the name VAL stands for the part of the actual
+(matching) operand.
+The expression may contain calls to procedures that are defined in the
+user-routines section.
+.DS
+entry             ->  pattern '->' replacement ';' .
+
+pattern           ->  instruction_descr
+		      { ':' instruction_descr }
+		      constraint .
+
+replacement       ->  [ instruction_descr { ':' instruction_descr } ] .
+
+instruction_descr -> opcode
+		     white
+		     [ operand_descr { ',' operand_descr } ] .
+
+constraint        -> '{' anything '}' .
+
+operand_descr     -> [ string_constant ]
+		     [ variable_name ]
+		     [ string_constant ] .
+
+variable_name     -> identifier .
+
+opcode            -> anything .
+.DE
+The symbol 'white' stands for white space (space or tab).
+An opcode can be any string not containing the special
+symbols ';', '{', '}', ':', ',', '->' or white space.
+To be recognized, it must begin with a letter.
+The opcode should either be a mnemonic of a target machine
+instruction or it should be one of the keywords ANY and labdef.
+ANY matches any actual opcode. labdef matches only label definitions.
+.PP
+If an operand description contains an identifier (as defined earlier),
+it is checked if the identifier is the name of a declared variable.
+This effects the semantics of the matching rules for the operand,
+as described in section 2.
+An operand may contain at most one such variable name.
+.PP
+The constraint must be a legal "C" expression, just as the operand restriction.
+It may call user-defined procedures and use or change the value of
+declared variables.
+It may also use the string variable REST,
+which contains the mnemonic of the first instruction of the
+rest of the input. (REST is a null-string if this mnemonic can
+not be determined).
+.DS
+user_routines -> anything .
+.DE
+The remainder of the table consists of user-defined subroutines.
+.bp
+.[
+$LIST$
+.]