Пример #1
0
void opt_const_unchecked(ENODE **node)
{
	dfs.printf("<OptConst2>");
	opt0(node);
	fold_const(node);
	opt0(node);
	dfs.printf("</OptConst2>");
}
Пример #2
0
//
//      apply all constant optimizations.
//
void opt_const(ENODE **node)
{
    if (opt_noexpr==FALSE) {
    	opt0(node);
    	fold_const(node);
    	opt0(node);
    }
}
Пример #3
0
void opt4(ENODE ** node)
/*
 *      apply all constant optimizations.
 */
{
		opt0(node);
        fold_const2(node);
        opt0(node);
}
Пример #4
0
//
//      apply all constant optimizations.
//
void opt_const(ENODE **node)
{
	dfs.printf("<OptConst>");
    if (opt_noexpr==FALSE) {
    	opt0(node);
    	fold_const(node);
    	opt0(node);
    }
	dfs.printf("</OptConst>");
}
Пример #5
0
/*
 *      opt0 - delete useless expressions and combine constants.
 *
 *      opt0 will delete expressions such as x + 0, x - 0, x * 0,
 *      x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
 *      by node and combine obvious constant operations. It cannot
 *      combine name and label constants but will combine icon type
 *      nodes.
 */
static void opt0(ENODE **node)
{
	ENODE *ep;
  int sc;
	int64_t val;

  ep = *node;
  if( ep == (ENODE *)NULL )
    return;
  switch( (*node)->nodetype ) {
	case en_vector_ref:
	case en_ref32: case en_ref32u:
  case en_b_ref:
	case en_c_ref:
	case en_h_ref:
  case en_w_ref:          /* optimize unary node */
  case en_ub_ref:
	case en_uc_ref:
	case en_uh_ref:
  case en_uw_ref:          /* optimize unary node */
	case en_flt_ref:
	case en_dbl_ref:
	case en_quad_ref:
	case en_wp_ref:
	case en_hp_ref:
	case en_ccwp:
	case en_cucwp:
		opt0(&((*node)->p[0]));
		return;
	case en_cubw:
	case en_cucw:
	case en_cuhw:
	case en_cubu:
	case en_cucu:
	case en_cuhu:
	case en_cbu:
	case en_ccu:
	case en_chu:
	case en_cbc:
	case en_cbh:
	case en_cbw:
	case en_cch:
	case en_ccw:
	case en_chw:
    opt0( &(ep->p[0]));
		if (ep->p[0]->nodetype == en_icon) {
			ep->nodetype = en_icon;
			ep->i = ep->p[0]->i;
		}
    return;
	case en_sxb:
	case en_sxc:
	case en_sxh:
	case en_zxb: case en_zxc: case en_zxh:
	case en_abs:
    opt0( &(ep->p[0]));
    if( ep->p[0]->nodetype == en_icon )
			dooper(*node);
		return;
	case en_compl:
    opt0( &(ep->p[0]));
    if( ep->p[0]->nodetype == en_icon )
    {
      ep->nodetype = en_icon;
      ep->i = ~ep->p[0]->i;
    }
    return;
			case en_not:
                    opt0( &(ep->p[0]));
                    if( ep->p[0]->nodetype == en_icon )
                    {
                        ep->nodetype = en_icon;
                        ep->i = !ep->p[0]->i;
                    }
                    return;
            case en_uminus:
                    opt0( &(ep->p[0]));
                    if( ep->p[0]->nodetype == en_icon )
                    {
                        ep->nodetype = en_icon;
                        ep->i = -ep->p[0]->i;
                    }
                    return;
            case en_tempref:
                    opt0( &(ep->p[0]));
                    if( ep->p[0] && ep->p[0]->nodetype == en_icon )
                    {
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i;
                    }
										else if (ep->constflag) {
											ep->nodetype = en_icon;
										}
                    return;
            case en_tempfpref:
              opt0( &(ep->p[0]));
              if( ep->p[0] && ep->p[0]->nodetype == en_fcon )
              {
                ep->nodetype = en_fcon;
                ep->f = ep->p[0]->f;
								Float128::Assign(&ep->f128,&ep->p[0]->f128);
              }
              return;
			case en_vadd:
			case en_vsub:
            case en_add:
            case en_sub:
              opt0(&(ep->p[0]));
              opt0(&(ep->p[1]));
              if(ep->p[0]->nodetype == en_icon) {
                if(ep->p[1]->nodetype == en_icon) {
                  dooper(*node);
                  return;
                }
                if( ep->p[0]->i == 0 ) {
									if( ep->nodetype == en_sub )
									{
										ep->p[0] = ep->p[1];
										ep->nodetype = en_uminus;
									}
									else
										*node = ep->p[1];
								return;
              }
						// Place the constant node second in the add to allow
						// use of immediate mode instructions.
						if (ep->nodetype==en_add)
							swap_nodes(ep);
                    }
					// Add or subtract of zero gets eliminated.
                    else if( ep->p[1]->nodetype == en_icon ) {
                        if( ep->p[1]->i == 0 ) {
                            *node = ep->p[0];
                            return;
                        }
                    }
                    return;
						case en_ptrdif:
							opt0(&(ep->p[0]));
							opt0(&(ep->p[1]));
							opt0(&(ep->p[4]));
							if (ep->p[0]->nodetype == en_icon) {
								if (ep->p[1]->nodetype == en_icon && ep->p[4]->nodetype == en_icon) {
									dooper(*node);
									return;
								}
							}
							break;
						case en_i2d:
				opt0(&(ep->p[0]));
				if (ep->p[0]->nodetype == en_icon) {
					dooper(*node);
					return;
				}
				break;
			case en_d2i:
				opt0(&(ep->p[0]));
				if (ep->p[0]->nodetype == en_fcon) {
					ep->i = (long)ep->p[0]->f;
					ep->nodetype = en_icon;
					return;
				}
				break;
			case en_fadd:
			case en_fsub:
				opt0(&(ep->p[0]));
				opt0(&(ep->p[1]));
				if (ep->p[0]->nodetype == en_fcon) {
					if (ep->p[1]->nodetype == en_fcon) {
						dooper(*node);
						return;
					}
				}
				break;
			case en_fmul:
				opt0(&(ep->p[0]));
				opt0(&(ep->p[1]));
				if (ep->p[0]->nodetype == en_fcon) {
					if (ep->p[1]->nodetype == en_fcon) {
						dooper(*node);
						return;
					}
					//else if (ep->p[1]->nodetype == en_icon) {
					//	ep->nodetype = en_fcon;
					//	ep->f = ep->p[0]->f * ep->p[1]->i;
					//	return;
					//}
				}
				//else if (ep->p[0]->nodetype == en_icon) {
				//	if (ep->p[1]->nodetype == en_fcon) {
				//		ep->nodetype = en_fcon;
				//		ep->f = ep->p[0]->i * ep->p[1]->f;
				//		return;
				//	}
				//}
				break;
			case en_fdiv:
				opt0(&(ep->p[0]));
				opt0(&(ep->p[1]));
				if (ep->p[0]->nodetype == en_fcon) {
					if (ep->p[1]->nodetype == en_fcon) {
						dooper(*node);
						return;
					}
					//else if (ep->p[1]->nodetype == en_icon) {
					//	ep->nodetype = en_fcon;
					//	ep->f = ep->p[0]->f / ep->p[1]->i;
					//	return;
					//}
				}
				break;
			case en_isnullptr:
				opt0(&(ep->p[0]));
				if (ep->p[0]->nodetype == en_icon)
					dooper(*node);
				return;
			case en_mulf:
				opt0(&(ep->p[0]));
				opt0(&(ep->p[1]));
				if (ep->p[0]->nodetype == en_icon && ep->p[1]->nodetype == en_icon)
					dooper(*node);
				return;
			case en_vmul:
			case en_vmuls:
      case en_mul:
			case en_mulu:
        opt0(&(ep->p[0]));
        opt0(&(ep->p[1]));
        if( ep->p[0]->nodetype == en_icon ) {
            if( ep->p[1]->nodetype == en_icon ) {
                dooper(*node);
                return;
            }
						if (ep->p[1]->nodetype == en_fcon) {
							ep->nodetype = en_icon;
							ep->i = ep->p[0]->i * ep->p[1]->f;
							return;
						}
            val = ep->p[0]->i;
						if( val == 0 ) {
                *node = ep->p[0];
                return;
            }
            if( val == 1 ) {
                *node = ep->p[1];
                return;
            }
            sc = pwrof2(val);
            if( sc != -1 )
            {
                swap_nodes(ep);
                ep->p[1]->i = sc;
                ep->nodetype = en_shl;
								return;
            }
						// Place constant as oper2
						swap_nodes(ep);
          }
          else if( ep->p[1]->nodetype == en_icon ) {
            val = ep->p[1]->i;
            if( val == 0 ) {
              *node = ep->p[1];
              return;
            }
            if( val == 1 ) {
              *node = ep->p[0];
              return;
            }
            sc = pwrof2(val);
            if( sc != -1 )
            {
							ep->p[1]->i = sc;
							ep->nodetype = en_shl;
							return;
            }
          }
          break;
      case en_div:
			case en_udiv:
        opt0(&(ep->p[0]));
        opt0(&(ep->p[1]));
        if( ep->p[0]->nodetype == en_icon ) {
          if( ep->p[1]->nodetype == en_icon ) {
            dooper(*node);
            return;
          }
          if( ep->p[0]->i == 0 ) {    /* 0/x */
						*node = ep->p[0];
						return;
          }
        }
        else if( ep->p[1]->nodetype == en_icon ) {
          val = ep->p[1]->i;
          if( val == 1 ) {        /* x/1 */
            *node = ep->p[0];
            return;
          }
          sc = pwrof2(val);
          if( sc != -1 )
          {
            ep->p[1]->i = sc;
						if ((*node)->nodetype == en_udiv)
							ep->nodetype = en_shru;
						else
							ep->nodetype = ep->p[0]->isUnsigned ? en_shru : en_shr;
          }
        }
        break;
            case en_mod:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[1]->nodetype == en_icon )
                            {
                            if( ep->p[0]->nodetype == en_icon )
                                    {
                                    dooper(*node);
                                    return;
                                    }
                            sc = pwrof2(ep->p[1]->i);
                            if( sc != -1 )
                                    {
                                    ep->p[1]->i = mod_mask(sc);
                                    ep->nodetype = en_and;
                                    }
                            }
                    break;

	case en_and: 
  case en_or:
	case en_xor:    
    opt0(&(ep->p[0]));
    opt0(&(ep->p[1]));
		if (ep->p[0]->nodetype == en_icon &&
			ep->p[1]->nodetype == en_icon)
			dooper(*node);
		else if (ep->p[0]->nodetype == en_icon)
			swap_nodes(ep);
		break;

	case en_shr:	case en_shru:	case en_asr:
	case en_asl:	case en_shl:	case en_shlu:
    opt0(&(ep->p[0]));
    opt0(&(ep->p[1]));
    if( ep->p[0]->nodetype == en_icon &&
      ep->p[1]->nodetype == en_icon )
      dooper(*node);
// Shift by zero....
    else if( ep->p[1]->nodetype == en_icon ) {
      if( ep->p[1]->i == 0 ) {
        *node = ep->p[0];
        return;
      }
    }
    break;

	case en_land_safe:
  case en_land:   
    opt0(&(ep->p[0]));
    opt0(&(ep->p[1]));
		if (ep->p[0]->nodetype==en_icon && ep->p[1]->nodetype==en_icon)
			dooper(*node);
    break;
	case en_lor_safe:
  case en_lor:
    opt0(&(ep->p[0]));
    opt0(&(ep->p[1]));
		if (ep->p[0]->nodetype==en_icon && ep->p[1]->nodetype==en_icon)
			dooper(*node);
    break;

	case en_ult:	case en_ule:
	case en_ugt:	case en_uge:
	case en_lt:		case en_le:
	case en_gt:		case en_ge:
	case en_eq:		case en_ne:
    opt0(&(ep->p[0]));
    opt0(&(ep->p[1]));
		if (ep->p[0]->nodetype==en_icon && ep->p[1]->nodetype==en_icon)
			dooper(*node);
    break;

	case en_feq:
	case en_fne:
	case en_flt:
	case en_fle:
	case en_fgt:
	case en_fge:
		opt0(&(ep->p[0]));
		opt0(&(ep->p[1]));
		if (ep->p[0]->nodetype == en_fcon && ep->p[1]->nodetype == en_fcon)
			dooper(*node);
		break;
                case en_veq:    case en_vne:
                case en_vlt:    case en_vle:
                case en_vgt:    case en_vge:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    break;
								case en_safe_cond:
			case en_cond:
                    opt0(&(ep->p[0]));
					opt0(&(ep->p[1]->p[0]));
					opt0(&(ep->p[1]->p[1]));
					if ((ep->p[0]->nodetype==en_icon||ep->p[0]->nodetype==en_cnacon) &&
						 (ep->p[1]->p[0]->nodetype==en_icon || ep->p[1]->p[0]->nodetype==en_cnacon) &&
						 (ep->p[1]->p[1]->nodetype==en_icon || ep->p[1]->p[1]->nodetype==en_cnacon))
						dooper(*node);
					break;
            case en_chk:
                    opt0(&(ep->p[0]));
					opt0(&(ep->p[1]));
					opt0(&(ep->p[2]));
					break;
            case en_asand:  case en_asor:
            case en_asadd:  case en_assub:
            case en_asmul:  case en_asdiv:
            case en_asmod:  case en_asrsh:
            case en_aslsh:  
            case en_fcall:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    break;
            case en_assign:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    break;
						// en_tempref comes from typecasting
						case en_void:
							opt0(&(ep->p[0]));
							opt0(&(ep->p[1]));
							if (ep->p[0]->nodetype == en_tempref) {
								(*node)->nodetype = ep->p[1]->nodetype;
								*node = ep->p[1];
							}
							break;
	case en_addrof:
		opt0(&(ep->p[0]));
		break;
	case en_list:
		for (ep = ep->p[2]; ep; ep = ep->p[2])
			opt0(&(ep->p[0]));
		break;
	}
}
Пример #6
0
void opt0(ENODE ** node)
/*
 *      opt0 - delete useless expressions and combine constants.
 *
 *      opt0 will delete expressions such as x + 0, x - 0, x * 0,
 *      x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
 *      by node and combine obvious constant operations. It cannot
 *      combine name and label constants but will combine icon type
 *      nodes.
 */
{       ENODE    *ep;
        int             sc,mode,val;
				double dval;
        ep = *node;
        if( ep == 0 )
                return;
        switch( (*node)->nodetype ) {
                case en_b_ref:
                case en_w_ref:          /* optimize unary node */
                case en_ub_ref:
                case en_uw_ref:          /* optimize unary node */
                case en_l_ref:
								case en_ul_ref:
								case en_floatref: case en_doubleref: case en_longdoubleref:
								case en_cb: case en_cub:
								case en_cw: case en_cuw:
								case en_cl: case en_cul:
								case en_cf: case en_cd: case en_cp: case en_bits: case en_cld:
				case en_ainc:
				case en_adec:
				case en_not:
				case en_compl:
                        opt0( &((*node)->v.p[0]));
                        return;
                case en_uminus:
                        opt0( &(ep->v.p[0]));
                        if( isintconst(ep->v.p[0]->nodetype))
                                {
                                ep->nodetype = ep->v.p[0]->nodetype;
                                ep->v.i = -ep->v.p[0]->v.i;
                                }
                        else if( ep->v.p[0]->nodetype == en_rcon || ep->v.p[0]->nodetype == en_fcon || ep->v.p[0]->nodetype == en_lrcon)
                                {
                                ep->nodetype = ep->v.p[0]->nodetype;
                                ep->v.i = -ep->v.p[0]->v.f;
                                }
                        return;
                case en_add:
                case en_sub:
                        opt0(&(ep->v.p[0]));
                        opt0(&(ep->v.p[1]));
												mode = getmode(ep->v.p[0],ep->v.p[1]);
												switch (mode) {
													case 1: case 2: case 3: case 4:
														dooper(node,mode);
														break;
													case 5:
														if (ep->v.p[0]->v.i == 0) {
															if (ep->nodetype == en_sub) {
																*node = makenode(en_uminus,ep->v.p[1],0);
															}
															else *node = ep->v.p[1];
														}
														else dooper(node,mode);
														break;
													case 6:
														if (ep->v.p[0]->v.f == 0) {
															if (ep->nodetype == en_sub) {
																*node = ep->v.p[1];
																ep->v.p[1]->v.f = - ep->v.p[1]->v.f;

															}
															else *node = ep->v.p[1];
														}
														else dooper(node,mode);
														break;
												  case 7:
														if (ep->v.p[1]->v.i == 0) {
															*node = ep->v.p[0];
														}
														else dooper(node,mode);
														break;
													case 8:
														if (ep->v.p[1]->v.f == 0) {
															*node = ep->v.p[0];
														}
														else dooper(node,mode);
														break;
												}
                        return;
                case en_mul:
								case en_umul:
								case en_pmul:
								case en_asmul: case en_asumul:
                        opt0(&(ep->v.p[0]));
                        opt0(&(ep->v.p[1]));
												mode = getmode(ep->v.p[0],ep->v.p[1]);
												switch(mode) {
													case 1: case 2: case 3: case 4:
														dooper(node,mode);
														break;
													case 5:
														if (!floatrecurse(ep->v.p[1])) {
                                sc = pwrof2(ep->v.p[0]->v.i);
                                if( sc != -1 )
                                        {
																				ENODE *temp = ep->v.p[0];
																				ep->v.p[0 ] = ep->v.p[1];
																				ep->v.p[1] = temp;
                                        ep->v.p[1]->v.i = sc;
																				switch(ep->nodetype) {
																					case en_mul:
																						ep->nodetype = en_alsh;
																						break;
																					case en_asmul:
																						ep->nodetype = en_asalsh;
																						break;
																					case en_umul:
																					case en_pmul:
																						ep->nodetype = en_lsh;
																						break;
																					case en_asumul:
																						ep->nodetype = en_aslsh;
																						break;
																				}
																				break;
                                        }
                            }
														val = ep->v.p[0]->v.i;
														if (val == 0)
															*node = ep->v.p[0];
														else if (val == 1)
															*node = ep->v.p[1];
														else if (val == -1)
															*node = makenode(en_uminus,(char *)ep->v.p[1],0);
														else dooper(node,mode);
														break;
													case 6:
														dval = ep->v.p[0]->v.f;
														if (dval == 0)
															*node = ep->v.p[0];
														else if (dval == 1)
															*node = ep->v.p[1];
														else if (dval == -1)
															*node = makenode(en_uminus,(char *)ep->v.p[1],0);
														else dooper(node,mode);
														break;
													case 7:
														if (!floatrecurse(ep->v.p[0])) {
                                sc = pwrof2(ep->v.p[1]->v.i);
                                if( sc != -1 )
                                        {
                                        ep->v.p[1]->v.i = sc;
																				switch(ep->nodetype) {
																					case en_mul:
																						ep->nodetype = en_alsh;
																						break;
																					case en_asmul:
																						ep->nodetype = en_asalsh;
																						break;
																					case en_umul:
																					case en_pmul:
																						ep->nodetype = en_lsh;
																						break;
																					case en_asumul:
																						ep->nodetype = en_aslsh;
																						break;
																				}
																				break;
                                        }
                            }
														val = ep->v.p[1]->v.i;
														if (val == 0)
															*node = ep->v.p[1];
														else if (val == 1)
															*node = ep->v.p[0];
														else if (val == -1)
															*node = makenode(en_uminus,(char *)ep->v.p[0],0);
														else dooper(node,mode);
														break;
													case 8:
														dval = ep->v.p[1]->v.f;
														if (dval == 0)
															*node = ep->v.p[1];
														else if (dval == 1)
															*node = ep->v.p[0];
														else if (dval == -1)
															*node = makenode(en_uminus,(char *)ep->v.p[0],0);
														else dooper(node,mode);
														break;
												}
                        break;
								case en_pdiv:
                case en_div:
								case en_udiv:
								case en_asdiv:
								case en_asudiv:
                        opt0(&(ep->v.p[0]));
                        opt0(&(ep->v.p[1]));
												mode = getmode(ep->v.p[0],ep->v.p[1]);
												switch(mode) {
													case 1:
													case 2:
													case 3:
													case 4: 
														dooper(node,mode);
														break;
													case 5:
														if (ep->v.p[0]->v.i == 0)
															*node = ep->v.p[0];
														else
															dooper(node,mode);
														break;
													case 6:
														if (ep->v.p[0]->v.f == 0)
															*node = ep->v.p[0];
														else
															dooper(node,mode);
														break;
													case 7:
														if (!floatrecurse(ep->v.p[0])) {
                                sc = pwrof2(ep->v.p[1]->v.i);
                                if( sc != -1 )
                                        {
                                        ep->v.p[1]->v.i = sc;
																				switch(ep->nodetype) {
																					case en_div:
																						ep->nodetype = en_arsh;
																						break;
																					case en_asdiv:
																						ep->nodetype = en_asarsh;
																						break;
																					case en_udiv:
																					case en_pdiv:
																						ep->nodetype = en_rsh;
																						break;
																					case en_asudiv:
																						ep->nodetype = en_asrsh;
																						break;
																				}
																				break;
                                        }
                            }
														val = ep->v.p[1]->v.i;
														if (val == 1)
															*node = ep->v.p[0];
														else if (val == -1)
															*node = makenode(en_uminus,(char *)ep->v.p[0],0);
														else dooper(node,mode);
														break;
													case 8:
														dval = ep->v.p[1]->v.f;
														if (dval == 1)
															*node = ep->v.p[0];
														else if (dval == -1)
															*node = makenode(en_uminus,(char *)ep->v.p[0],0);
														else dooper(node,mode);
														break;
												}
                        break;
                case en_mod:
								case en_umod:
								case en_asmod: case en_asumod:
                        opt0(&(ep->v.p[0]));
                        opt0(&(ep->v.p[1]));
												mode = getmode(ep->v.p[0],ep->v.p[1]);
												switch(mode) {
													case 7:
														if (!floatrecurse(ep->v.p[0])) {
                                sc = pwrof2(ep->v.p[1]->v.i);
                                if( sc != -1 )
                                        {
                                        ep->v.p[1]->v.i = mod_mask(sc);
																				if (ep->nodetype == en_asmod || ep->nodetype == en_asumod)
                                        	ep->nodetype = en_asand;
																				else
                                        	ep->nodetype = en_and;
																				break;
                                        }
                                }
													case 1:
													case 2:
													case 3:
													case 4: 
													case 5: case 6: case 8:
														dooper(node,mode);
												}
                        break;
                case en_and:    case en_or:
                case en_xor:    case en_rsh:
                case en_lsh:    case en_arsh: case en_alsh:
                        opt0(&(ep->v.p[0]));
                        opt0(&(ep->v.p[1]));
                        if( isintconst(ep->v.p[0]->nodetype) &&
                                isintconst(ep->v.p[1]->nodetype) )
                                dooper(node,getmode(ep->v.p[0],ep->v.p[1]));
                        break;
                case en_land:   case en_lor:
				case en_lt:		case en_le:
				case en_ugt:	case en_uge: case en_ult: case en_ule:
				case en_gt:		case en_ge:
				case en_eq:		case en_ne:
								case en_asalsh: case en_asarsh:
                case en_asand:  case en_asor:  case en_asxor:
                case en_asadd:  case en_assub:
                case en_asrsh:
                case en_aslsh:  case en_cond:
                case en_fcall:  case en_void: case en_trapcall: case en_intcall:
								case en_pfcall: case en_pfcallb:
                case en_assign: case en_moveblock: case en_stackblock: case en_callblock:
								case en_fcallb: case en_refassign: case en_pcallblock:
                        opt0(&(ep->v.p[0]));
                        opt0(&(ep->v.p[1]));
                        break;
                }
}
Пример #7
0
/*
 *      apply all constant optimizations.
 */
void opt4(struct enode **node)
{
	opt0(node);
	fold_const(node);
	opt0(node);
}
Пример #8
0
/*
 *      opt0 - delete useless expressions and combine constants.
 *
 *      opt0 will delete expressions such as x + 0, x - 0, x * 0,
 *      x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
 *      by node and combine obvious constant operations. It cannot
 *      combine name and label constants but will combine icon type
 *      nodes.
 */
void opt0(ENODE **node)
{
	ENODE *ep;
    __int64 val, sc;

    ep = *node;
    if( ep == NULL )
        return;
    switch( (*node)->nodetype ) {
            case en_b_ref:
			case en_c_ref:
			case en_h_ref:
            case en_w_ref:          /* optimize unary node */
            case en_ub_ref:
			case en_uc_ref:
			case en_uh_ref:
            case en_uw_ref:          /* optimize unary node */
			case en_flt_ref:
			case en_dbl_ref:
			case en_cbc:
			case en_cbh:
			case en_cbw:
			case en_cch:
			case en_ccw:
			case en_chw:
			case en_ainc:
			case en_adec:
			case en_not:
			case en_compl:
                    opt0( &((*node)->p[0]));
                    return;
            case en_uminus:
                    opt0( &(ep->p[0]));
                    if( ep->p[0]->nodetype == en_icon )
                    {
                        ep->nodetype = en_icon;
                        ep->i = -ep->p[0]->i;
                    }
                    return;
            case en_add:
            case en_sub:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon ) {
                        if( ep->p[1]->nodetype == en_icon ) {
                            dooper(node);
                            return;
                        }
                        if( ep->p[0]->i == 0 ) {
							if( ep->nodetype == en_sub )
							{
								ep->p[0] = ep->p[1];
                                ep->nodetype = en_uminus;
							}
							else
								*node = ep->p[1];
								return;
                        }
                    }
                    else if( ep->p[1]->nodetype == en_icon ) {
                        if( ep->p[1]->i == 0 ) {
                            *node = ep->p[0];
                            return;
                        }
                    }
                    return;
            case en_mul:
			case en_mulu:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon ) {
                        if( ep->p[1]->nodetype == en_icon ) {
                            dooper(node);
                            return;
                        }
                        val = ep->p[0]->i;
                        if( val == 0 ) {
                            *node = ep->p[0];
                            return;
                        }
                        if( val == 1 ) {
                            *node = ep->p[1];
                            return;
                        }
                        sc = pwrof2(val);
                        if( sc != -1 )
                        {
                            swap_nodes(ep);
                            ep->p[1]->i = sc;
                            ep->nodetype = en_shl;
                        }
                    }
                    else if( ep->p[1]->nodetype == en_icon ) {
                        val = ep->p[1]->i;
                        if( val == 0 ) {
                            *node = ep->p[1];
                            return;
                        }
                        if( val == 1 ) {
                            *node = ep->p[0];
                            return;
                        }
                        sc = pwrof2(val);
                        if( sc != -1 )
                        {
							ep->p[1]->i = sc;
							ep->nodetype = en_shl;
                        }
                    }
                    break;
            case en_div:
			case en_udiv:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon ) {
                            if( ep->p[1]->nodetype == en_icon ) {
                                    dooper(node);
                                    return;
                                    }
                            if( ep->p[0]->i == 0 ) {    /* 0/x */
                                    *node = ep->p[0];
                                    return;
                                    }
                            }
                    else if( ep->p[1]->nodetype == en_icon ) {
                            val = ep->p[1]->i;
                            if( val == 1 ) {        /* x/1 */
                                    *node = ep->p[0];
                                    return;
                                    }
                            sc = pwrof2(val);
                            if( sc != -1 )
                                    {
                                    ep->p[1]->i = sc;
                                    ep->nodetype = en_shr;
                                    }
                            }
                    break;
            case en_mod:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[1]->nodetype == en_icon )
                            {
                            if( ep->p[0]->nodetype == en_icon )
                                    {
                                    dooper(node);
                                    return;
                                    }
                            sc = pwrof2(ep->p[1]->i);
                            if( sc != -1 )
                                    {
                                    ep->p[1]->i = mod_mask(sc);
                                    ep->nodetype = en_and;
                                    }
                            }
                    break;
            case en_and:    case en_or:
			case en_xor:    case en_shr:	case en_shru:
            case en_shl:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon &&
                            ep->p[1]->nodetype == en_icon )
                            dooper(node);
                    break;
            case en_land:   case en_lor:
			case en_ult:	case en_ule:
			case en_ugt:	case en_uge:
			case en_lt:		case en_le:
			case en_gt:		case en_ge:
			case en_eq:		case en_ne:
            case en_asand:  case en_asor:
            case en_asadd:  case en_assub:
            case en_asmul:  case en_asdiv:
            case en_asmod:  case en_asrsh:
            case en_aslsh:  case en_cond:
            case en_fcall:  case en_void:
            case en_assign:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    break;
            }
}
Пример #9
0
/*
 *      opt0 - delete useless expressions and combine constants.
 *
 *      opt0 will delete expressions such as x + 0, x - 0, x * 0,
 *      x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
 *      by node and combine obvious constant operations. It cannot
 *      combine name and label constants but will combine icon type
 *      nodes.
 */
static void opt0(ENODE **node)
{
	ENODE *ep;
    int64_t val, sc;

    ep = *node;
    if( ep == (ENODE *)NULL )
        return;
    switch( (*node)->nodetype ) {
            case en_b_ref:
			case en_c_ref:
			case en_h_ref:
            case en_w_ref:          /* optimize unary node */
            case en_ub_ref:
			case en_uc_ref:
			case en_uh_ref:
            case en_uw_ref:          /* optimize unary node */
			case en_flt_ref:
			case en_dbl_ref:
			case en_cubw:
			case en_cucw:
			case en_cuhw:
			case en_cubu:
			case en_cucu:
			case en_cuhu:
			case en_cbu:
			case en_ccu:
			case en_chu:
			case en_cbc:
			case en_cbh:
			case en_cbw:
			case en_cch:
			case en_ccw:
			case en_chw:
			case en_ainc:
			case en_adec:
                    opt0( &((*node)->p[0]));
                    return;
			case en_compl:
                    opt0( &(ep->p[0]));
                    if( ep->p[0]->nodetype == en_icon )
                    {
                        ep->nodetype = en_icon;
                        ep->i = ~ep->p[0]->i;
                    }
                    return;
			case en_not:
                    opt0( &(ep->p[0]));
                    if( ep->p[0]->nodetype == en_icon )
                    {
                        ep->nodetype = en_icon;
                        ep->i = !ep->p[0]->i;
                    }
                    return;
            case en_uminus:
                    opt0( &(ep->p[0]));
                    if( ep->p[0]->nodetype == en_icon )
                    {
                        ep->nodetype = en_icon;
                        ep->i = -ep->p[0]->i;
                    }
                    return;
            case en_tempref:
                    opt0( &(ep->p[0]));
                    if( ep->p[0] && ep->p[0]->nodetype == en_icon )
                    {
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i;
                    }
                    return;
            case en_tempfpref:
                    opt0( &(ep->p[0]));
                    if( ep->p[0] && ep->p[0]->nodetype == en_fcon )
                    {
                        ep->nodetype = en_fcon;
                        ep->f = ep->p[0]->f;
                    }
                    return;
            case en_add:
            case en_sub:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon ) {
                        if( ep->p[1]->nodetype == en_icon ) {
                            dooper(node);
                            return;
                        }
                        if( ep->p[0]->i == 0 ) {
							if( ep->nodetype == en_sub )
							{
								ep->p[0] = ep->p[1];
                                ep->nodetype = en_uminus;
							}
							else
								*node = ep->p[1];
								return;
                        }
                    }
                    else if( ep->p[1]->nodetype == en_icon ) {
                        if( ep->p[1]->i == 0 ) {
                            *node = ep->p[0];
                            return;
                        }
                    }
                    return;
            case en_mul:
			case en_mulu:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon ) {
                        if( ep->p[1]->nodetype == en_icon ) {
                            dooper(node);
                            return;
                        }
                        val = ep->p[0]->i;
                        if( val == 0 ) {
                            *node = ep->p[0];
                            return;
                        }
                        if( val == 1 ) {
                            *node = ep->p[1];
                            return;
                        }
                        sc = pwrof2(val);
                        if( sc != -1 )
                        {
                            swap_nodes(ep);
                            ep->p[1]->i = sc;
                            ep->nodetype = en_shl;
                        }
                    }
                    else if( ep->p[1]->nodetype == en_icon ) {
                        val = ep->p[1]->i;
                        if( val == 0 ) {
                            *node = ep->p[1];
                            return;
                        }
                        if( val == 1 ) {
                            *node = ep->p[0];
                            return;
                        }
                        sc = pwrof2(val);
                        if( sc != -1 )
                        {
							ep->p[1]->i = sc;
							ep->nodetype = en_shl;
                        }
                    }
                    break;
            case en_div:
			case en_udiv:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon ) {
                            if( ep->p[1]->nodetype == en_icon ) {
                                    dooper(node);
                                    return;
                                    }
                            if( ep->p[0]->i == 0 ) {    /* 0/x */
                                    *node = ep->p[0];
                                    return;
                                    }
                            }
                    else if( ep->p[1]->nodetype == en_icon ) {
                            val = ep->p[1]->i;
                            if( val == 1 ) {        /* x/1 */
                                    *node = ep->p[0];
                                    return;
                                    }
                            sc = pwrof2(val);
                            if( sc != -1 )
                                    {
                                    ep->p[1]->i = sc;
									if ((*node)->nodetype == en_udiv)
										ep->nodetype = en_shru;
									else
										ep->nodetype = ep->p[0]->isUnsigned ? en_shru : en_shr;
                                    }
                            }
                    break;
            case en_mod:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[1]->nodetype == en_icon )
                            {
                            if( ep->p[0]->nodetype == en_icon )
                                    {
                                    dooper(node);
                                    return;
                                    }
                            sc = pwrof2(ep->p[1]->i);
                            if( sc != -1 )
                                    {
                                    ep->p[1]->i = mod_mask(sc);
                                    ep->nodetype = en_and;
                                    }
                            }
                    break;
            case en_and: 
            case en_or:
			case en_xor:    
			case en_shr:	case en_shru:	case en_asr:
			case en_shl:	case en_shlu:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon &&
                            ep->p[1]->nodetype == en_icon )
                            dooper(node);
                    break;
            case en_land:   
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
					if (ep->p[0]->nodetype==en_icon && ep->p[1]->nodetype==en_icon) {
						dooper(node);
						break;
                    }
                    break;
            case en_lor:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
					if (ep->p[0]->nodetype==en_icon && ep->p[1]->nodetype==en_icon) {
						dooper(node);
						break;
                    }
                    break;
			case en_ult:	case en_ule:
			case en_ugt:	case en_uge:
			case en_lt:		case en_le:
			case en_gt:		case en_ge:
			case en_eq:		case en_ne:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
					if (ep->p[0]->nodetype==en_icon && ep->p[1]->nodetype==en_icon)
						dooper(node);
                    break;
                case en_feq:    case en_fne:
                case en_flt:    case en_fle:
                case en_fgt:    case en_fge:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    break;
			case en_cond:
                    opt0(&(ep->p[0]));
					opt0(&(ep->p[1]->p[0]));
					opt0(&(ep->p[1]->p[1]));
					if ((ep->p[0]->nodetype==en_icon||ep->p[0]->nodetype==en_cnacon) &&
						 (ep->p[1]->p[0]->nodetype==en_icon || ep->p[1]->p[0]->nodetype==en_cnacon) &&
						 (ep->p[1]->p[1]->nodetype==en_icon || ep->p[1]->p[1]->nodetype==en_cnacon))
						dooper(node);
					break;
            case en_chk:
                    opt0(&(ep->p[0]));
					opt0(&(ep->p[1]));
					opt0(&(ep->p[2]));
					break;
            case en_asand:  case en_asor:
            case en_asadd:  case en_assub:
            case en_asmul:  case en_asdiv:
            case en_asmod:  case en_asrsh:
            case en_aslsh:  
            case en_fcall:  case en_void:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    break;
            case en_assign:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    break;
            }
}