This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Committed] Fold (int)~(unsigned int)X as ~(int)X.


The following patch optimizes conversions of the form (T1)(~(T2)X)
as ~(T1)X, for integral types T1 and T2 where sizeof(T1) == sizeof(T2),
and (T2)X is not a zero/sign extension.  This takes advantage of the
fact that BIT_NOT_EXPR behaves identically for signed and unsigned
integral types.  Expressions of this form are created internally by
fold during the optimization of address arithmetic on LP64 targets
(this missed optimization was spotted during the analysis of PR22524).

The following patch has been tested on x86_64-unknown-linux-gnu with
a full make bootstrap, all default languages, and regression tested
with a top-level "make -k check" with no new failures.

Committed to mainline as revision 112455.



2006-03-28  Roger Sayle  <roger@eyesopen.com>

	* fold-const.c (fold_unary) <NOP_EXPR>: Fold (T1)(~(T2)X) as
	~(T1)X, when T1 and T2 are integer types of the same precision
	and (T2)X isn't an extension.

	* gcc.dg/fold-convnotconv-1.c: New test case.


Index: fold-const.c
===================================================================
*** fold-const.c	(revision 112052)
--- fold-const.c	(working copy)
*************** fold_unary (enum tree_code code, tree ty
*** 7074,7079 ****
--- 7074,7095 ----
  			   TREE_OPERAND (arg0, 1));
  	}

+       /* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types
+ 	 of the same precision, and X is a integer type not narrower than
+ 	 types T1 or T2, i.e. the cast (T2)X isn't an extension.  */
+       if (INTEGRAL_TYPE_P (type)
+ 	  && TREE_CODE (op0) == BIT_NOT_EXPR
+ 	  && INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ 	  && (TREE_CODE (TREE_OPERAND (op0, 0)) == NOP_EXPR
+ 	      || TREE_CODE (TREE_OPERAND (op0, 0)) == CONVERT_EXPR)
+ 	  && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0)))
+ 	{
+ 	  tem = TREE_OPERAND (TREE_OPERAND (op0, 0), 0);
+ 	  if (INTEGRAL_TYPE_P (TREE_TYPE (tem))
+ 	      && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (tem)))
+ 	    return fold_build1 (BIT_NOT_EXPR, type, fold_convert (type, tem));
+ 	}
+
        tem = fold_convert_const (code, type, arg0);
        return tem ? tem : NULL_TREE;


/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-original" } */

int test1(int a)
{
  return ~(unsigned int)a;
}

unsigned int test2(unsigned int b)
{
  return ~(int)b;
}

/* { dg-final { scan-tree-dump-times "~a" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "~b" 1 "original" } } */
/* { dg-final { cleanup-tree-dump "original" } } */


Roger
--


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]