GCC后端及汇编发布(3)

    技术2022-05-20  48

    2.2. 输出指令定义模式的条件部分

    接着 genconditions 将产生包含指令描述模式的条件测试部分的数组 insn_conditions 。这个数组将被用于协助优化后端功能单元的生成,我们将在后面的章节看到这一点。

     

    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  }

     

    这里,在 203 行, read_md_rtx 几乎不作任何事,因为 insn_elision_unavailable 1 ——仅创建它。 read_md_rtx 仅相应地从 define_attr_queue define_insn_queue other_queue 返回 rtx 对象。

     

    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    }

     

    所有的模式都将被函数 add_condition 加入哈希表 condition_table 。注意传递给 add_condition 的参数,它是模式的条件部分。在 231 行, write_header 输出该输出文件的常量部分。

     

    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  }

     

    上面,在 173 行, htab_traverse 将为每个 condition_table 的成员调用 write_one_condition 。在这里这个函数构建了数组 insn_conditions 。注意到在 179 行,当构建 insn-recog.c 时, maybe_eval_c_test 将执行评估,因为现在 insn_elision_unavailable 0 了。

     

    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  }

     

    上面在 157 行, MAYBE_EVAL 具有如下定义,它同样出现在产生的文件 insn-conditions.c 中(通过 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 GCC 3.0.1 版本之后提供的内建函数,如果 expr 是编译时刻已知的常量,它返回 1 ;否则返回 0 。因此 MAYBE_EVAL ,如果表达式的值是编译时刻可以计算的,就返回这个值,否则返回 -1 。这个宏被 insn-conditions 大量用于其它工具,后面我们可以看到。它确实能帮助减小产生代码的大小,及节省处理时间,因为在处理的某个时间点上,工具可以跳过那些已知不匹配的模式。

     


    最新回复(0)