在下一步,同样的,对应NOT子树的EQ_ATTR_ATL的底部节点,在3322行把自身作为left返回。
图86:优化属性,步骤2
对于NOT内部右侧的孩子IOR,在3585行构建一个新的EQ_ATTR_ATL,并在3326行作为rigth返回。
图87:优化属性,步骤3
现在作为第四步,在NOT节点中的IOR节点具有EQ_ATTR_ATL,作为其left及right的结果,在3334行,调用attr_alt_intersection来构建新的EQ_ATTR_ATL。
图88:优化属性,步骤4
3204 static rtx
3205 attr_alt_intersection (rtx s1, rtx s2) in genattrtab.c
3206 {
3207 rtx result = rtx_alloc (EQ_ATTR_ALT);
3208
3209 switch ((XINT (s1, 1)<< 1) | XINT (s2, 1))
3210 {
3211 case (0<< 1) | 0:
3212 XINT (result, 0) = XINT (s1, 0) & XINT (s2, 0);
3213 break;
3214 case (0<< 1) | 1:
3215 XINT (result, 0) = XINT (s1, 0) & ~XINT (s2, 0);
3216 break;
3217 case (1<< 1) | 0:
3218 XINT (result, 0) = XINT (s2, 0) & ~XINT (s1, 0);
3219 break;
3220 case (1<< 1) | 1:
3221 XINT (result, 0) = XINT (s1, 0) | XINT (s2, 0);
3222 break;
3223 default:
3224 abort ();
3225 }
3226 XINT (result, 1) = XINT (s1, 1) & XINT (s2, 1);
3227
3228 returnresult;
3229 }
这个EQ_ATTR_ATL在上面3211行构建的。这个节点在3525行作为left返回。参见下图中的这个EQ_ATTR_ATL对象。
图89:优化属性,步骤5
在3543行,attr_alt_complement被调用来为这个NOT操作构建新的EQ_ATTR_ATL。
3262 static rtx
3263 attr_alt_complement (rtx s) in genattrtab.c
3264 {
3265 rtx result = rtx_alloc (EQ_ATTR_ALT);
3266
3267 XINT (result, 0) = XINT (s, 0);
3268 XINT (result, 1) = 1 - XINT (s, 1);
3269
3270 returnresult;
3271 }
在NOT把这个EQ_ATTR_ATL返回给下图的IOR后,在3334行,为这个OR操作调用attr_alt_intersection。这次,注意到由NOT返回的EQ_ATTR_ATL,其第二个孩子是1,在3214行构建新的EQ_ATTR_ATL。
图90:优化属性,步骤6
类似的,在第六步,根节点AND的右分枝的左侧底部的EQ_ATTR_ATL,把自己返回给父节点,如下图所示。
图91:优化属性,步骤7
因为其兄弟是EQ_ATTR,而不是“alternative”,在simplify_test_exp 的3599行,调用evaluate_eq_attr来做处理。注意3594及3595行的FOR循环,因为我们已经把所有指令按所使用的属性值链接在一起,很容易找出这个指令是否使用这个属性值。
下面在evaluate_eq_attr中,参数exp是EQ_ATTR的rtx对象,它来自我们试图在optimize_attrs中简化的COND表达式,参数value是编码为insn_code的指令(参见simplify_test_exp的3594~3596行)所使用的属性值。在evaluate_eq_attr中,我们可以看到应用了已知的,该指令所使用的,属性值之后,exp的结果是什么。
2768 static rtx
2769 evaluate_eq_attr (rtx exp, rtx value,int insn_code, int insn_index) in genattrtab.c
2770 {
2771 rtx orexp, andexp;
2772 rtx right;
2773 rtx newexp;
2774 int i;
2775
2776 if (GET_CODE (value) == CONST_STRING)
2777 {
2778 if (! strcmp_check (XSTR (value, 0), XSTR(exp, 1)))
2779 newexp = true_rtx;
2780 else
2781 newexp = false_rtx;
2782 }
2783 else if (GET_CODE (value) == SYMBOL_REF)
2784 {
2785 char *p;
2786 char string[256];
2787
2788 if (GET_CODE (exp) != EQ_ATTR)
2789 abort ();
2790
2791 if (strlen (XSTR (exp, 0)) + strlen (XSTR(exp, 1)) + 2 > 256)
2792 abort ();
2793
2794 strcpy (string, XSTR (exp, 0));
2795 strcat (string, "_");
2796 strcat (string, XSTR (exp, 1));
2797 for (p =string; *p; p++)
2798 *p = TOUPPER (*p);
2799
2800 newexp = attr_rtx(EQ, value,
2801 attr_rtx(SYMBOL_REF,
2802 DEF_ATTR_STRING (string)));
2803 }
2804 else if (GET_CODE (value) == COND)
2805 {
2806 /* We constructan IOR of all the cases for which the requested attribute
2807 value is present. Since we start withFALSE, if it is not present,
2808 FALSE will be returned.
2809
2810 Each case is the AND of the NOT's of theprevious conditions with the
2811 current condition; in the default casethe current condition is TRUE.
2812
2813 For each possible COND value, callourselves recursively.
2814
2815 The extra TRUE and FALSE expressions willbe eliminated by another
2816 call to the simplification routine. */
2817
2818 orexp = false_rtx;
2819 andexp = true_rtx;
2820
2821 if (current_alternative_string)
2822 clear_struct_flag (value);
2823
2824 for (i = 0; i < XVECLEN (value, 0); i += 2)
2825 {
2826 rtx this = simplify_test_exp_in_temp (XVECEXP (value, 0, i),
2827 insn_code,insn_index);
2828
2829 SIMPLIFY_ALTERNATIVE (this);
2830
2831 right = insert_right_side (AND, andexp, this,
2832 insn_code,insn_index);
2833 right = insert_right_side (AND, right,
2834 evaluate_eq_attr (exp,
2835 XVECEXP(value, 0,
2836 i + 1),
2837 insn_code, insn_index),
2838 insn_code,insn_index);
2839 orexp = insert_right_side (IOR, orexp, right,
2840 insn_code,insn_index);
2841
2842 /* Add thiscondition into the AND expression. */
2843 newexp = attr_rtx(NOT, this);
2844 andexp = insert_right_side (AND, andexp, newexp,
2845 insn_code,insn_index);
2846 }
2847
2848 /* Handle the default case. */
2849 right= insert_right_side (AND, andexp,
2850 evaluate_eq_attr (exp, XEXP (value, 1),
2851 insn_code,insn_index),
2852 insn_code, insn_index);
2853 newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
2854 }
2855 else
2856 abort ();
2857
2858 /* If uses anaddress, must return original expression. But set the
2859 ATTR_IND_SIMPLIFIED_P bit so we don't tryto simplify it again. */
2860
2861 address_used = 0;
2862 walk_attr_value (newexp);
2863
2864 if (address_used)
2865 {
2866 /* This had`&& current_alternative_string', which seems to be wrong. */
2867 if (! ATTR_IND_SIMPLIFIED_P (exp))
2868 returncopy_rtx_unchanging (exp);
2869 return exp;
2870 }
2871 else
2872 returnnewexp;
2873 }
对于COND的value,我们知道其偶数序号孩子是条件测试,奇数序号孩子是属性值。因此在这里,为这些测试,我们递归调用simplify_test_exp,而为这些值,递归调用evaluate_eq_attr。其净效果是把COND对象转换为,我们可以再次通过simplify_test_exp及evaluate_eq_attr处理的,IOR/AND树。
为了更清楚地看这个函数,假定有以下的例子(其中cond*_s代表经过简化的cond*, val*_e代表经过评估的val*):
图92:COND优化属性值的简化
该变换是恒等的。上图右手侧新构建的表达式,由3600行的simplify_test_exp处理。我们在上面看到的过程将重复。出于简洁的目的,在这个优化属性值的例子中,假定属性“ccc”包含CONST_STRING的值“n4”,该值被这个指令使用。我们可以得到下面的步骤。
图93:优化属性,步骤8
注意在simplify_test_exp的3601,转换后的属性将被attr_rtx_cost评估,来查看是否值得展开整个表达式(看到图92,如果某些值是算术表达式,整个表达式可能不能简化很多,那么我们不希望返回这个大家伙。事实上,这个表达式必须保留在某个属性的值列表中,在这个位置上它将得到简化,并将被扩展入函数get_attr_*。这意味着,如果在为当前属性构建get_attr_*函数的过程中,我们希望得到这个复杂表达式的值,我们可以对这些使用的属性值调用get_attr_*函数)。对于这里我们假设的例子,看到true_rtx是CONST_INT对象(参见main的6009行),并且其rtx编码是‘w’’。attr_rtx_cost的结果是0。
3806 static int
3807 attr_rtx_cost (rtx x) ingenattrtab.c
3808 {
3809 int cost = 0;
3810 enum rtx_code code;
3811 if (!x)
3812 return 0;
3813 code = GET_CODE (x);
3814 switch (code)
3815 {
3816 caseMATCH_OPERAND:
3817 if (XSTR (x, 1)[0])
3818 return 10;
3819 else
3820 return 0;
3821
3822 caseEQ_ATTR_ALT:
3823 return 0;
3824
3825 caseEQ_ATTR:
3826 /* Alternativesdon't result into function call. */
3827 if (!strcmp_check (XSTR (x, 0), alternative_name))
3828 return 0;
3829 else
3830 return 5;
3831 default:
3832 {
3833 int i, j;
3834 const char *fmt =GET_RTX_FORMAT (code);
3835 for (i =GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3836 {
3837 switch(fmt[i])
3838 {
3839 case'V':
3840 case'E':
3841 for(j = 0; j < XVECLEN (x, i); j++)
3842 cost += attr_rtx_cost (XVECEXP (x, i, j));
3843 break;
3844 case'e':
3845 cost += attr_rtx_cost (XEXP (x, i));
3846 break;
3847 }
3848 }
3849 }
3850 break;
3851 }
3852 return cost;
3853 }
然后在下一步,IOR节点在simplify_test_exp的3435行返回true_rtx。
图94:优化属性,步骤9
在simplify_test_exp的3539行,接受了true_rtx,NOT立即返回false_rtx。
图95:优化属性,步骤10
最后,我们得到结果:false_rtx!这意味着这个指令不满足这个条件测试,没有使用该属性值。而如果简化后的条件测试是true_rtx,就意味着关联的值被该指令使用。
图96:优化属性,步骤11
注意2548行及2562行之间,相邻的相同的值,将导致它们的条件通过IOR(逻辑OR操作符)合并,不过这个算法不保证能利用所有的机会。但是还是可以期望它,在绝大多数时间,良好工作。
simplify_cond (continued)
2568 /* If the last test in a COND has the same value
2569 as the default value, that test isn'tneeded. */
2570
2571 while (len> 0 && attr_equal_p (tests[len - 1], new_defval))
2572 len -= 2;
2573
2574 /* See if we changedanything. */
2575 if (len != XVECLEN (exp, 0) || new_defval != XEXP (exp,1))
2576 allsame = 0;
2577 else
2578 for (i = 0;i < len; i++)
2579 if (! attr_equal_p (tests[i], XVECEXP(exp, 0, i)))
2580 {
2581 allsame = 0;
2582 break;
2583 }
2584
2585 if (len == 0)
2586 {
2587 if (GET_CODE (defval) == COND)
2588 ret = simplify_cond (defval, insn_code, insn_index);
2589 else
2590 ret = defval;
2591 }
2592 else if (allsame)
2593 ret = exp;
2594 else
2595 {
2596 rtx newexp = rtx_alloc (COND);
2597
2598 XVEC (newexp, 0) = rtvec_alloc (len);
2599 memcpy (XVEC (newexp, 0)->elem, tests,len * sizeof (rtx));
2600 XEXP (newexp, 1) = new_defval;
2601 ret = newexp;
2602 }
2603 free (tests);
2604 return ret;
2605 }
在simplify_cond剩下的代码中,如果COND最后的测试被发现等于new_defval,在上面2572行移走这个测试(因为测试失败了也是使用缺省值)。在2585行,当len == 0时,似乎有一个bug,在这个情形下,ret应该被赋予2590行的new_defval。