GCC后端及汇编发布(31)

9.6.1.3.    属性的优化

一些属性包含复杂的表达式作为其值。使用i386.md文件中的一个例子,“length_immediate”属性的定义如下" 。

 

189  (define_attr "length_immediate"""

190   (cond [(eq_attr "type""incdec,setcc,icmov,str,cld,lea,other,multi,idiv,leave")

191            (const_int 0)

192         (eq_attr "unit" "i387,sse,mmx")

193            (const_int 0)

194         (eq_attr "type""alu,alu1,negnot,imovx,ishift,rotate,ishift1,rotate1,

195                         imul,icmp,push,pop")

196            (symbol_ref"ix86_attr_length_immediate_default(insn,1)")

197         (eq_attr "type" "imov,test")

198            (symbol_ref"ix86_attr_length_immediate_default(insn,0)")

199         (eq_attr "type" "call")

200            (if_then_else (match_operand 0"constant_call_address_operand" "")

201              (const_int 4)

202              (const_int 0))

203         (eq_attr "type" "callv")

204            (if_then_else (match_operand 1"constant_call_address_operand" "")

205              (const_int 4)

206              (const_int 0))

207         ;; We don't know the size before shorten_branches. Expect

208         ;; the instruction to fit for better scheduling.

209         (eq_attr "type" "ibr")

210            (const_int 1)

211         ]

212         (symbol_ref "/* Update immediate_length and other attributes! */

213                      abort(),1")))

 

190行到213行是用于该属性缺省值的表达式。从这个原始形式为所关联的指令产生get_attr_length_immediate是困难的。不过,因为缺省值将被用于没有显式声明这个属性值的指令中,并且该指令,在任何时候,都必须为每个属性采取值列表中的一个值。而当选定了一个指令,必须通过其define_insn模式中的条件测试。即确定了绝大多数属性的值。因此,最好把这些属性值应用到这个表达式来得到最简化的形式,并为该指令保存这个简化的表达式。这就是所谓的属性优化的目的。

不过记住,现在这个属性的rtx对象并不是我们在上面看到的。主要的1在于所有的IF_THEN_ELSE对象被重构为COND对象(参见get_attr_value,及调用的make_canonical)。

 

3624 static void

3625 optimize_attrs (void)                                                                          in genattrtab.c

3626 {

3627  struct attr_desc*attr;

3628   struct attr_value*av;

3629   struct insn_ent*ie;

3630   rtx newexp;

3631   int i;

3632   structattr_value_list

3633   {

3634     struct attr_value *av;

3635     struct insn_ent*ie;

3636     struct attr_desc*attr;

3637     structattr_value_list *next;

3638   };

3639   structattr_value_list **insn_code_values;

3640   structattr_value_list *ivbuf;

3641   structattr_value_list *iv;

3642

3643   /* For each insncode, make a list of all the insn_ent's for it,

3644     for all values for all attributes.  */

3645

3646   if (num_insn_ents == 0)

3647     return;

3648

3649   /* Make 2 extraelements, for "code" values -2 and -1.  */

3650  insn_code_values = xcalloc ((insn_code_number + 2),

3651                           sizeof (structattr_value_list *));

3652

3653   /* Offset the tableaddress so we can index by -2 or -1.  */

3654   insn_code_values += 2;

3655

3656   iv = ivbuf = xmalloc (num_insn_ents * sizeof (structattr_value_list));

3657

3658   for (i = 0; i < MAX_ATTRS_INDEX; i++)

3659     for (attr =attrs[i];attr; attr = attr->next)

3660       for (av =attr->first_value; av; av = av->next)

3661         for (ie =av->first_insn; ie; ie = ie->next)

3662        {

3663          iv->attr = attr;

3664          iv->av = av;

3665          iv->ie = ie;

3666          iv->next = insn_code_values[ie->insn_code];

3667          insn_code_values[ie->insn_code] = iv;

3668           iv++;

3669         }

3670

3671   /* Sanity check onnum_insn_ents.  */

3672   if (iv != ivbuf + num_insn_ents)

3673     abort ();

3674

3675   /* Process one insncode at a time.  */

3676   for (i = -2; i < insn_code_number; i++)

3677   {

3678     /* Clear theATTR_CURR_SIMPLIFIED_P flag everywhere relevant.

3679       We use it to mean "alreadysimplified for this insn".  */

3680     for (iv =insn_code_values[i]; iv; iv = iv->next)

3681       clear_struct_flag (iv->av->value);

3682

3683     for (iv =insn_code_values[i]; iv; iv = iv->next)

3684     {

3685       structobstack *old = rtl_obstack;

3686

3687       attr = iv->attr;

3688       av = iv->av;

3689       ie= iv->ie;

3690       if (GET_CODE (av->value) != COND)

3691         continue;

3692

3693       rtl_obstack = temp_obstack;

3694       newexp = av->value;

3695       while(GET_CODE (newexp) == COND)

3696       {

3697         rtx newexp2 = simplify_cond (newexp, ie->insn_code,

3698                                 ie->insn_index);

3699         if (newexp2 == newexp)

3700           break;

3701         newexp = newexp2;

3702       }

3703

3704       rtl_obstack = old;

3705       if (newexp != av->value)

3706       {

3707         newexp = attr_copy_rtx (newexp);

3708         remove_insn_ent (av, ie);

3709         av = get_attr_value (newexp, attr, ie->insn_code);

3710         iv->av = av;

3711         insert_insn_ent (av, ie);

3712       }

3713     }

3714   }

3715

3716   free (ivbuf);

3717   free (insn_code_values - 2);

3718 }

 

为了理解在3658行的大FOR循环,参见下面的图形。在这些循环之前,数据的地图如下,所有使用同一个属性的指令构成了一个链表,这个链表保存在属性值的数据对象中(注意缺省值已经被链入value,参见fill_attr)。

图82:属性优化,图1

这个FOR循环组合上图所示的数据。被绿色线所包围的数据形成了一个iv,被红色线所包围的数据形成了下一个iv。这个数据有三个层次,attribute位于最顶层,value在中间,而insn在最底层。组合首先在底层开始,在3个层次上相关的数据被放在一起(同样看到,被绿色线包围的指令必须具有,比红色线包围的指令更小的,指令编码,参见gen_insn以及fill_attr)。

图83:属性优化,图2

注意在3676及3683行的FOR循环中,iv的遍历次序是指令编码的升序。根据指令编码来处理是必要的。这是因为在简化过程中,我们可能得到以下的数据——一个新的属性值被作为对指令的简化结果加入(它看起来不像列表中的其它值,通常的情形是使用缺省值的指令),而这个insn被移到这个值的下面。因此如果我们根据值来处理,这个新的值就会被重复访问——这是重复的工作。

图84:属性优化,图3

对于每个是COND的属性值,simplify_cond用于检查是否可以执行简化。在研究这个函数之前,请回忆COND虽然类似于switch-case语句,其条件测试必须被依次执行。因此,以正确的次序安排这个条件是非常重要的。这是机器描述文件作者的责任。

 

2492 static rtx

2493 simplify_cond (rtx exp, int insn_code,int insn_index)                           ingenattrtab.c

2494 {

2495   int i, j;

2496   /* We store the desired contents here,

2497     then build a new expression if they don'tmatch EXP.  */

2498  rtx defval = XEXP (exp, 1);

2499   rtx new_defval = XEXP (exp, 1);

2500   int len = XVECLEN (exp, 0);

2501   rtx *tests = xmalloc (len * sizeof (rtx));

2502   int allsame = 1;

2503   rtx ret;

2504

2505   /* This lets us free all storage allocatedbelow, if appropriate.  */

2506   obstack_finish (rtl_obstack);

2507

2508   memcpy (tests, XVEC (exp, 0)->elem, len * sizeof (rtx));

2509

2510   /* See if default value needssimplification.  */

2511   if (GET_CODE (defval) == COND)

2512     new_defval = simplify_cond (defval, insn_code, insn_index);

2513

2514   /* Simplify the subexpressions, and see whattests we can get rid of.  */

2515

2516   for (i = 0; i< len; i += 2)

2517   {

2518     rtx newtest, newval;

2519

2520     /* Simplify this test.  */

2521     newtest = simplify_test_exp_in_temp (tests[i], insn_code, insn_index);

2522     tests[i] = newtest;

2523

2524     newval = tests[i + 1];

2525     /* See if this value may needsimplification.  */

2526     if (GET_CODE (newval) == COND)

2527       newval = simplify_cond (newval, insn_code, insn_index);

2528

2529     /* Look for ways to delete or combine thistest.  */

2530     if (newtest == true_rtx)

2531     {

2532       /* If test istrue, make this value the default

2533         and discard this + any followingtests.  */

2534       len = i;

2535       defval = tests[i + 1];

2536       new_defval = newval;

2537     }

2538

2539     else if (newtest == false_rtx)

2540     {

2541       /* If test isfalse, discard it and its value.  */

2542      for (j = i; j < len - 2; j++)

2543         tests[j] = tests[j + 2];

2544       i -= 2;

2545       len -= 2;

2546     }

2547

2548     else if (i > 0 && attr_equal_p(newval, tests[i - 1]))

2549     {

2550       /* If thisvalue and the value for the prev test are the same,

2551         merge the tests.  */

2552

2553       tests[i - 2]

2554          = insert_right_side (IOR, tests[i - 2],newtest,

2555                          insn_code,insn_index);

2556

2557       /* Delete thistest/value.  */

2558      for (j = i; j < len - 2; j++)

2559         tests[j] = tests[j + 2];

2560       len -= 2;

2561       i -= 2;

2562     }

2563

2564     else

2565       tests[i + 1] = newval;

2566   }

 

在2498行的defval,及在2499行的new_default都是感兴趣属性的缺省值的别名。在2508行的tests保存了该COND对象的余下部分,其中用于值的条件测试部分,由在2521行的simplify_test_exp_in_temp处理。注意,在处理过程中,对于遇到的每个COND,递归调用simplify_cond

 

3139 static rtx

3140 simplify_test_exp_in_temp (rtx exp, intinsn_code, int insn_index)        in genattrtab.c

3141 {

3142   rtx x;

3143   structobstack *old;

3144   if (ATTR_IND_SIMPLIFIED_P (exp))

3145     return exp;

3146   old = rtl_obstack;

3147   rtl_obstack = temp_obstack;

3148   x = simplify_test_exp (exp, insn_code,insn_index);

3149   rtl_obstack = old;

3150   if (x == exp || rtl_obstack == temp_obstack)

3151     return x;

3152   returnattr_copy_rtx (x);

3153 }

 

simplify_test_exp_in_temp将间接递归,并且所有运行的simplify_test_exp_in_temp使用同一个栈——temp_obstack。这些函数共享在temp_obstack中的rtx对象,直到顶层的simplify_test_exp_in_temp退出。这时,这个rtx对象一个被拷贝到初始的内存栈(通过attr_copy_rtx)。因此simplify_test_exp在3148开始与temp_obstack一起工作。

 

3304 static rtx

3305 simplify_test_exp (rtx exp, intinsn_code, int insn_index)                       in genattrtab.c

3306 {

3307   rtx left, right;

3308   struct attr_desc*attr;

3309   struct attr_value*av;

3310   structinsn_ent *ie;

3311   int i;

3312   rtx newexp = exp;

3313   bool left_alt, right_alt;

3314

3315  /* Don't re-simplifysomething we already simplified.  */

3316   if (ATTR_IND_SIMPLIFIED_P (exp) ||ATTR_CURR_SIMPLIFIED_P (exp))

3317     return exp;

3318

3319   switch(GET_CODE (exp))

3320   {

3321     case AND:

3322       left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);

3323       SIMPLIFY_ALTERNATIVE (left);

3324       if (left == false_rtx)

3325         return false_rtx;

3326       right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);

3327       SIMPLIFY_ALTERNATIVE (right);

3328       if (left == false_rtx)

3329         return false_rtx;

3330

3331       if (GET_CODE (left) == EQ_ATTR_ALT

3332           && GET_CODE (right) ==EQ_ATTR_ALT)

3333       {

3334         exp = attr_alt_intersection (left, right);

3335         return simplify_test_exp (exp, insn_code, insn_index);

3336       }

3337

3338       /* If eitherside is an IOR and we have (eq_attr "alternative" ..")

3339         present on both sides, apply thedistributive law since this will

3340         yield simplifications.  */

3341       if ((GET_CODE (left) == IOR || GET_CODE(right) == IOR)

3342         && compute_alternative_mask (left, IOR)

3343         && compute_alternative_mask (right, IOR))

3344       {

3345         if (GET_CODE (left) == IOR)

3346         {

3347           rtx tem = left;

3348           left = right;

3349           right = tem;

3350         }

3351

3352         newexp = attr_rtx(IOR,

3353                        attr_rtx(AND, left, XEXP (right, 0)),

3354                        attr_rtx(AND, left, XEXP (right, 1)));

3355

3356         return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);

3357       }

3358

3359       /* Try with theterm on both sides.  */

3360       right = simplify_and_tree (right, &left, insn_code, insn_index);

3361       if (left == XEXP (exp, 0) && right == XEXP (exp,1))

3362         left = simplify_and_tree (left, &right, insn_code, insn_index);

3363

3364       if (left == false_rtx || right == false_rtx)

3365         return false_rtx;

3366       else if (left == true_rtx)

3367       {

3368         returnright;

3369       }

3370       else if (right == true_rtx)

3371       {

3372         returnleft;

3373       }

3374       /* See if allor all but one of the insn's alternatives are specified

3375         in this tree. Optimize if so.  */

3376

3377       if (GET_CODE (left) == NOT)

3378         left_alt = (GET_CODE (XEXP (left,0)) == EQ_ATTR

3379            && XSTR (XEXP (left,0), 0) == alternative_name);

3380       else

3381         left_alt = (GET_CODE (left) ==EQ_ATTR_ALT

3382            && XINT (left, 1));

3383

3384       if (GET_CODE (right) == NOT)

3385         right_alt = (GET_CODE (XEXP (right,0)) == EQ_ATTR

3386            && XSTR (XEXP (right,0), 0) == alternative_name);

3387       else

3388         right_alt = (GET_CODE (right) ==EQ_ATTR_ALT

3389            && XINT (right, 1));

3390

3391       if (insn_code >= 0

3392           && (GET_CODE (left) == AND

3393           || left_alt

3394           || GET_CODE (right) == AND

3395           || right_alt))

3396       {

3397         i = compute_alternative_mask (exp, AND);

3398         if (i & ~insn_alternatives[insn_code])

3399           fatal ("invalid alternativespecified for pattern number %d",

3400               insn_index);

3401

3402         /* If allalternatives are excluded, this is false. */

3403         i ^= insn_alternatives[insn_code];

3404         if (i == 0)

3405           returnfalse_rtx;

3406         else if ((i & (i - 1)) == 0&& insn_alternatives[insn_code]> 1)

3407         {

3408           /* If justone excluded, AND a comparison with that one to the

3409             front of the tree. The others willbe eliminated by

3410             optimization. We do not want to dothis if the insn has one

3411             alternative and we have tested noneof them!  */

3412           left = make_alternative_compare (i);

3413           right = simplify_and_tree (exp, &left, insn_code, insn_index);

3414           newexp = attr_rtx(AND, left, right);

3415

3416           returnSIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);

3417         }

3418       }

3419

3420       if (left != XEXP (exp, 0) || right != XEXP (exp,1))

3421       {

3422         newexp = attr_rtx(AND, left, right);

3423         return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);

3424       }

3425       break;

3426

3427     case IOR:

3428       left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);

3429       SIMPLIFY_ALTERNATIVE (left);

3430       if (left == true_rtx)

3431         return true_rtx;

3432       right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);

3433       SIMPLIFY_ALTERNATIVE (right);

3434       if (right == true_rtx)

3435         return true_rtx;

3436

3437       if (GET_CODE (left) == EQ_ATTR_ALT

3438          && GET_CODE (right) ==EQ_ATTR_ALT)

3439       {

3440         exp = attr_alt_union (left, right);

3441         return simplify_test_exp (exp, insn_code, insn_index);

3442       }

3443

3444       right = simplify_or_tree (right,&left, insn_code, insn_index);

3445       if (left == XEXP (exp, 0) && right == XEXP (exp,1))

3446         left = simplify_or_tree (left,&right, insn_code, insn_index);

3447

3448       if (right == true_rtx || left == true_rtx)

3449         return true_rtx;

3450       else if (left == false_rtx)

3451       {

3452         returnright;

3453       }

3454       else if (right == false_rtx)

3455       {

3456         returnleft;

3457       }

3458

3459       /* Test forsimple cases where the distributive law is useful. I.e.,

3460         convert (ior (and (x) (y))

3461                   (and (x) (z)))

3462         to    (and (x)

3463               (ior (y) (z)))

3464       */

3465

3466       else if (GET_CODE (left) == AND&& GET_CODE (right) == AND

3467              && attr_equal_p (XEXP (left, 0), XEXP (right, 0)))

3468       {

3469         newexp = attr_rtx(IOR, XEXP (left, 1), XEXP (right, 1));

3470

3471         left = XEXP (left, 0);

3472         right = newexp;

3473         newexp = attr_rtx(AND, left, right);

3474         return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);

3475       }

3476

3477       /* See if allor all but one of the insn's alternatives are specified

3478         in this tree. Optimize if so.  */

3479

3480       else if (insn_code >= 0

3481             && (GET_CODE (left) == IOR

3482             || (GET_CODE (left) == EQ_ATTR_ALT

3483               && !XINT (left, 1))

3484             || (GET_CODE (left) == EQ_ATTR

3485               && XSTR (left, 0) == alternative_name)

3486             || GET_CODE (right) == IOR

3487             || (GET_CODE (right) == EQ_ATTR_ALT

3488               && !XINT (right, 1))

3489             || (GET_CODE (right) == EQ_ATTR

3490               && XSTR (right, 0) == alternative_name)))

3491       {

3492         i = compute_alternative_mask (exp,IOR);

3493         if (i & ~insn_alternatives[insn_code])

3494           fatal ("invalid alternativespecified for pattern number %d",

3495                insn_index);

3496

3497         /* If allalternatives are included, this is true. */

3498         i ^= insn_alternatives[insn_code];

3499         if (i == 0)

3500           returntrue_rtx;

3501         else if ((i & (i - 1)) == 0 &&insn_alternatives[insn_code]> 1)

3502         {

3503           /* If justone excluded, IOR a comparison with that one to the

3504             front of the tree. The others willbe eliminated by

3505             optimization. We do not want to dothis if the insn has one

3506             alternative and we have tested noneof them!  */

3507           left = make_alternative_compare (i);

3508           right = simplify_and_tree (exp, &left, insn_code, insn_index);

3509           newexp = attr_rtx(IOR, attr_rtx (NOT, left), right);

3510

3511           returnSIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);

3512         }

3513       }

3514

3515       if (left != XEXP (exp, 0) || right != XEXP (exp,1))

3516       {

3517         newexp = attr_rtx(IOR, left, right);

3518         return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);

3519       }

3520       break;

3521

3522     case NOT:

3523       if (GET_CODE (XEXP (exp, 0)) == NOT)

3524       {

3525         left = SIMPLIFY_TEST_EXP (XEXP (XEXP (exp, 0), 0),

3526                                  insn_code,insn_index);

3527         SIMPLIFY_ALTERNATIVE (left);

3528         return left;

3529          }

3530

3531       left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);

3532       SIMPLIFY_ALTERNATIVE (left);

3533       if (GET_CODE (left) == NOT)

3534         return XEXP (left,0);

3535

3536       if (left == false_rtx)

3537         return true_rtx;

3538       if (left == true_rtx)

3539         return false_rtx;

3540

3541       if (GET_CODE (left) == EQ_ATTR_ALT)

3542       {

3543         exp = attr_alt_complement (left);

3544         return simplify_test_exp (exp, insn_code, insn_index);

3545       }

3546

3547       /* Try to applyDe`Morgan's laws.  */

3548       if (GET_CODE (left) == IOR)

3549       {

3550         newexp = attr_rtx(AND,

3551                        attr_rtx(NOT, XEXP (left, 0)),

3552                        attr_rtx(NOT, XEXP (left, 1)));

3553

3554         newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);

3555       }

3556       else if (GET_CODE (left) == AND)

3557       {

3558         newexp = attr_rtx(IOR,

3559                        attr_rtx(NOT, XEXP (left, 0)),

3560                        attr_rtx(NOT, XEXP (left, 1)));

3561

3562         newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);

3563       }

3564       else if (left != XEXP (exp, 0))

3565       {

3566         newexp = attr_rtx(NOT, left);

3567       }

3568       break;

3569

3570     caseEQ_ATTR_ALT:

3571       if (current_alternative_string)

3572         returnattr_alt_bit_p (exp, atoi (current_alternative_string)) ? true_rtx: false_rtx;

3573

3574       if (!XINT (exp, 0))

3575         return XINT(exp, 1) ? true_rtx: false_rtx;

3576       break;

3577

3578     caseEQ_ATTR:

3579       if (current_alternative_string && XSTR (exp,0) == alternative_name)

3580         return (XSTR(exp, 1) == current_alternative_string

3581                      ? true_rtx : false_rtx);

3582

3583       if (XSTR (exp, 0) == alternative_name)

3584       {

3585         newexp = mk_attr_alt (1 << atoi(XSTR (exp, 1)));

3586         break;

3587       }

3588

3589       /* Look at thevalue for this insn code in the specified attribute.

3590         We normally can replace this comparisonwith the condition that

3591         would give this insn the values beingtested for.  */

3592       if (XSTR (exp, 0) != alternative_name

3593          && (attr = find_attr(&XSTR (exp, 0), 0)) != NULL)

3594         for (av =attr->first_value; av; av = av->next)

3595           for(ie = av->first_insn; ie; ie = ie->next)

3596            if (ie->insn_code == insn_code)

3597             {

3598               rtx x;

3599               x = evaluate_eq_attr (exp, av->value, insn_code, insn_index);

3600               x = SIMPLIFY_TEST_EXP (x, insn_code,insn_index);

3601               if (attr_rtx_cost(x) < 20)

3602                 returnx;

3603            }

3604       break;

3605

3606     default:

3607       break;

3608   }

3609

3610   /* We have alreadysimplified this expression. Simplifying it again

3611     won't buy anything unless we weren't givena valid insn code

3612     to process (i.e., we are canonicalizingsomething.).  */

3613   if (insn_code != -2 /*Seems wrong: && current_alternative_string.  */

3614       && ! ATTR_IND_SIMPLIFIED_P (newexp))

3615     returncopy_rtx_unchanging (newexp);

3616

3617   returnnewexp;

3618 }

 

上面在3322行,宏SIMPLIFY_TEST_EXP具有如下定义。在下面的370行,宏ATTR_CURR_SIMPLIFIED_P访问rtx对象的in_struct域。在这里如果in_struct是1,表示这个rtx对于当前正在处理的指令已经是完全简化的。并且我们知道ATTR_IND_SIMPLIED_P访问unchanging域,其如果是1表示这个rtx是完全不依赖于指令编码简化的。对于两者,不需要尝试简化。

 

369  #define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX)\     in genattrtab.c

370   (ATTR_IND_SIMPLIFIED_P (EXP) || ATTR_CURR_SIMPLIFIED_P (EXP)? (EXP)\

371    : simplify_test_exp (EXP, INSN_CODE, INSN_INDEX))

 

在3323行,宏SIMPLIFY_ALTERNATIVE具有如下定义。在这个定义中,alternative_name是字符串“alternative”,而current_alternative_string在这个版本中没有使用。它总是0。因此它事实上是空的。

 

375  #define SIMPLIFY_ALTERNATIVE(EXP) \                                         ingenattrtab.c

376   if (current_alternative_string                          \

377       && GET_CODE ((EXP)) == EQ_ATTR                       \

378       && XSTR ((EXP), 0) == alternative_name)                 \

379     (EXP) = (XSTR ((EXP), 1) == current_alternative_string  \

380             ? true_rtx : false_rtx);

 

3328行包含了一个bug,left应该是right。这个bug已经在V4中被修正。

simplify_test_exp的3331行,可能在check_attr_test的943行构建EQ_ATTR_ALT。,其第一个孩子保存了值(1<<alternativenumber),它将被用作一个位图。对于由在check_attr_test中的mk_attr_alt构建的EQ_ATTR_ATL对象,其第二个孩子总是0。

simplify_test_exp对COND对象的条件测试执行前序遍历。为了能清楚地看到它如何工作,假定我们有如下例子。对应某个值的属性条件的rtx对象在图85的左侧(记住我们现在在一个COND对象中,我们正在一个类似swtch-case的跳转中)。对于第一步, simplify_test_exp递归到左侧子树的底部,处理EQ_ATTR_ATL节点。从3574行,由mk_attr_alt创建的EQ_ATTR_ATL在其第一个孩子中将不包含0, 因此EQ_ATTR_ATL对象返回自己,如图形右侧所示。

在3615行,对于每个访问的节点,其in_struct域将被设置,并将不会被下面的simplify_test_exp所处理。

图85:优化属性,步骤1



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值