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

📄 fold-const.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
     HOST_WIDE_INT lnum_orig, hnum_orig; /* num == numerator == dividend */     HOST_WIDE_INT lden_orig, hden_orig; /* den == denominator == divisor */     HOST_WIDE_INT *lquo, *hquo, *lrem, *hrem;{  int quo_neg = 0;  HOST_WIDE_INT num[4 + 1];	/* extra element for scaling.  */  HOST_WIDE_INT den[4], quo[4];  register int i, j;  unsigned HOST_WIDE_INT work;  register unsigned HOST_WIDE_INT carry = 0;  HOST_WIDE_INT lnum = lnum_orig;  HOST_WIDE_INT hnum = hnum_orig;  HOST_WIDE_INT lden = lden_orig;  HOST_WIDE_INT hden = hden_orig;  int overflow = 0;  if ((hden == 0) && (lden == 0))    abort ();  /* calculate quotient sign and convert operands to unsigned.  */  if (!uns)     {      if (hnum < 0)	{	  quo_neg = ~ quo_neg;	  /* (minimum integer) / (-1) is the only overflow case.  */	  if (neg_double (lnum, hnum, &lnum, &hnum) && (lden & hden) == -1)	    overflow = 1;	}      if (hden < 0) 	{	  quo_neg = ~ quo_neg;	  neg_double (lden, hden, &lden, &hden);	}    }  if (hnum == 0 && hden == 0)    {				/* single precision */      *hquo = *hrem = 0;      /* This unsigned division rounds toward zero.  */      *lquo = lnum / (unsigned HOST_WIDE_INT) lden;      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 ((char *) quo, sizeof quo);  bzero ((char *) num, sizeof num);	/* to zero 9th element */  bzero ((char *) den, sizeof den);  encode (num, lnum, hnum);   encode (den, lden, hden);  /* Special code for when the divisor < BASE.  */  if (hden == 0 && lden < BASE)    {      /* hnum != 0 already checked.  */      for (i = 4 - 1; i >= 0; i--)	{	  work = num[i] + carry * BASE;	  quo[i] = work / (unsigned HOST_WIDE_INT) lden;	  carry = work % (unsigned HOST_WIDE_INT) lden;	}    }  else    {      /* Full double precision division,	 with thanks to Don Knuth's "Seminumerical Algorithms".  */    int num_hi_sig, den_hi_sig;    unsigned HOST_WIDE_INT quo_est, scale;    /* Find the highest non-zero divisor digit.  */    for (i = 4 - 1; ; i--)      if (den[i] != 0) {	den_hi_sig = i;	break;      }    /* 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 <= 4 - 1; i++) {	work = (num[i] * scale) + carry;	num[i] = LOWPART (work);	carry = HIGHPART (work);      } num[4] = carry;      carry = 0;      for (i = 0; i <= 4 - 1; i++) {	work = (den[i] * scale) + carry;	den[i] = LOWPART (work);	carry = HIGHPART (work);	if (den[i] != 0) den_hi_sig = i;      }    }    num_hi_sig = 4;    /* Main loop */    for (i = num_hi_sig - den_hi_sig - 1; i >= 0; i--) {      /* guess 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.  */      unsigned HOST_WIDE_INT tmp;      num_hi_sig = i + den_hi_sig + 1;      work = num[num_hi_sig] * BASE + num[num_hi_sig - 1];      if (num[num_hi_sig] != 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.   */      tmp = work - quo_est * den[den_hi_sig];      if (tmp < BASE	  && den[den_hi_sig - 1] * quo_est > (tmp * BASE + num[num_hi_sig - 2]))	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++)	{	  work = quo_est * den[j] + carry;	  carry = HIGHPART (work);	  work = num[i + j] - LOWPART (work);	  num[i + j] = LOWPART (work);	  carry += HIGHPART (work) != 0;	}      /* if quo_est was high by one, then num[i] went negative and	 we need to correct things.  */      if (num[num_hi_sig] < carry)	{	  quo_est--;	  carry = 0;		/* add divisor back in */	  for (j = 0; j <= den_hi_sig; j++)	    {	      work = num[i + j] + den[j] + carry;	      carry = HIGHPART (work);	      num[i + j] = LOWPART (work);	    }	  num [num_hi_sig] += carry;	}      /* store the quotient digit.  */      quo[i] = 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 overflow;    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, (HOST_WIDE_INT) -1, (HOST_WIDE_INT)  -1,		      lquo, hquo);	}      else return overflow;      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, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,		      lquo, hquo);	}      else return overflow;      break;        case ROUND_DIV_EXPR:    case ROUND_MOD_EXPR:	/* round to closest integer */      {	HOST_WIDE_INT labs_rem = *lrem, habs_rem = *hrem;	HOST_WIDE_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 ((HOST_WIDE_INT) 2, (HOST_WIDE_INT) 0,		    labs_rem, habs_rem, &ltwice, &htwice);	if (((unsigned HOST_WIDE_INT) habs_den	     < (unsigned HOST_WIDE_INT) htwice)	    || (((unsigned HOST_WIDE_INT) habs_den		 == (unsigned HOST_WIDE_INT) htwice)		&& ((HOST_WIDE_INT unsigned) labs_den		    < (unsigned HOST_WIDE_INT) ltwice)))	  {	    if (*hquo < 0)	      /* quo = quo - 1;  */	      add_double (*lquo, *hquo,			  (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1, lquo, hquo);	    else	      /* quo = quo + 1; */	      add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,			  lquo, hquo);	  }	else return overflow;      }      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);  return overflow;}#ifndef REAL_ARITHMETIC/* Effectively truncate a real value to represent the nearest possible value   in a narrower mode.  The result is actually represented in the same data   type as the argument, but its value is usually different.   A trap may occur during the FP operations and it is the responsibility   of the calling function to have a handler established.  */REAL_VALUE_TYPEreal_value_truncate (mode, arg)     enum machine_mode mode;     REAL_VALUE_TYPE arg;{  return REAL_VALUE_TRUNCATE (mode, arg);}#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT/* Check for infinity in an IEEE double precision number.  */inttarget_isinf (x)     REAL_VALUE_TYPE x;{  /* The IEEE 64-bit double format.  */  union {    REAL_VALUE_TYPE d;    struct {      unsigned sign      :  1;      unsigned exponent  : 11;      unsigned mantissa1 : 20;      unsigned mantissa2;    } little_endian;    struct {      unsigned mantissa2;      unsigned mantissa1 : 20;      unsigned exponent  : 11;      unsigned sign      :  1;    } big_endian;      } u;  u.d = dconstm1;  if (u.big_endian.sign == 1)    {      u.d = x;      return (u.big_endian.exponent == 2047	      && u.big_endian.mantissa1 == 0	      && u.big_endian.mantissa2 == 0);    }  else    {      u.d = x;      return (u.little_endian.exponent == 2047	      && u.little_endian.mantissa1 == 0	      && u.little_endian.mantissa2 == 0);    }}/* Check whether an IEEE double precision number is a NaN.  */inttarget_isnan (x)     REAL_VALUE_TYPE x;{  /* The IEEE 64-bit double format.  */  union {    REAL_VALUE_TYPE d;    struct {      unsigned sign      :  1;      unsigned exponent  : 11;      unsigned mantissa1 : 20;      unsigned mantissa2;    } little_endian;    struct {      unsigned mantissa2;      unsigned mantissa1 : 20;      unsigned exponent  : 11;      unsigned sign      :  1;    } big_endian;      } u;  u.d = dconstm1;  if (u.big_endian.sign == 1)    {      u.d = x;      return (u.big_endian.exponent == 2047	      && (u.big_endian.mantissa1 != 0		  || u.big_endian.mantissa2 != 0));    }  else    {      u.d = x;      return (u.little_endian.exponent == 2047	      && (u.little_endian.mantissa1 != 0		  || u.little_endian.mantissa2 != 0));    }}/* Check for a negative IEEE double precision number.  */inttarget_negative (x)     REAL_VALUE_TYPE x;{  /* The IEEE 64-bit double format.  */  union {    REAL_VALUE_TYPE d;    struct {      unsigned sign      :  1;      unsigned exponent  : 11;      unsigned mantissa1 : 20;      unsigned mantissa2;    } little_endian;    struct {      unsigned mantissa2;      unsigned mantissa1 : 20;      unsigned exponent  : 11;      unsigned sign      :  1;    } big_endian;      } u;  u.d = dconstm1;  if (u.big_endian.sign == 1)    {      u.d = x;      return u.big_endian.sign;    }  else    {      u.d = x;      return u.little_endian.sign;    }}#else /* Target not IEEE *//* Let's assume other float formats don't have infinity.   (This can be overridden by redefining REAL_VALUE_ISINF.)  */target_isinf (x)     REAL_VALUE_TYPE x;{  return 0;}/* Let's assume other float formats don't have NaNs.   (This can be overridden by redefining REAL_VALUE_ISNAN.)  */target_isnan (x)     REAL_VALUE_TYPE x;{  return 0;}/* Let's assume other float formats don't have minus zero.   (This can be overridden by redefining REAL_VALUE_NEGATIVE.)  */target_negative (x)     REAL_VALUE_TYPE x;{  return x < 0;}#endif /* Target not IEEE */#endif /* no REAL_ARITHMETIC *//* 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      || (! FLOAT_TYPE_P (TREE_TYPE (in))	  /* 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)	{

⌨️ 快捷键说明

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