GCC's bacl-end & assemble emission (3)

    技术2022-05-20  41

    2.2. Output condition part of instruction defining patterns

    Following genconditions will generate array insn_conditions which contains conditional test part of instrucitons description patterns. This array will be used to help optimizing the generation of backend functionalities, as we will see in later sections.

     

    main (continued, genconditions)

     

    199    /* Read the machine description.  */

    200 

    201    while (1)

    202    {

    203      desc = read_md_rtx (&pattern_lineno, &code);

    204      if (desc == NULL)

    205        break ;

    206 

    207       /* N.B. define_insn_and_split, define_cond_exec are handled

    208         entirely within read_md_rtx; we never see them.  */

    209      switch (GET_CODE (desc))

    210      {

    211        default :

    212           break ;

    213 

    214        case DEFINE_INSN:

    215        case DEFINE_EXPAND:

    216            add_condition (XSTR (desc, 2));

    217            /* except.h needs to know whether there is an eh_return

    218               pattern in the machine description.  */

    219            if (!strcmp (XSTR (desc, 0), "eh_return"))

    220               saw_eh_return = 1;

    221            break ;

    222 

    223        case DEFINE_SPLIT:

    224        case DEFINE_PEEPHOLE:

    225        case DEFINE_PEEPHOLE2:

    226              add_condition (XSTR (desc, 1));

    227             break ;

    228      }

    229    }

    230 

    231    write_header ();

    232    write_conditions ();

    233 

    234    fflush (stdout);

    235    return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);

    236  }

     

    Here, at line 203, read_md_rtx nearly does nothing, as insn_elision_unavailable is 1 – we just creating it. read_md_rtx just returns rtx object from define_attr_queue , define_insn_queue , or other_queue accordingly.

     

    52    static void

    53    add_condition (const char *expr)                                                          in genconditions.c

    54    {

    55      struct c_test *test;

    56   

    57      if (expr[0] == 0)

    58        return ;

    59   

    60      test = xmalloc (sizeof (struct c_test));

    61      test->expr = expr;

    62   

    63      *(htab_find_slot (condition_table , test, INSERT)) = test;

    64    }

     

    All patterns will be put into hash table of condition_table via funciton add_condition . Pay attention to the parameter passed to add_condition , it is the condition part of the pattern. At line 231, write_header just outputs the constant part of the output file.

     

    163  static void

    164  write_conditions (void)                                                                              in genconditions.c

    165  {

    166    puts ("/

    167  /* This table lists each condition found in the machine description./n/

    168     Each condition is mapped to its truth value (0 or 1), or -1 if that/n/

    169     cannot be calculated at compile time. *//n/

    170  /n/

    171  const struct c_test insn_conditions[] = {");

    172 

    173    htab_traverse (condition_table , write_one_condition , 0);

    174 

    175    puts ("};/n");

    176 

    177    printf ("const size_t n_insn_conditions = %lu;/n",

    178           (unsigned long) htab_elements (condition_table ));

    179    puts ("const int insn_elision_unavailable = 0;");

    180  }

     

    Above, at line 173, htab_traverse will invoke write_one_condition for every member in the condition_table . Here the function constructs the array of insn_conditions . And notice that at line 179, when creating insn-recog.c, maybe_eval_c_test will do the evaluation as now insn_elision_unavailable is zero.

     

    140  static int

    141  write_one_condition (void **slot, void *dummy ATTRIBUTE_UNUSED)       in genconditions.c

    142  {

    143    const struct c_test *test = * (const struct c_test **) slot;

    144    const char *p;

    145 

    146    fputs ("  { /"", stdout);

    147    for (p = test->expr; *p; p++)

    148    {

    149      if (*p == '/n')

    150        fputs ("//n///n", stdout);

    151      else if (*p == '"')

    152        fputs ("///"", stdout);

    153      else

    154        putchar (*p);

    155    }

    156 

    157    printf ("/",/n    MAYBE_EVAL (%s) },/n", test->expr);

    158    return 1;

    159  }

     

    Above at line 157, MAYBE_EVAL has definition as below. It also appears in the generated file insn-conditions.c (output by write_header ).

     

    #if (GCC_VERSION >= 3001) || ((GCC_VERSION == 3000) && !__OPTIMIZE__)

    # define MAYBE_EVAL(expr) (__builtin_constant_p(expr) ? (int) (expr) : -1)

    #else

    # define MAYBE_EVAL(expr) -1

    #endif

     

    __builtin_constant_p is the builtin function provided by GCC after release V3.0.1, it returns 1 if the expr is constant known at the time of compilation, otherwise returns 0. So MAYBE_EVAL returns the value of expression if it is constant; or -1 if it is not. This macro is used heavily with insn-conditions for other tools as we see later. It does helpful to reduce the size of generated code and save the processing time as the tools can skip those patterns known unmatched during handling at certain point of time.

     


    最新回复(0)