specRTL:A Language for Machine Descriptions
-
specRTL (Spec Register Transfer Language) is a language designed to
replace the existing RTL form machine descriptions which along with C Code forms the backend of GCC.
specRTL provides a compositional specification mechanism for defining patterns that describe RTL templates in machine descriptions. These patterns can be refined by extending them and by associating concrete details with them in a a need based manner. Machine descriptions written using specRTL are smaller and simpler and hence easy to read, construct, and maintain. specRTL integrates with conventional machine descriptions seamlessly. Since specRTL compiler generates the conventional machine descriptions, GCC source need not change. This enables external, incremental and non-disruptive migration of the existing machine descriptions to specRTL and construction of new machine descriptions thereby paving way for a smooth transition to better code generation in GCC.
- GCC is very widely used compiler. It has been ported to
almost 30 different cpu architectures. This portability is achieved by
instructing the compiler to generate code for the target machine of choice. All such target machines are described to GCC in the form of a Lisp like (syntactically) language knows as RTL along with a few C files.
The header files associated with the C files describe the structure of the target architecture like the register and stack layout while the machine descriptions describe target optimization and make sure that the correct assembly code is generated for the desired target machine. The .md files contain a pattern for each instruction that the target machine supports.
However, this mechanism is quite ad hoc and the machine descriptions are difficult to construct, understand maintain, and enhance because of the verbosity, the amount of details and the repetitiveness. There is no systematic way of constructing machine descriptions and there are no clear guide-lines on where to begin developing machine descriptions.
specRTL tries to resolve this problem by separating the shapes from the fine details.
We introduce three different types of patterns:
- Abstract Patterns
- Concrete Patterns
- List Patterns
- Abstract Patterns
Abstract Patterns describe the shape of the pattern eliminating all the concrete details.
As these do not contain anything related to the target machine, most of these can be used across
different architectures. This concept gives rise to the basis set which will be detailed below.
abtract set_plus2 extends set {
root.2:=plus;
}
Abstract patterns can extend other abstract patterns to form more complex tree structures needed by many md patterns, thus, reusing existing shapes.
abstract set_plus2_minus2 extends set_plus2 {
root.2.2:=minus;
}
- Concrete Patterns
Concrete patterns derive their structures from abstract patterns. Only details must be specified o these patterns. The data provided in these patterns is attached to the leaf nodes of the abstract pattern trees.
concrete addsi3.insn instantiates set_plus2 {
root (register_operand:SI:"p", register_operand:SI:"q",
register_operand:QI:"p");
root.2.mode:=SI;
}
There are many cases where the patterns only differ slightly with respect to each other. For e.g. Only the "Mode" of an operand is chagned. In such cases, it is better to override another pattern and make the necessary changes as against create and instantiate another abstract pattern.
Consider the following example where
concrete adddi3.insn overrides addsi3.insn {
SI->DI;
}
There are many ways in which we can override various aspects of a concrete pattern. The above example changes all the instances SI into DI. i.e. It replaces the modes in all of the matching operands.
The other statements that can be written in an overriding concrete pattern are:
- root.x:=newPredicate:newMode:newConstraint
- root.x.operand:=newPredicate:newMode:newConstraint
- root.x.predicate:=newPredicate
- root.x.constraint:=newConstraint
- root.x.mode:=newMode
- allconstraints:=("","","")
By using the above stated constructs and using overrides, the textual size of the patterns can be drastically reduced.
- Patterns can distinguished by their shapes and details. In specRTL,
we have separated these shapes into abstract patterns and the details into concrete patterns. Many of the MD patterns share common shapes.
The addsi3 concrete pattern for instance instantiates the set_plus2 abstract pattern. Patterns instantiating set_plus2, having different names maybe,
are found in almost all of the architectures. We have embedded such abstract patterns inside the specRTL pattern.
There is no need to write this abstract pattern in the specRTL file and can be directly instantiated or extended.
The list of all such patterns is given below. The patterns follow a specific naming scheme which is detailed here.
Abstract Patterns From the Basis Set
|
set_const | set_const2 | set_const_int2 |
set_const_fixed2 | set_const_string2 | set_const_vector2 |
set_symbol_ref2 | set_label_ref2 | set_high2 |
set_plus2 | set_ss_plus2 | set_us_plus2 |
set_minus2 | set_ss_minus2 | set_us_minus2 |
set_plusminus2 | set_mult2 | set_ssmult2 |
set_usmult2 | set_ssdiv2 | set_usdiv2 |
set_div2 | set_udiv2 | set_mod2 |
set_umod2 | set_smax2 | set_smin2 |
set_smaxmin2 | set_umax2 | set_umin2 |
set_unsigned_float2 | set_float2 | set_neg2 |
set_ssneg2 | set_usneg2 | set_absneg2 |
set_abs2 | set_sign_extend1 | set_sign_extend2 |
set_sign_extract2 | set_zero_extract1 | set_zero_extract2 |
set_fe2 | set_sqrt2 | set_bswap2 |
set_ashift2 | set_lshiftrt2 | set_ashiftrt2 |
set_any_shiftrt2 | set_not2 | set_ior2 |
set_and2 | set_or2 | set_ao2 |
set_xor2 | set_compare2 | set_compare |
set_if_then_else2 | set_if_then_else | set_ite2 |
set_match_operator2 | set_match_operator | set_match_op_dup2 |
set_match_op_dup | set_eq2 | set_ne2 |
set_lt2 | set_ltu2 | set_gt2 |
set_gtu2 | set_ge2 | set_geu2 |
set_le2 | set_leu2 | set_mem1 |
set_mem | set_mem2 | set_srict_low_part1 |
set_unspec | set_rotate2 | set_call2 |
set_parity2 | set_truncate2 | set_sset_truncate2 |
set_unset_truncate2 | set_float_truncate2 | set_fix2 |
set_unsigned_fix2 | set_vec_merge2 | set_vec_select2 |
set_vec_concat2 | set_vec_duplicate2 | set_fma2 |
set_unspec_volatile2 | set_zero_extract | set_subreg2 |
set_float_truncate2 | set_zero_extract2 | set_zero_extend2 |
set_vect_merge2 | set_strict_low_part1 | set_mem1 |
set_unspec2_compare | set_unspec_compare | set_compare2_minus1 |
set_compare_minus | set_compare2_plus1 | set_compare2_neg1 |
set_compare2_and1 | set_compare2_any_or1 | set_ite2_ne1 |
set_zero_extend2_not1 | set_zero_extend2_ashift1 | set_zero_extend2_any_shiftrt1 |
set_zero_extend2_any_rotate1 | set_and2_zero_extract | set_and2_not1 |
set_and2_neg1 | set_and2_plus1 | set_and2_plus1_not2 |
set_ior2_plus1 | set_ior2_plus1_not2 | set_ior2_plus1 |
set_vect_merge2_plus1_minus2 | set_plus2_plus1 | set_plus2_mult1 |
set_match_operator2_eq1 | set_absneg2_float_extend1 | set_ao2_zero_extend1 |
set_srict_low_part1_and1 | set_zero_extract2_subreg1 | set_zero_extract2_plus1 |
set_zero_extract2_minus1 | set_mult2_any_extend2 | set_zero_extract2_plusminus1 |
set_unspec_compare_match_operator | set_zero_extend2_sign_extend | set_vec_concat2_float_truncate1 |
set_compare2_plus | set_compare2_neg | set_compare_not |
set_compare2_minus | set_compare2_and | set_compare2_ashift1 |
set_zero_extend2_minus1 | set_zero_extend2_minus | set_zero_extend_not |
set_match_op_dup2_and1 | set_match_operator2_and1 | set_strict_low_part_and2 |
set_zero_extract1_and2 | set_if_then_else2_ne1 | set_const_double2 |
| set_unspec2 | |
- This section details the basis set. Writing specRTL and it compact comes to choosing the correct abstract patterns that the concrete patterns extend. A concrete pattern like define_insn can be created in a multitude number of ways an be instantiated from a single abstract pattern or a chain of abstract patterns. Many of the most used abstract patterns which constitute the basis set are already a part of the compiler. We propose a certain convention while naming abstract patterns. This convention has also been largely followed while creating the patterns in the basis set. The name of the abstract patterns should be able to tell the reader what the pattern is made of without looking at the pattern body. e.g. set_plus2 denotes that plus is the second child of set.
Similarly,
set_plus2_minus2_clobber2 denotes that plus2 is the second child of set. minus
is a second child of plus and clobber is the second child of minus.
-
The compiler has to be compiled with make. An executable srtl is generated. This executable also contains the basis set.
./srtl -o outFile.md inFile.specmd
inFile.specmd contains the specRTL machine descriptions. While outFile.md contains the conventional machine descriptions that the compiler generates.
This file can then be replaced in the GCC Machine Descriptions folder. We have not yet integrated srtl with the GCC Building process.
-
specRTL Visualizer
specRTL Visualizer is an application written in Qt which makes it easier to write & visualize specRTL.
It shows graphical representation of patterns, both abstract and concrete, in the form of trees.
When writing a concrete pattern, the structure of the abstract pattern that the pattern is instantiating
is displayed and concrete details are filled in after pattern is completed.
- The compiler is written in C++ using the C++ extensions of flex & bison. srtl_driver is the main class which drives the flow as well as contains important data structures like the symbol table and the basis set. There are 2 symbol tables.
- Known Pattern Names Table.
- Pattern Table.
- The known Pattern names table contains known operands along with the maximum number of children the operand can have. It is map of String:Int. If the input file contains a define_code_attr, then that name is also added to this table with its maximum number of children depending upon one of its children. This dynamic behavior is only valid for that specific invocation.
-
Pattern Table. This table is the primary symbol table, which stores patterns that are already parsed. These patterns are needed when another pattern instantiates/extends or overrides a pattern that is already parsed and thus exists in the symbol table.
-
The classes Abstract Pattern, Concrete Pattern and List Pattern inherit the Pattern parent class.
The methods createPattern for ConcretePattern and ListPattern and createPatternOut for ConcretePattern for Patterns like splits and peephole2 take care of
generating the respective pattern.
Abstract Patterns contain a tree constructed from the objects of the class Node. Classes Operand and ModeStmt help in creating the pattern details.
-
- Abstract Constructs
Abstract Patterns define the shape of the MD Constructs i.e. they define
the structure of the tree. Abstract patterns either extend a root
node or they extend other abstract patterns. It possible to change any
node of an abstract pattern thus giving us the flexibility of creating
complex shapes required by many MD Constructs.
Syntax:
e.g. Simple abstract pattern:
abstract set_set extends sequence
{
root.1:=set;
root.2:=set;
}
e.g. A complex abstract pattern subdivided into different parts that
can be used later in other patterns.
abstract set_compare2 extends set
{
root.2:=compare;
}
abstract set_compare2_and1 extends set_compare2
{
root.2.1:=and;
}
abstract set_compare2_and1_zero_extract1 extends set_compare2_and1
{
root.2.1.1:=zero_extract;
}
abstract set_zero_extract1_and2 extends set
{
root.1:=zero_extract;
root.2:=and;
}
abstract set_zero_extract1_and2_zero_extract1 extends set_zero_extract1_and2
{
root.2.1:=zero_extract;
}
abstract set_compare2_and1_zero_extract1_set_zero_extract1_and2_zero_
extract1 extends sequence
{
root.1:=set_compare2_and1_zero_extract1;
root.2:=set_zero_extract1_and2_zero_extract1;
}
NOTE: The above final pattern
set_compare2_and1_zero_extract1_set_zero_extract1_and2_zero_extract1
can be constructed in a single step also by defining the various non-leaf
nodes like in example 1.
-
Concrete Pattern
Concrete patterns must either instantiate abstract patterns or they
should override other concrete patterns. Concrete patterns take the
shape of the abstract pattern that they have been associated with. If
a concrete pattern overrides another concrete pattern, then it takes
the shape of the abstract pattern related with that of the overridden
concrete pattern.
Syntax:
concrete spec header { in specs } {: other stu :} { out specs }
This syntax differs slightly with each pattern as has been detailed below.
- define insn
Syntax:
CONCRETE name.insn (INSTANTIATES|OVERRIDES) name.{insn|exp} {
statements
}
{:
cmd_spec
:}
e.g. MD Construct:
(define_insn "*cmp_ccno_1"
[(set (reg FLAGS_REG)
(compare (match_operand:SWI 0 "nonimmediate_operand" ",?m")
(match_operand:SWI 1 "const0_operand" "")))]
"ix86_match_ccmode (insn, CCNOmode)"
"@
test{}\t%0, %0
cmp{}\t{%1, %0|%0, %1}"
[(set_attr "type" "test,icmp")
(set_attr "length_immediate" "0,1")
(set_attr "mode" "")])
Corresponding specRTL Pattern:
concrete *cmp_ccno_1.insn instantiates set_compare
{
root(reg(NULL:FLAGS_REG),0=nonimmediate_operand:SWI:",?m",
1=const0_operand:SWI:"");
}
{:
"ix86_match_ccmode (insn, CCNOmode)"
"@
test{}\t%0, %0
cmp{}\t{%1, %0|%0,%1}"
[(set_attr "type" "test,icmp")
(set_attr "length_immediate" "0,1")
(set_attr "mode" "")]
:}
-
define expand
Syntax:
CONCRETE name.exp (INSTANTIATES|OVERRIDES) name{.insn|.exp} {
statements
}
{:
cmd_spec
:}
MD Construct:
(define_expand "cbranchxf4"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:XF 1 "nonmemory_operand" "")
(match_operand:XF 2 "nonmemory_operand" "")))
(set (pc) (if_then_else
(match_operator 0 "ix86_fp_comparison_operator"
[(reg:CC FLAGS_REG)
(const_int 0)])
(label_ref (match_operand 3 "" ""))
(pc)))]
"TARGET_80387"
{
ix86_expand_branch (GET_CODE (operands[0]),
operands[1], operands[2], operands[3]);
DONE;
})
Corresponding specRTL Pattern:
concrete cbranchxf4.exp instantiates
set_compare_set_if_then_else_match_operator_label_ref
{
root(reg(CC:FLAGS_REG),1=nonmemory_operand:XF:"",
2=nonmemory_operand:XF:"",pc,(0=ix86_fp_comparison_operator,
reg(CC:FLAGS_REG),const_int:0),3=NULL:NULL:"",pc);
root.1.2.mode:=CC;
}
{:
"TARGET_80387"
{
ix86_expand_branch (GET_CODE (operands[0]),
operands[1], operands[2], operands[3]);
DONE;
}
:}
-
define insn and split
Syntax:
concrete name.insn_and_split instantiates.in name {
statements
}
cmd_spec.in
{:
cmd_spec
:}
instantiates.out name {
statements
}
cmd_spec.out
{:
cmd_spec
:}
MD Construct:
(define_insn_and_split "*cmpfp_0_cc"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP
(match_operand 1 "register_operand" "f")
(match_operand 2 "const0_operand" "")))
(clobber (match_operand:HI 0 "register_operand" "=a"))]
"X87_FLOAT_MODE_P (GET_MODE (operands[1]))
&& TARGET_SAHF && !TARGET_CMOVE
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
"#"
"&& reload_completed"
[(set (match_dup 0)
(unspec:HI
[(compare:CCFP (match_dup 1)(match_dup 2))]
UNSPEC_FNSTSW))
(set (reg:CC FLAGS_REG)
(unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
""
[(set_attr "type" "multi")
(set_attr "unit" "i387")
(set (attr "mode")
(cond [(match_operand:SF 1 "" "")
(const_string "SF")
(match_operand:DF 1 "" "")
(const_string "DF")]
(const_string "XF")))])
Corresponding specRTL Pattern:
concrete *cmpfp_0_cc.insn_and_split instantiates.in set_compare_clobber
{
root (reg(CCFP:FLAGS_REG),1=register_operand:NULL:"f",2=const0_operand:NULL:"",
0=register_operand:H
:}
instantiates.out set_unspec_compare_set_unspec
{
root (duplicate 0,(duplicate 1, duplicate 2,),reg(CC:FLAGS_REG),
(duplicate 0,= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno));
}
Corresponding specRTL patterns:
concrete small_addr_symbolic_operand.predicate extends and
{
root (match_code:"symbol_ref", match_test:"SYMBOL_REF_SMALL_ADDR_P (op)");
}
concrete gr_register_operand.predicate extends sequence
{
root (0=register_operand);
}
{:
unsigned int regno;
if (GET_CODE (op) == SUBREG)
op= SUREG_REG (op);
regno = REGNO (op);
return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno));
:}
-
define_split
e.g. MD Construct:
(define_split
[(set (match_operand:TI 0 "push_operand" "")
(match_operand:TI 1 "general_operand" ""))]
"TARGET_64BIT && reload_completed
&& !SSE_REG_P (operands[1])"
[(const_int 0)]
"ix86_split_long_move (operands); DONE;")
Corresponding specRTL Pattern:
concrete .split instantiates.in set
{
root (0=push_operand:TI:"",1=general_operand:TI:"");
}
cmd_spec.in
{:
"TARGET_64BIT && reload_completed
&& !SSE_REG_P (operands[1])"
:}
instantiates.out sequence
{
root (const_int:0);
}
cmd_spec.out
{:
"ix86_split_long_move (operands); DONE;"
:}
-
define_peephole2
e.g.
MD Construct:
(define_peephole2
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode) && 1"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 2) (match_dup 3))]
{
split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
GEN_INT (4)));
})
Corresponding specRTL pattern:
concrete .peep2 instantiates.in sequence_set
{
root (2=DI:"r",0=push_operand:DI:"",1=immediate_operand:DI:"");
}
cmd_spec.in
{:
"TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
:}
instantiates.out set_set
{
root (duplicate 2,duplicate 1,duplicate 0,duplicate 2);
}
-
define_predicates
e.g. MD Constructs:
(define_predicate "small_addr_symbolic_operand"
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_SMALL_ADDR_P (op)")))
(define_predicate "gr_register_operand"
(match_operand 0 "register_operand")
{
unsigned int regno;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
regno = REGNO (op);
return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno));
})
Corresponding specRTL patterns:
concrete small_addr_symbolic_operand.predicate extends and
{
root (match_code:"symbol_ref", match_test:"SYMBOL_REF_SMALL_ADDR_P (op)");
}
concrete gr_register_operand.predicate extends sequence
{
root (0=register_operand);
}
{:
unsigned int regno;
if (GET_CODE (op) == SUBREG)
op= SUREG_REG (op);
regno = REGNO (op);
return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno));
:}
-
define special predicates
Syntax:
concrete name.specialPredicate instantiates name
{
statements
}
{:
cmd_spec
:}
MD Constructs :
(define_special_predicate "lea_address_operand"
(match_operand 0 "address_operand")
{
struct ix86_address parts;
int ok;
ok = ix86_decompose_address (op, &parts);
gcc_assert (ok);
return parts.seg == SEG_DEFAULT;
})
Corresponding specRTL pattern:
concrete lea_address_operand.specialPredicate instantiates sequence
{
root (0=address_operand);
}
{:
struct ix86_address parts;
int ok;
ok = ix86_decompose_address (op, &parts);
gcc_assert (ok);
return parts.seg == SEG_DEFAULT;
:}
-
define constraints
Syntax:
concrete name.cons instantiates name {
statements
}
This is a group of MD Constructs consisting of:
- define constraint MD Constructs:
(define_constraint "z"
"@internal Constant call address operand."
(match_operand 0 "constant_call_address_operand"))
(define_constraint "w"
"@internal Call memory operand."
(and (not (match_test "TARGET_X32"))
(match_operand 0 "memory_operand")))
Corresponding specRTL Patterns:
concrete z.cons instantiates sequence {
docstring:="@internal Constant call address operand.";
root (0=constant_call_address_operand);
}
concrete w.cons instantiates and_not1 {
docstring:="@internal Call memory operand.";
root (match_test:"TARGET_X32", 0=memory_operand);
}
-
define memory constraint
- define address constraint The syntax of above two constrain is similar
to that of define constraint except the pattern identifier.
concrete name.addrCons & concrete name.memCons for define memory constraint
and define address constraints respectively.
-
define register constraint
Syntax:
concrete name.regCons
{
statements
}
MD Constructs:
(define_register_constraint "R" "LEGACY_REGS"
"Legacy register---the eight integer registers available on all
i386 processors (@code{a}, @code{b}, @code{c}, @code{d},
@code{si}, @code{di}, @code{bp}, @code{sp}).")
Corresponding specRTL Patterns:
concrete R.regCons
{
docstring:="Legacy register";
regclass := "LEGACY_REGS
}
-
define attr
Syntax:
concrete name.attr instantiates name
{
statements
}
MD Constructs:
(define_attr "type" "load,store,arith,fp,branch" (const_string "arith"))
(define_attr "cc" "clobber,unchanged,set,change0"
(cond [(eq_attr "type" "load")
(const_string "change0")
(eq_attr "type" "store,branch")
(const_string "unchanged")
(eq_attr "type" "arith")
(if_then_else (match_operand:SI 0 "" "")
(const_string "set")
(const_string "clobber"))]
(const_string "clobber")))
-
define_insn_reservation
MD Constructs:
concrete k6_alux_only.insn_reserv instantiates and_and
{
root (cpu:"k6", type:"ishift", memory:"load");
latency:=4;
}
{:
"athlon-vector,((athlon-load,athlon-ieu0*6)+(athlon-fpsched,athlon-fvector))"
:}
Corresponding specRTL Pattern:
(define_insn_reservation "k6_alux_only" 4
[(and (match_scratch: 0 "k6") (and (match_scratch: 0 "ishift") (match_scratch: 0 "load") ) )
"athlon-vector,((athlon-load,athlon-ieu0*6)+(athlon-fpsched,athlon-fvector))"
)
-
List Patterns
The GCC instruction scheduler uses a pipeline hazard recognizer to figure out
the possibility of the instruction issue by the processor on a given simulated
processor cycle. The pipeline hazard recognizer is automatically generated
from the processor pipeline description. The pipeline hazard recognizer
generated from the machine description is based on a deterministic finite state
automaton (DFA): the instruction issue is possible if there is a transition
from one automaton state to another one. This algorithm is very fast, and
furthermore, its speed is not dependent on processor complexity.This section
constitutes an automaton-based processor pipeline description.
-
define_automaton
The following optional construction describes names of automata generated and
used for the pipeline hazards recognition. Sometimes the generated finite state
automaton used by the pipeline hazard recognizer is large. If we use more than
one automaton and bind functional units to the automata, the total size of the
automata is usually less than the size of the single automaton. If there is no
one such construction, only one finite state automaton is generated.
md construct
(define_automaton automata-names)
automata-names: String giving names of the automata. The names are separated
by commas. All the automata should have unique names. The automaton name is used
in the constructions define_cpu_unit and define_query_cpu_unit.
specRTL construct
LIST automata-names.AUTOMATA
-
define_cpu_unit
Each processor functional unit used in the description of instruction reservations
md construct
(define_cpu_unit unit_names [automaton-names])
unit_names: String giving the names of the functional units separated by commas.
specRTL construct
LIST unit_names.CPU_UNIT automaton-names
-
define_reservations
Sometimes unit reservations for different insns contain common parts. In such case,
you can simplify the pipeline description by describing the common part by the
following construction
md construct:
(define_reservation reservation-name regexp)
reservation-name is a string giving name of regexp. Functional unit names and
reservation names are in the same name space. So the reservation names should be
different from the functional unit names and can not be the reserved name 'nothing'.
specRTL construct
LIST reservation-name.reserve regexp
-
define_constants
Using literal constants inside instruction patterns reduces legibility and can
be a maintenance problem.
To overcome this problem, you may use the define_constants expression. It
contains a vector of name-value pairs. From that point on, wherever any of the
names appears in the MD file, it is as if the corresponding value had been.
Example:
(define_insn ""
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "gpc_reg_operand" "=r")
(match_operand:SI 2 "memory_operand" "m"))
(use (reg:SI 179))
(clobber (reg:SI 179))])]
""
"loadm 0,0,%1,%2")
register 179 can be replaced by more meaningful name
(define_constants [
(R_BP 177)
(R_FC 178)
(R_CR 179)
(R_Q 180)
])
(define_insn ""
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "gpc_reg_operand" "=r")
(match_operand:SI 2 "memory_operand" "m"))
(use (reg:SI R_CR))
(clobber (reg:SI R_CR))])]
""
"loadm 0,0,%1,%2")
md construct
(define_constant [(alias1 value1) (alias2 value2) ....])
specRTL construct
LIST NONAME.CONSTANTS [(alias1,value1)(alias2,value2)..]
-
define_enum
Like the constants defined by define_constant, these enumerations are
visible to both the machine description file and the main C code.
md construct
(define_enum [value1 value2 value3...])
specRTL construct
LIST NONAME.ENUM [value1,value2,value3]
-
Iterators
Ports often need to define similar patterns for more than one machine mode
or for more than one rtx code. GCC provides some simple iterator facilities
to make this process.
-
Mode Iterator
md construct
(define_mode_iterator name [(mode1 "cond1") ... (moden "condn")])
specRTL construct:
LIST name.MODE_ITER [(mode1,"cond1")....]
-
Code Iterator
md construct
(define_code_iterator name [(mode1 "cond1") ... (moden "condn")])
specRTL construct
LIST name.CODE_ITER [(mode1,"cond1")....]
-
Patterns are divided into three types. Abstract Patterns, Concrete Patters and List Patterns. CMD_SPEC is also
regarded as a Pattern so long as the Grammar is Concerned. This CMD_SPEC is required for the comments
for traditional machine descriptions.
Error detection in the input file is done at the pattern level. Only 1 error per pattern can be displayed.
Pattern_List : Pattern_List Pattern
| Pattern
/* Only one error per pattern */
| error '}'
;
Patterns: Abstract_Pattern
| Concrete_Pattern
| List_Pattern
| CMD_SPEC_BODY
;
-
Abstract Pattern Grammar
Abstract_Pattern : ABSTRACT Abstract_Pattern_Name Abstract_Rtl_Spec
;
Abstract_Pattern_Name : ID
;
Abstract_Rtl_Spec : EXTENDS Base_Name '{' Abstract_Extends_Body '}'
| OVERRIDES Base_Name '{' Abstract_Overrides_Body '}'
;
Abstract_Extends_Body : Abstract_Extends_Body Stmt
| Stmt
;
Abstract_Overrides_Body : ID {
}
;
-
Concrete Pattern Grammar
Concrete_Pattern : CONCRETE Concrete_Pattern_Name_Qualifier Concrete_Rtl_Spec
| CONCRETE Concrete_Pattern_Name_Qualifier_C Concrete_Rtl_Spec_C
| CONCRETE Concrete_Pattern_Name_Qualifier_S Concrete_Rtl_Spec_S
| CONCRETE Concrete_Pattern_Name_List '.' REG_CONS '{' Concrete_Inst_Stmt_List '}'
;
Concrete_Pattern_Name_Qualifier_S : Concrete_Pattern_Name_List '.' CONS
| Concrete_Pattern_Name_List '.' ATTR
| Concrete_Pattern_Name_List '.' MEM_CONS
| Concrete_Pattern_Name_List '.' ADD_CONS
;
Concrete_Pattern_Name_Qualifier : Concrete_Pattern_Name_List '.' ID
;
Concrete_Pattern_Name_Qualifier_C : '.' ID
| Concrete_Pattern_Name_List '.' INSN_AND_SPLIT
;
Concrete_Rtl_Spec_S : INSTANTIATES Concrete_Pattern_Name_List Concrete_Instantiates_Body
;
Concrete_Rtl_Spec : INSTANTIATES Concrete_Pattern_Name_List Concrete_Instantiates_Body CMD_SPEC_BODY
| OVERRIDES Concrete_Pattern_Name_List '.' ID Concrete_Overrides_Body CMD_SPEC_BODY
;
Concrete_Rtl_Spec_C : INSTANTIATES '.' IN Concrete_Pattern_Name_List Concrete_Instantiates_Body_C
| OVERRIDES '.' IN Concrete_Pattern_Name_List Concrete_Instantiates_Body_C
;
Concrete_Instantiates_Body_C : Concrete_Instantiates_Body CMD_SPEC '.' IN CMD_SPEC_BODY
Concrete_Instantiates_Body_C2
;
Concrete_Instantiates_Body_C2 : INSTANTIATES '.' OUT Concrete_Pattern_Name_List
Concrete_Instantiates_Body_Out CMD_SPEC '.' OUT CMD_SPEC_BODY
| INSTANTIATES '.' OUT Concrete_Pattern_Name_List Concrete_Instantiates_Body_Out
| OVERRIDES '.' OUT Concrete_Pattern_Name_List Concrete_Overrides_Body_Out CMD_SPEC '.' OUT CMD_SPEC_BODY
;
Concrete_Instantiates_Body : '{' Concrete_Instantiates_Body_Inner '}'
;
Concrete_Overrides_Body : '{' Concrete_Overrides_Body_Inner '}'
;
Concrete_Instantiates_Body_Inner : ROOT '(' Operands ')' ';' Concrete_Inst_Stmt_List
| ROOT '(' Operands ')' ';'
| Concrete_Inst_Stmt_List
;
Quoted_Id_List : Quoted_Id_List ',' Quoted_Id
| Quoted_Id
;
Concrete_Overrides_Body_Inner : Concrete_Inst_Stmt_List
;
Concrete_Instantiates_Body_Out : '{' Concrete_Instantiates_Body_Inner_Out '}'
;
Concrete_Overrides_Body_Out : '{' Concrete_Overrides_Body_Inner_Out '}'
;
Concrete_Instantiates_Body_Inner_Out : ROOT '(' Operands ')' ';' Concrete_Inst_Stmt_List
| ROOT '(' Operands ')' ';'
;
Concrete_Overrides_Body_Inner_Out : Concrete_Inst_Stmt_List
;
Concrete_Inst_Stmt_List: Concrete_Inst_Stmt_List Mode_Stmt
| Mode_Stmt
;
-
Statements Grammar
Stmt : ROOT Operand_Access ASSIGN Pattern_Name ';'
;
Mode_Stmt : ROOT Attr_Access ASSIGN Predicate_Or_Mode ';'
| ROOT Attr_Access ASSIGN Quoted_Id ';'
| ROOT Attr_Access ASSIGN '<' Predicate_Or_Mode '>' ';'
| ROOT Attr_Access ASSIGN CONST_INT ':' INT ';'
| ROOT Attr_Access ASSIGN ID '(' ID ':' FIXED_REG ')' ';'
| ROOT Operand_Access ASSIGN Predicate_Or_Mode_List ':' Predicate_Or_Mode_List ':' Quoted_Id ';'
| ROOT Operand_Access ASSIGN INT '=' Predicate_Or_Mode_List ':' Predicate_Or_Mode_List ':' Quoted_Id ';'
| LATENCY ASSIGN INT ';'
| LOV ASSIGN Quoted_Id ';'
| DOCSTRING ASSIGN Quoted_Id ';'
| REGCLASS ASSIGN Quoted_Id ';'
| ALLCONSTRAINTS ASSIGN '(' Quoted_Id_List ')' ';'
| ID '-' '>' ID ';'
;
-
Operands Grammar
Attr_Access : '.' ID
| Operand_Access '.' ID
;
Operand_Access : Operand_Access '.' INT
| '.' INT
;
Operands : Operands ',' '(' Operands ')'
| Operands ',' Operand
| Operand
;
Operand : Predicate_Or_Mode_List ':' Predicate_Or_Mode_List ':' Constraint
| INT '=' Predicate_Or_Mode_List ':' Predicate_Or_Mode_List ':' Constraint
| DUPLICATE INT
| Predicate_Or_Mode_List ':' Constraint
| ATTR ':' Constraint
| INT '=' Predicate_Or_Mode_List ':' Constraint
| INT '=' Predicate_Or_Mode_List
| INT
| Fixed_Reg_Or_Const
;
Fixed_Reg_Or_Const : ID '(' Predicate_Or_Mode_List ':' FIXED_REG ')'
| ID '(' Predicate_Or_Mode_List ':' INT ')'
| FIXED_REG
| ID
| CONST_INT ':' INT
| CONST_INT ':' INT ':' ID
| '<' INT '>'
| '<' ID '>'
;
Constraint : Quoted_Id;
Predicate_Or_Mode_List : Predicate_Or_Mode_List Predicate_Or_Mode_With_Brackets
| Predicate_Or_Mode_List Predicate_Or_Mode
| Predicate_Or_Mode_With_Brackets
| Predicate_Or_Mode
;
Predicate_Or_Mode_With_Brackets: '<' Predicate_Or_Mode '>'
;
Predicate_Or_Mode : INT
| ID
;
Quoted_Id : QUOTED_ID ;
-
Pattern Name Grammar
Concrete_Pattern_Name_List : Concrete_Pattern_Name_List Concrete_Pattern_Name_With_Brackets
| Concrete_Pattern_Name_List Concrete_Pattern_Name
| Concrete_Pattern_Name_With_Brackets
| Concrete_Pattern_Name
;
Concrete_Pattern_Name_With_Brackets : '<' Concrete_Pattern_Name '>'
| '<' Concrete_Pattern_Name ':' Concrete_Pattern_Name '>'
;
Concrete_Pattern_Name : ID
| INT
| '*'
| ':'
| '_'
;
Base_Name : ID;
Pattern_Name : ID;
-
List Patterns Grammar
List_Pattern: LIST QUOTED_ID '.' AUTOMATON
| LIST ID '.' C_ENUM OBRACE ListEntries CBRACE
| LIST INT '.' BYPASS QIDList
| LIST QUOTED_ID '.' CPU_UNIT QUOTED_ID
| LIST QUOTED_ID '.' RESERVATION QUOTED_ID
| LIST QUOTED_ID '.' RESERVATION '"' PipedId '"'
| LIST NONAME '.' CONSTANTS OBRACE ListPID CBRACE
| LIST NONAME '.' ASM_ATTR OBRACE ListAsmEntries CBRACE
| LIST ID '.' Code_Mode_Iter OBRACE ListEntries CBRACE
| LIST ID '.' Code_Mode_Attr OBRACE ListQEntries CBRACE
;
Code_Mode_Iter: C_ITER
| M_ITER
;
Code_Mode_Attr: C_ATTR
| M_ATTR
;
ListAsmEntries : ListAsmEntries ',' AsmEntry
| AsmEntry
;
AsmEntry : '(' SET_ATTR ',' Quoted_Id ',' QUOTED_ID ')'
;
ListPID : ListPID ',' '(' IEntryPair ')'
| '(' IEntryPair ')'
;
ListEntries : ListEntries ',' SEntry
| SEntry
|ListEntries ',''(' SQEntryPair ')'
| '(' SQEntryPair ')'
;
ListQEntries : ListQEntries ',''(' SQEntryPair ')'
| ListQEntries ',' SEntry
| '(' SQEntryPair ')'
| SEntry
;
SQEntryPair : ID ',' Quoted_Id;
IEntryPair : Id_Reg ',' ID
| Id_Reg ',' INT
| Id_Reg',' INT ID
;
Id_Reg: ID
| FIXED_REG
;
QIDList : QUOTED_ID
| QIDList QUOTED_ID
;
SEntry : ID;
PipedId : ID PIPE PipedId
| '(' PipedId ')'
| ID PLUS PipedId
| ID
| QUOTED_ID
| ID ',' PipedId
;
-
|