GCC后端及汇编发布(10)

4.3. define_split 产生代码

现在回到 main ,在 840 行,这个 define_insn_and_split split 部分 将被通过 gen_split 写出。我们的例子显示如下:

t30

30 genemit - define_insn_and_split 模式的例子 – split 部分

 

550  static void

551  g en_split (rtx split)                                                                                    in genemit.c

552  {

553    int i;

554    int operands;

555    const char *const name =

556      ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");

557    const char *unused;

558    char *used;

559 

560    if (XVEC (split, 0) == 0)

561      fatal ("define_%s (definition %d) lacks a pattern", name,

562            insn_index_number );

563    else if (XVEC (split, 2) == 0)

564      fatal ("define_%s (definition %d) lacks a replacement pattern", name,

565            insn_index_number );

566 

567    /* Find out how many operands this function has.  */

568 

569    max_operand_vec (split, 2);

570    operands = MAX (max_opno , MAX (max_dup_opno , max_scratch_opno )) + 1;

571    unused = (operands == 0 ? " ATTRIBUTE_UNUSED" : "");

572    used = xcalloc (1, operands);

573 

574    /* Output the prototype, function name and argument declarations.  */

575    if (GET_CODE (split) == DEFINE_PEEPHOLE2)

576    {

577      printf ("extern rtx gen_%s_%d (rtx, rtx *);/n",

578          name, insn_code_number );

579      printf ("rtx/ngen_%s_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)/n",

580          name, insn_code_number , unused);

581    }

582    else

583    {

584      printf ("extern rtx gen_split_%d (rtx *);/n", insn_code_number );

585      printf ("rtx/ngen_%s_%d (rtx *operands%s)/n", name, insn_code_number , unused);

586    }

587    printf ("{/n");

 

569 行,因为其第二个参数为 2 max_operand_vec 检查 define_split 模式的第三个孩子的操作数的个数。显然,在 570 行, operands 2 。这里我们假定对于我们的例子 insn_code_number 0 ,因此由上面的代码我们得到如下判断。

 

extern rtx gen_split_0 (rtx *);

rtx

gen_split_0 (rtx *operands)

{

 

gen_split (continued)

 

589    /* Declare all local variables.  */

590    for (i = 0; i < operands; i++)

591      printf ("  rtx operand%d;/n", i);

592    printf ("  rtx _val = 0;/n");

593 

594    if (GET_CODE (split) == DEFINE_PEEPHOLE2)

595      output_peephole2_scratches (split);

596 

597    printf ("  start_sequence ();/n");

598 

599    /* The fourth operand of DEFINE_SPLIT is some code to be executed

600      before the actual construction.  */

601 

602    if (XSTR (split, 3))

603       printf ("%s/n", XSTR (split, 3));

604 

605    /* Output code to copy the arguments back out of `operands'  */

606    for (i = 0; i < operands; i++)

607      printf ("  operand%d = operands[%d];/n", i, i);

 

在执行上面的代码之后,我们将得到如下片段。在 602 行,这个 split 模式的第四个孩子得到处理。

 

extern rtx gen_split_0 (rtx *);

rtx

gen_split_0 (rtx *operands)

{

  rtx operand0;

  rtx operand1;

  rtx_val = 0;

  start_sequence ();

  ix86_optimize_mode_switching = 1;

  operands[2] = assign_386_stack_local (HImode, 1);

  operands[3] = assign_386_stack_local (HImode, 2);

  if (memory_operand (operands[0], VOIDmode))

    emit_insn (gen_fix_truncdi_memory (operands[0], operands[1],

                                   operands[2], operands[3]));

  else

    {

      operands[4] = assign_386_stack_local (DImode, 0);

      emit_insn (gen_fix_truncdi_nomemory (operands[0], operands[1],

                                      operands[2], operands[3],

                                      operands[4]));

    }

  DONE;

  operand0 = operands[0];

  operand1 = operands[1];

 

在上面的代码中, DONE 定义在 main 817 行:“ #define DONE return (_val = get_insns (), end_sequence (), _val)/n/n ”。因此在 DONE 下面的代码将得不到执行。

 

gen_split (continued)

 

609    /* Output code to construct the rtl for the instruction bodies.

610      Use emit_insn to add them to the sequence being accumulated.

611      But don't do this if the user's code has set `no_more' nonzero.  */

612 

613    for (i = 0; i < XVECLEN (split, 2); i++)

614    {

615      rtx next = XVECEXP (split, 2, i);

616      if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)

617         || (GET_CODE (next) == PARALLEL

618           && GET_CODE (XVECEXP (next, 0, 0)) == SET

619           && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)

620         || GET_CODE (next) == RETURN)

621        printf ("  emit_jump_insn (");

622      else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)

623         || GET_CODE (next) == CALL

624         || (GET_CODE (next) == PARALLEL

625           && GET_CODE (XVECEXP (next, 0, 0)) == SET

626           && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)

627         || (GET_CODE (next) == PARALLEL

628            && GET_CODE (XVECEXP (next, 0, 0)) == CALL))

629        printf ("  emit_call_insn (");

630      else if (GET_CODE (next) == CODE_LABEL)

631        printf ("  emit_label (");

632      else if (GET_CODE (next) == MATCH_OPERAND

633         || GET_CODE (next) == MATCH_OPERATOR

634         || GET_CODE (next) == MATCH_PARALLEL

635         || GET_CODE (next) == MATCH_OP_DUP

636         || GET_CODE (next) == MATCH_DUP

637         || GET_CODE (next) == PARALLEL)

638        printf ("  emit (");

639      else

640        printf ("  emit_insn (");

641      gen_exp (next, GET_CODE (split), used);

642      printf (");/n");

643      if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC

644         && GET_CODE (SET_SRC (next)) == LABEL_REF)

645         printf ("  emit_barrier ();");

646    }

647 

648    /* Call `get_insns' to make a list of all the

649      insns emitted within this gen_... function.  */

650 

651    printf ("  _val = get_insns ();/n");

652    printf ("  end_sequence ();/n");

653    printf ("  return _val;/n}/n/n");

654 

655    free (used);

656  }

 

这个 split 模式的第三个孩子是 const_int ,而 gen_exp 641 行被调用来处理它。因此我们最后得到如下的代码。

 

1     extern rtx gen_split_0 (rtx *);

2     rtx

3     gen_split_0 (rtx *operands)

4     {

5       rtx operand0;

6       rtx operand1;

7       rtx_val = 0;

8       start_sequence ();

9       ix86_optimize_mode_switching = 1;

10      operands[2] = assign_386_stack_local (HImode, 1);

11      operands[3] = assign_386_stack_local (HImode, 2);

12      if (memory_operand (operands[0], VOIDmode))

13        emit_insn (gen_fix_truncdi_memory (operands[0], operands[1],

14                                       operands[2], operands[3]));

15      else

16        {

17          operands[4] = assign_386_stack_local (DImode, 0);

18          emit_insn (gen_fix_truncdi_nomemory (operands[0], operands[1],

19                                          operands[2], operands[3],

20                                          operands[4]));

21         }

22      DONE;

23      operand0 = operands[0];

24      operand1 = operands[1];

25      emit insn (const0_rtx);

26      _val = get_insn ();

27      end_sequence ();

28      return _val;

29    }

 

好了,现在我们做完了,不过记得这个模式在其名字的开头有‘ * ’,因此事实上它不会被 genemit 生成进入 insn-emit.c

4.3. define_peephole2 产生代码

至于 define_peephole 的正式解释,参考 概览 关于 define_peephole ,而 define_peephole2 的描述则参考 define_peephole2的概览 。工具 genemit 将为 define_peephole2 模式产生转移( transformation )函数,它将为 recog 相关函数所使用(关于 recog 的细节,参考 genrecog工具 )。

gen_split 也被用于处理 define_peephole2 ,它在 595 行调用。

 

736  static void

737  output_peephole2_scratches (rtx split)                                                          in genemit.c

738  {

739    int i;

740    int insn_nr = 0;

741 

742    printf ("  HARD_REG_SET _regs_allocated;/n");

743    printf ("  CLEAR_HARD_REG_SET (_regs_allocated);/n");

744 

745    for (i = 0; i < XVECLEN (split, 0); i++)

746    {

747      rtx elt = XVECEXP (split, 0, i);

748      if (GET_CODE (elt) == MATCH_SCRATCH)

749      {

750        int last_insn_nr = insn_nr;

751        int cur_insn_nr = insn_nr;

752        int j;

753        for (j = i + 1; j < XVECLEN (split, 0); j++)

754          if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP)

755          {

756            if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0))

757            last_insn_nr = cur_insn_nr;

758          }

759          else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)

760            cur_insn_nr++;

761 

762         printf ("  if ((operands[%d] = peep2_find_free_register (%d, %d, /"%s/", %smode, &_regs_allocated)) == NULL_RTX)/n/

763       return NULL;/n",

764                  XINT (elt, 0),

765                  insn_nr, last_insn_nr,

766                  XSTR (elt, 1),

767                  GET_MODE_NAME (GET_MODE (elt)));

768 

769      }

770      else if (GET_CODE (elt) != MATCH_DUP)

771        insn_nr++;

772    }

773  }

 

这个函数,为模式中的 match_scratch 操作符,产生选择空闲寄存器的代码。输出的一个例子如下。

 

if ((operands[2] = peep2_find_free_register (1, 1, "r", SImode, &_regs_allocated)) == NULL_RTX)

   return NULL;

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值