fold-const.c

来自「GCC编译器源代码」· C语言 代码 · 共 2,288 行 · 第 1/5 页

C
2,288
字号
      return operand_equal_p (TREE_OPERAND (arg0, 0),			      TREE_OPERAND (arg1, 0), 0);    case '<':    case '2':      if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0)	  && operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1),			      0))	return 1;      /* For commutative ops, allow the other order.  */      return ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MULT_EXPR	       || TREE_CODE (arg0) == MIN_EXPR || TREE_CODE (arg0) == MAX_EXPR	       || TREE_CODE (arg0) == BIT_IOR_EXPR	       || TREE_CODE (arg0) == BIT_XOR_EXPR	       || TREE_CODE (arg0) == BIT_AND_EXPR	       || TREE_CODE (arg0) == NE_EXPR || TREE_CODE (arg0) == EQ_EXPR)	      && operand_equal_p (TREE_OPERAND (arg0, 0),				  TREE_OPERAND (arg1, 1), 0)	      && operand_equal_p (TREE_OPERAND (arg0, 1),				  TREE_OPERAND (arg1, 0), 0));    case 'r':      switch (TREE_CODE (arg0))	{	case INDIRECT_REF:	  return operand_equal_p (TREE_OPERAND (arg0, 0),				  TREE_OPERAND (arg1, 0), 0);	case COMPONENT_REF:	case ARRAY_REF:	  return (operand_equal_p (TREE_OPERAND (arg0, 0),				   TREE_OPERAND (arg1, 0), 0)		  && operand_equal_p (TREE_OPERAND (arg0, 1),				      TREE_OPERAND (arg1, 1), 0));	case BIT_FIELD_REF:	  return (operand_equal_p (TREE_OPERAND (arg0, 0),				   TREE_OPERAND (arg1, 0), 0)		  && operand_equal_p (TREE_OPERAND (arg0, 1),				      TREE_OPERAND (arg1, 1), 0)		  && operand_equal_p (TREE_OPERAND (arg0, 2),				      TREE_OPERAND (arg1, 2), 0));	default:	  return 0;	}          default:      return 0;    }}/* Similar to operand_equal_p, but see if ARG0 might have been made by   shorten_compare from ARG1 when ARG1 was being compared with OTHER.    When in doubt, return 0.  */static int operand_equal_for_comparison_p (arg0, arg1, other)     tree arg0, arg1;     tree other;{  int unsignedp1, unsignedpo;  tree primarg1, primother;  unsigned correct_width;  if (operand_equal_p (arg0, arg1, 0))    return 1;  if (! INTEGRAL_TYPE_P (TREE_TYPE (arg0))      || ! INTEGRAL_TYPE_P (TREE_TYPE (arg1)))    return 0;  /* Duplicate what shorten_compare does to ARG1 and see if that gives the     actual comparison operand, ARG0.     First throw away any conversions to wider types     already present in the operands.  */  primarg1 = get_narrower (arg1, &unsignedp1);  primother = get_narrower (other, &unsignedpo);  correct_width = TYPE_PRECISION (TREE_TYPE (arg1));  if (unsignedp1 == unsignedpo      && TYPE_PRECISION (TREE_TYPE (primarg1)) < correct_width      && TYPE_PRECISION (TREE_TYPE (primother)) < correct_width)    {      tree type = TREE_TYPE (arg0);      /* Make sure shorter operand is extended the right way	 to match the longer operand.  */      primarg1 = convert (signed_or_unsigned_type (unsignedp1,						  TREE_TYPE (primarg1)),			 primarg1);      if (operand_equal_p (arg0, convert (type, primarg1), 0))	return 1;    }  return 0;}/* See if ARG is an expression that is either a comparison or is performing   arithmetic on comparisons.  The comparisons must only be comparing   two different values, which will be stored in *CVAL1 and *CVAL2; if   they are non-zero it means that some operands have already been found.   No variables may be used anywhere else in the expression except in the   comparisons.  If SAVE_P is true it means we removed a SAVE_EXPR around   the expression and save_expr needs to be called with CVAL1 and CVAL2.   If this is true, return 1.  Otherwise, return zero.  */static inttwoval_comparison_p (arg, cval1, cval2, save_p)     tree arg;     tree *cval1, *cval2;     int *save_p;{  enum tree_code code = TREE_CODE (arg);  char class = TREE_CODE_CLASS (code);  /* We can handle some of the 'e' cases here.  */  if (class == 'e' && code == TRUTH_NOT_EXPR)    class = '1';  else if (class == 'e'	   && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR	       || code == COMPOUND_EXPR))    class = '2';  /* ??? Disable this since the SAVE_EXPR might already be in use outside     the expression.  There may be no way to make this work, but it needs     to be looked at again for 2.6.  */#if 0  else if (class == 'e' && code == SAVE_EXPR && SAVE_EXPR_RTL (arg) == 0)    {      /* If we've already found a CVAL1 or CVAL2, this expression is	 two complex to handle.  */      if (*cval1 || *cval2)	return 0;      class = '1';      *save_p = 1;    }#endif  switch (class)    {    case '1':      return twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p);    case '2':      return (twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p)	      && twoval_comparison_p (TREE_OPERAND (arg, 1),				      cval1, cval2, save_p));    case 'c':      return 1;    case 'e':      if (code == COND_EXPR)	return (twoval_comparison_p (TREE_OPERAND (arg, 0),				     cval1, cval2, save_p)		&& twoval_comparison_p (TREE_OPERAND (arg, 1),					cval1, cval2, save_p)		&& twoval_comparison_p (TREE_OPERAND (arg, 2),					cval1, cval2, save_p));      return 0;	      case '<':      /* First see if we can handle the first operand, then the second.  For	 the second operand, we know *CVAL1 can't be zero.  It must be that	 one side of the comparison is each of the values; test for the	 case where this isn't true by failing if the two operands	 are the same.  */      if (operand_equal_p (TREE_OPERAND (arg, 0),			   TREE_OPERAND (arg, 1), 0))	return 0;      if (*cval1 == 0)	*cval1 = TREE_OPERAND (arg, 0);      else if (operand_equal_p (*cval1, TREE_OPERAND (arg, 0), 0))	;      else if (*cval2 == 0)	*cval2 = TREE_OPERAND (arg, 0);      else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 0), 0))	;      else	return 0;      if (operand_equal_p (*cval1, TREE_OPERAND (arg, 1), 0))	;      else if (*cval2 == 0)	*cval2 = TREE_OPERAND (arg, 1);      else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 1), 0))	;      else	return 0;      return 1;    default:      return 0;    }}/* ARG is a tree that is known to contain just arithmetic operations and   comparisons.  Evaluate the operations in the tree substituting NEW0 for   any occurrence of OLD0 as an operand of a comparison and likewise for   NEW1 and OLD1.  */static treeeval_subst (arg, old0, new0, old1, new1)     tree arg;     tree old0, new0, old1, new1;{  tree type = TREE_TYPE (arg);  enum tree_code code = TREE_CODE (arg);  char class = TREE_CODE_CLASS (code);  /* We can handle some of the 'e' cases here.  */  if (class == 'e' && code == TRUTH_NOT_EXPR)    class = '1';  else if (class == 'e'	   && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))    class = '2';  switch (class)    {    case '1':      return fold (build1 (code, type,			   eval_subst (TREE_OPERAND (arg, 0),				       old0, new0, old1, new1)));    case '2':      return fold (build (code, type,			  eval_subst (TREE_OPERAND (arg, 0),				      old0, new0, old1, new1),			  eval_subst (TREE_OPERAND (arg, 1),				      old0, new0, old1, new1)));    case 'e':      switch (code)	{	case SAVE_EXPR:	  return eval_subst (TREE_OPERAND (arg, 0), old0, new0, old1, new1);	case COMPOUND_EXPR:	  return eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1);	case COND_EXPR:	  return fold (build (code, type,			      eval_subst (TREE_OPERAND (arg, 0),					  old0, new0, old1, new1),			      eval_subst (TREE_OPERAND (arg, 1),					  old0, new0, old1, new1),			      eval_subst (TREE_OPERAND (arg, 2),					  old0, new0, old1, new1)));	default:	  break;	}      /* fall through (???) */    case '<':      {	tree arg0 = TREE_OPERAND (arg, 0);	tree arg1 = TREE_OPERAND (arg, 1);	/* We need to check both for exact equality and tree equality.  The	   former will be true if the operand has a side-effect.  In that	   case, we know the operand occurred exactly once.  */	if (arg0 == old0 || operand_equal_p (arg0, old0, 0))	  arg0 = new0;	else if (arg0 == old1 || operand_equal_p (arg0, old1, 0))	  arg0 = new1;	if (arg1 == old0 || operand_equal_p (arg1, old0, 0))	  arg1 = new0;	else if (arg1 == old1 || operand_equal_p (arg1, old1, 0))	  arg1 = new1;	return fold (build (code, type, arg0, arg1));      }    default:      return arg;    }}/* Return a tree for the case when the result of an expression is RESULT   converted to TYPE and OMITTED was previously an operand of the expression   but is now not needed (e.g., we folded OMITTED * 0).   If OMITTED has side effects, we must evaluate it.  Otherwise, just do   the conversion of RESULT to TYPE.  */static treeomit_one_operand (type, result, omitted)     tree type, result, omitted;{  tree t = convert (type, result);  if (TREE_SIDE_EFFECTS (omitted))    return build (COMPOUND_EXPR, type, omitted, t);  return non_lvalue (t);}/* Similar, but call pedantic_non_lvalue instead of non_lvalue.  */static treepedantic_omit_one_operand (type, result, omitted)     tree type, result, omitted;{  tree t = convert (type, result);  if (TREE_SIDE_EFFECTS (omitted))    return build (COMPOUND_EXPR, type, omitted, t);  return pedantic_non_lvalue (t);}/* Return a simplified tree node for the truth-negation of ARG.  This   never alters ARG itself.  We assume that ARG is an operation that   returns a truth value (0 or 1).  */treeinvert_truthvalue (arg)     tree arg;{  tree type = TREE_TYPE (arg);  enum tree_code code = TREE_CODE (arg);  if (code == ERROR_MARK)    return arg;  /* If this is a comparison, we can simply invert it, except for     floating-point non-equality comparisons, in which case we just     enclose a TRUTH_NOT_EXPR around what we have.  */  if (TREE_CODE_CLASS (code) == '<')    {      if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))	  && code != NE_EXPR && code != EQ_EXPR)	return build1 (TRUTH_NOT_EXPR, type, arg);      else	return build (invert_tree_comparison (code), type,		      TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));    }  switch (code)    {    case INTEGER_CST:      return convert (type, build_int_2 (TREE_INT_CST_LOW (arg) == 0					 && TREE_INT_CST_HIGH (arg) == 0, 0));    case TRUTH_AND_EXPR:      return build (TRUTH_OR_EXPR, type,		    invert_truthvalue (TREE_OPERAND (arg, 0)),		    invert_truthvalue (TREE_OPERAND (arg, 1)));    case TRUTH_OR_EXPR:      return build (TRUTH_AND_EXPR, type,		    invert_truthvalue (TREE_OPERAND (arg, 0)),		    invert_truthvalue (TREE_OPERAND (arg, 1)));    case TRUTH_XOR_EXPR:      /* Here we can invert either operand.  We invert the first operand	 unless the second operand is a TRUTH_NOT_EXPR in which case our	 result is the XOR of the first operand with the inside of the	 negation of the second operand.  */      if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)	return build (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),		      TREE_OPERAND (TREE_OPERAND (arg, 1), 0));      else	return build (TRUTH_XOR_EXPR, type,		      invert_truthvalue (TREE_OPERAND (arg, 0)),		      TREE_OPERAND (arg, 1));    case TRUTH_ANDIF_EXPR:      return build (TRUTH_ORIF_EXPR, type,		    invert_truthvalue (TREE_OPERAND (arg, 0)),		    invert_truthvalue (TREE_OPERAND (arg, 1)));    case TRUTH_ORIF_EXPR:      return build (TRUTH_ANDIF_EXPR, type,		    invert_truthvalue (TREE_OPERAND (arg, 0)),		    invert_truthvalue (TREE_OPERAND (arg, 1)));    case TRUTH_NOT_EXPR:      return TREE_OPERAND (arg, 0);    case COND_EXPR:      return build (COND_EXPR, type, TREE_OPERAND (arg, 0),		    invert_truthvalue (TREE_OPERAND (arg, 1)),		    invert_truthvalue (TREE_OPERAND (arg, 2)));    case COMPOUND_EXPR:      return build (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),		    invert_truthvalue (TREE_OPERAND (arg, 1)));    case NON_LVALUE_EXPR:      return invert_truthvalue (TREE_OPERAND (arg, 0));    case NOP_EXPR:    case CONVERT_EXPR:    case FLOAT_EXPR:      return build1 (TREE_CODE (arg), type,		     invert_truthvalue (TREE_OPERAND (arg, 0)));    case BIT_AND_EXPR:      if (!integer_onep (TREE_OPERAND (arg, 1)))	break;      return build (EQ_EXPR, type, arg, convert (type, integer_zero_node));    case SAVE_EXPR:      return build1 (TRUTH_NOT_EXPR, type, arg);    case CLEANUP_POINT_EXPR:      return build1 (CLEANUP_POINT_EXPR, type,		     invert_truthvalue (TREE_OPERAND (arg, 0)));    default:      break;    }  if (TREE_CODE (TREE_TYPE (arg)) != BOOLEAN_TYPE)    abort ();  return build1 (TRUTH_NOT_EXPR, type, arg);}/* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both   operands are another bit-wise operation with a common input.  If so,   distribute the bit operations to save an operation and possibly two if   constants are involved.  For example, convert   	(A | B) & (A | C) into A | (B & C)   Further simplification will occur if B and C are constants.   If this optimization cannot be done, 0 will be returned.  */static treedistribute_bit_expr (code, type, arg0, arg1)     enum tree_code code;     tree type;     tree arg0, arg1;{  tree common;  tree left, right;  if (TREE_CODE (arg0) != TREE_CODE (arg1)      || TREE_CODE (arg0) == code      || (TREE_C

⌨️ 快捷键说明

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