⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fold-const.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
      *hquo = *hrem = 0;      *lquo = lnum / lden;	/* rounds toward zero since positive args */      goto finish_up;    }  if (hnum == 0)    {				/* trivial case: dividend < divisor */      /* hden != 0 already checked.  */      *hquo = *lquo = 0;      *hrem = hnum;      *lrem = lnum;      goto finish_up;    }  bzero (quo, sizeof quo);  bzero (num, sizeof num);	/* to zero 9th element */  bzero (den, sizeof den);  encode (num, lnum, hnum);   encode (den, lden, hden);  /* This code requires more than just hden == 0.     We also have to require that we don't need more than three bytes     to hold CARRY.  If we ever did need four bytes to hold it, we     would lose part of it when computing WORK on the next round.  */  if (hden == 0 && ((lden << 8) >> 8) == lden)    {				/* simpler algorithm */      /* hnum != 0 already checked.  */      for (i = 7; i >= 0; i--)	{	  work = num[i] + (carry << 8);	  quo[i] = work / lden;	  carry = work % lden;	}    }  else {			/* full double precision,				   with thanks to Don Knuth's				   "Semi-Numericial Algorithms".  */#define BASE 256    int quo_est, scale, num_hi_sig, den_hi_sig, quo_hi_sig;    /* Find the highest non-zero divisor digit.  */    for (i = 7; ; i--)      if (den[i] != 0) {	den_hi_sig = i;	break;      }    for (i = 7; ; i--)      if (num[i] != 0) {	num_hi_sig = i;	break;      }    quo_hi_sig = num_hi_sig - den_hi_sig + 1;    /* Insure that the first digit of the divisor is at least BASE/2.       This is required by the quotient digit estimation algorithm.  */    scale = BASE / (den[den_hi_sig] + 1);    if (scale > 1) {		/* scale divisor and dividend */      carry = 0;      for (i = 0; i <= 8; i++) {	work = (num[i] * scale) + carry;	num[i] = work & 0xff;	carry = work >> 8;	if (num[i] != 0) num_hi_sig = i;      }      carry = 0;      for (i = 0; i <= 7; i++) {	work = (den[i] * scale) + carry;	den[i] = work & 0xff;	carry = work >> 8;	if (den[i] != 0) den_hi_sig = i;      }    }    /* Main loop */    for (i = quo_hi_sig; i > 0; i--) {      /* quess the next quotient digit, quo_est, by dividing the first	 two remaining dividend digits by the high order quotient digit.	 quo_est is never low and is at most 2 high.  */      int num_hi;		/* index of highest remaining dividend digit */      num_hi = i + den_hi_sig;      work = (num[num_hi] * BASE) + (num_hi > 0 ? num[num_hi - 1] : 0);      if (num[num_hi] != den[den_hi_sig]) {	quo_est = work / den[den_hi_sig];      }      else {	quo_est = BASE - 1;      }      /* refine quo_est so it's usually correct, and at most one high.   */      while ((den[den_hi_sig - 1] * quo_est)	     > (((work - (quo_est * den[den_hi_sig])) * BASE)		 + ((num_hi - 1) > 0 ? num[num_hi - 2] : 0)))	quo_est--;      /* Try QUO_EST as the quotient digit, by multiplying the         divisor by QUO_EST and subtracting from the remaining dividend.	 Keep in mind that QUO_EST is the I - 1st digit.  */      carry = 0;      for (j = 0; j <= den_hi_sig; j++)	{	  int digit;	  work = num[i + j - 1] - (quo_est * den[j]) + carry;	  digit = work & 0xff;	  carry = work >> 8;	  if (digit < 0)	    {	      digit += BASE;	      carry--;	    }	  num[i + j - 1] = digit;	}      /* if quo_est was high by one, then num[i] went negative and	 we need to correct things.  */      if (num[num_hi] < 0)	{	  quo_est--;	  carry = 0;		/* add divisor back in */	  for (j = 0; j <= den_hi_sig; j++)	    {	      work = num[i + j - 1] + den[j] + carry;	      if (work > BASE)		{		  work -= BASE;		  carry = 1;		}	      else		{		  carry = 0;		}	      num[i + j - 1] = work;	    }	  num [num_hi] += carry;	}      /* store the quotient digit.  */      quo[i - 1] = quo_est;    }  }  decode (quo, lquo, hquo); finish_up:  /* if result is negative, make it so.  */  if (quo_neg)    neg_double (*lquo, *hquo, lquo, hquo);  /* compute trial remainder:  rem = num - (quo * den)  */  mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);  neg_double (*lrem, *hrem, lrem, hrem);  add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);  switch (code)    {    case TRUNC_DIV_EXPR:    case TRUNC_MOD_EXPR:	/* round toward zero */    case EXACT_DIV_EXPR:	/* for this one, it shouldn't matter */      return;    case FLOOR_DIV_EXPR:    case FLOOR_MOD_EXPR:	/* round toward negative infinity */      if (quo_neg && (*lrem != 0 || *hrem != 0))   /* ratio < 0 && rem != 0 */	{	  /* quo = quo - 1;  */	  add_double (*lquo, *hquo, -1, -1, lquo, hquo);	}      else return;      break;    case CEIL_DIV_EXPR:    case CEIL_MOD_EXPR:		/* round toward positive infinity */      if (!quo_neg && (*lrem != 0 || *hrem != 0))  /* ratio > 0 && rem != 0 */	{	  add_double (*lquo, *hquo, 1, 0, lquo, hquo);	}      else return;      break;        case ROUND_DIV_EXPR:    case ROUND_MOD_EXPR:	/* round to closest integer */      {	int labs_rem = *lrem, habs_rem = *hrem;	int labs_den = lden, habs_den = hden, ltwice, htwice;	/* get absolute values */	if (*hrem < 0) neg_double (*lrem, *hrem, &labs_rem, &habs_rem);	if (hden < 0) neg_double (lden, hden, &labs_den, &habs_den);	/* if (2 * abs (lrem) >= abs (lden)) */	mul_double (2, 0, labs_rem, habs_rem, &ltwice, &htwice);	if (((unsigned) habs_den < (unsigned) htwice)	    || (((unsigned) habs_den == (unsigned) htwice)		&& ((unsigned) labs_den < (unsigned) ltwice)))	  {	    if (*hquo < 0)	      /* quo = quo - 1;  */	      add_double (*lquo, *hquo, -1, -1, lquo, hquo);	    else	      /* quo = quo + 1; */	      add_double (*lquo, *hquo, 1, 0, lquo, hquo);	  }	else return;      }      break;    default:      abort ();    }  /* compute true remainder:  rem = num - (quo * den)  */  mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);  neg_double (*lrem, *hrem, lrem, hrem);  add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);}/* Split a tree IN into a constant and a variable part   that could be combined with CODE to make IN.   CODE must be a commutative arithmetic operation.   Store the constant part into *CONP and the variable in &VARP.   Return 1 if this was done; zero means the tree IN did not decompose   this way.   If CODE is PLUS_EXPR we also split trees that use MINUS_EXPR.   Therefore, we must tell the caller whether the variable part   was subtracted.  We do this by storing 1 or -1 into *VARSIGNP.   The value stored is the coefficient for the variable term.   The constant term we return should always be added;   we negate it if necessary.  */static intsplit_tree (in, code, varp, conp, varsignp)     tree in;     enum tree_code code;     tree *varp, *conp;     int *varsignp;{  register tree outtype = TREE_TYPE (in);  *varp = 0;  *conp = 0;  /* Strip any conversions that don't change the machine mode.  */  while ((TREE_CODE (in) == NOP_EXPR	  || TREE_CODE (in) == CONVERT_EXPR)	 && (TYPE_MODE (TREE_TYPE (in))	     == TYPE_MODE (TREE_TYPE (TREE_OPERAND (in, 0)))))    in = TREE_OPERAND (in, 0);  if (TREE_CODE (in) == code      || (TREE_CODE (TREE_TYPE (in)) != REAL_TYPE	  /* We can associate addition and subtraction together	     (even though the C standard doesn't say so)	     for integers because the value is not affected.	     For reals, the value might be affected, so we can't.  */	  &&	  ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR)	   || (code == MINUS_EXPR && TREE_CODE (in) == PLUS_EXPR))))    {      enum tree_code code = TREE_CODE (TREE_OPERAND (in, 0));      if (code == INTEGER_CST)	{	  *conp = TREE_OPERAND (in, 0);	  *varp = TREE_OPERAND (in, 1);	  if (TREE_TYPE (*varp) != outtype)	    *varp = convert (outtype, *varp);	  *varsignp = (TREE_CODE (in) == MINUS_EXPR) ? -1 : 1;	  return 1;	}      if (TREE_LITERAL (TREE_OPERAND (in, 1)))	{	  *conp = TREE_OPERAND (in, 1);	  *varp = TREE_OPERAND (in, 0);	  *varsignp = 1;	  if (TREE_TYPE (*varp) != outtype)	    *varp = convert (outtype, *varp);	  if (TREE_CODE (in) == MINUS_EXPR)	    {	      /* If operation is subtraction and constant is second,		 must negate it to get an additive constant.		 And this cannot be done unless it is a manifest constant.		 It could also be the address of a static variable.		 We cannot negate that, so give up.  */	      if (TREE_CODE (*conp) == INTEGER_CST)		*conp = fold (build (NEGATE_EXPR, TREE_TYPE (*conp), *conp));	      else		return 0;	    }	  return 1;	}      if (TREE_LITERAL (TREE_OPERAND (in, 0)))	{	  *conp = TREE_OPERAND (in, 0);	  *varp = TREE_OPERAND (in, 1);	  if (TREE_TYPE (*varp) != outtype)	    *varp = convert (outtype, *varp);	  *varsignp = (TREE_CODE (in) == MINUS_EXPR) ? -1 : 1;	  return 1;	}    }  return 0;}/* Combine two constants NUM and ARG2 under operation CODE   to produce a new constant.   We assume ARG1 and ARG2 have the same data type,   or at least are the same kind of constant and the same machine mode.  *//* Handle floating overflow for `combine'.  */static jmp_buf combine_error;treecombine (code, arg1, arg2)     enum tree_code code;     register tree arg1, arg2;{  if (TREE_CODE (arg1) == INTEGER_CST)    {      register int int1l = TREE_INT_CST_LOW (arg1);      register int int1h = TREE_INT_CST_HIGH (arg1);      int int2l = TREE_INT_CST_LOW (arg2);      int int2h = TREE_INT_CST_HIGH (arg2);      int low, hi;      int garbagel, garbageh;      register tree t;      int uns = TREE_UNSIGNED (TREE_TYPE (arg1));      switch (code)	{	case BIT_IOR_EXPR:	  t = build_int_2 (int1l | int2l, int1h | int2h);	  break;	case BIT_XOR_EXPR:	  t = build_int_2 (int1l ^ int2l, int1h ^ int2h);	  break;	case BIT_AND_EXPR:	  t = build_int_2 (int1l & int2l, int1h & int2h);	  break;	case BIT_ANDTC_EXPR:	  t = build_int_2 (int1l & ~int2l, int1h & ~int2h);	  break;	case RSHIFT_EXPR:	  int2l = - int2l;	case LSHIFT_EXPR:	  lshift_double (int1l, int1h, int2l,			 TYPE_PRECISION (TREE_TYPE (arg1)),			 &low, &hi,			 !uns);	  t = build_int_2 (low, hi);	  break;	case RROTATE_EXPR:	  int2l = - int2l;	case LROTATE_EXPR:	  lrotate_double (int1l, int1h, int2l,			  TYPE_PRECISION (TREE_TYPE (arg1)),			  &low, &hi);	  t = build_int_2 (low, hi);	  break;	case PLUS_EXPR:	  if (int1h == 0)	    {	      int2l += int1l;	      if ((unsigned) int2l < int1l)		int2h += 1;	      t = build_int_2 (int2l, int2h);	      break;	    }	  if (int2h == 0)	    {	      int1l += int2l;	      if ((unsigned) int1l < int2l)		int1h += 1;	      t = build_int_2 (int1l, int1h);	      break;	    }	  add_double (int1l, int1h, int2l, int2h, &low, &hi);	  t = build_int_2 (low, hi);	  break;	case MINUS_EXPR:	  if (int1h == 0 && int1l == 0)	    {	      t = build_int_2 (- int2l, - int2h - (int2l != 0));	      break;	    }	  if (int2h == 0 && int2l == 0)	    {	      t = build_int_2 (int1l, int1h);	      break;	    }	  neg_double (int2l, int2h, &int2l, &int2h);	  add_double (int1l, int1h, int2l, int2h, &low, &hi);	  t = build_int_2 (low, hi);	  break;	case MULT_EXPR:  /* Optimize simple cases.  */	  if (int1h == 0)	    {	      unsigned temp;	      switch (int1l)		{		case 0:		  t = build_int_2 (0, 0);		  goto got_it;		case 1:		  t = build_int_2 (int2l, int2h);		  goto got_it;		case 2:		  temp = int2l + int2l;		  int2h = int2h * 2 + (temp < int2l);		  t = build_int_2 (temp, int2h);		  goto got_it;#if 0 /* This code can lose carries.  */		case 3:		  temp = int2l + int2l + int2l;		  int2h = int2h * 3 + (temp < int2l);		  t = build_int_2 (temp, int2h);		  goto got_it;#endif		case 4:		  temp = int2l + int2l;		  int2h = int2h * 4 + (temp < int2l) << 1;		  int2l = temp;		  temp += temp;		  int2h += (temp < int2l);		  t = build_int_2 (temp, int2h);		  goto got_it;		case 8:		  temp = int2l + int2l;		  int2h = int2h * 8 + (temp < int2l) << 2;		  int2l = temp;		  temp += temp;		  int2h += (temp < int2l) << 1;		  int2l = temp;		  temp += temp;		  int2h += (temp < int2l);		  t = build_int_2 (temp, int2h);		  goto got_it;		default:		  break;		}	    }	  if (int2h == 0)	    {	      if (int2l == 0)		{		  t = build_int_2 (0, 0);		  break;		}	      if (int2l == 1)		{		  t = build_int_2 (int1l, int1h);		  break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -