1. About specRTL

  2. Need For specRTL

  3. The Basis Set

  4. Writing specRTL Machine Descriptions

  5. Using specRTL Compiler

  6. specRTL Projects

  7. specRTL Compiler Architecture

  8. specRTL Construct Specifications

  9. specRTL Grammar

  10. Download the specRTL compiler

specRTL:A Language for Machine Descriptions


  • About specRTL

    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.

  • Need for specRTL

    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:
    1. Abstract Patterns
    2. Concrete Patterns
    3. List Patterns

    1. 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;
                  }
              



    2. 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.
  • The Basis Set

    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_constset_const2set_const_int2
    set_const_fixed2set_const_string2set_const_vector2
    set_symbol_ref2set_label_ref2set_high2
    set_plus2set_ss_plus2set_us_plus2
    set_minus2set_ss_minus2set_us_minus2
    set_plusminus2set_mult2set_ssmult2
    set_usmult2set_ssdiv2set_usdiv2
    set_div2set_udiv2set_mod2
    set_umod2set_smax2set_smin2
    set_smaxmin2set_umax2set_umin2
    set_unsigned_float2set_float2set_neg2
    set_ssneg2set_usneg2set_absneg2
    set_abs2set_sign_extend1set_sign_extend2
    set_sign_extract2set_zero_extract1set_zero_extract2
    set_fe2set_sqrt2set_bswap2
    set_ashift2set_lshiftrt2set_ashiftrt2
    set_any_shiftrt2set_not2set_ior2
    set_and2set_or2set_ao2
    set_xor2set_compare2set_compare
    set_if_then_else2set_if_then_elseset_ite2
    set_match_operator2set_match_operatorset_match_op_dup2
    set_match_op_dupset_eq2set_ne2
    set_lt2set_ltu2set_gt2
    set_gtu2set_ge2set_geu2
    set_le2set_leu2set_mem1
    set_memset_mem2set_srict_low_part1
    set_unspecset_rotate2set_call2
    set_parity2set_truncate2set_sset_truncate2
    set_unset_truncate2set_float_truncate2set_fix2
    set_unsigned_fix2set_vec_merge2set_vec_select2
    set_vec_concat2set_vec_duplicate2set_fma2
    set_unspec_volatile2set_zero_extractset_subreg2
    set_float_truncate2set_zero_extract2set_zero_extend2
    set_vect_merge2set_strict_low_part1set_mem1
    set_unspec2_compareset_unspec_compareset_compare2_minus1
    set_compare_minusset_compare2_plus1set_compare2_neg1
    set_compare2_and1set_compare2_any_or1set_ite2_ne1
    set_zero_extend2_not1set_zero_extend2_ashift1set_zero_extend2_any_shiftrt1
    set_zero_extend2_any_rotate1set_and2_zero_extractset_and2_not1
    set_and2_neg1set_and2_plus1set_and2_plus1_not2
    set_ior2_plus1set_ior2_plus1_not2set_ior2_plus1
    set_vect_merge2_plus1_minus2set_plus2_plus1set_plus2_mult1
    set_match_operator2_eq1set_absneg2_float_extend1set_ao2_zero_extend1
    set_srict_low_part1_and1set_zero_extract2_subreg1set_zero_extract2_plus1
    set_zero_extract2_minus1set_mult2_any_extend2set_zero_extract2_plusminus1
    set_unspec_compare_match_operatorset_zero_extend2_sign_extendset_vec_concat2_float_truncate1
    set_compare2_plusset_compare2_negset_compare_not
    set_compare2_minusset_compare2_andset_compare2_ashift1
    set_zero_extend2_minus1set_zero_extend2_minusset_zero_extend_not
    set_match_op_dup2_and1set_match_operator2_and1set_strict_low_part_and2
    set_zero_extract1_and2set_if_then_else2_ne1set_const_double2
    set_unspec2
  • Writing specRTL Machine Descriptions

    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.

  • Using specRTL Compiler

    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 Projects

    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.
  • specRTL Compiler Architecture

    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.
    1. Known Pattern Names Table.
    2. Pattern Table.

    1. 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.
    2. 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.
  • specRTL Construct Specifications

    1. 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.

    2. 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.
      1. 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" "")]
                  :}
                  
      2. 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;
                     }
                  :}
                  
      3. 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));
            :}
            
      4. 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;"
                :}
            
      5. 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);
                }
            
      6. 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));
                    :}
            
      7. 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;
            :}
            
      8. define constraints
            Syntax:
            
            concrete name.cons instantiates name {
              statements
            }
            
        This is a group of MD Constructs consisting of:
        1. 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);
              }
              
        2. define memory constraint
        3. 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.
        4. 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
              }
            
      9. 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")))
        
        
              
      10. 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))"
                    )
                
    3. 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.
      1. 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
                  
      2. 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
                  
      3. 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 
                  
      4. 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)..]
                  
      5. 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]
                  
    4. 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.
      1. Mode Iterator
        md construct
                    (define_mode_iterator name [(mode1 "cond1") ... (moden "condn")])
                  
        specRTL construct:
                    LIST name.MODE_ITER [(mode1,"cond1")....]
                  
      2. Code Iterator
        md construct
                    (define_code_iterator name [(mode1 "cond1") ... (moden "condn")])
                  
        specRTL construct
                    LIST name.CODE_ITER [(mode1,"cond1")....]
                  
                  
  • specRTL Grammar


    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
                  ;   
      
                
  • Download the specRTL compiler