diff mbox

Empty static constructor folding

Message ID 20100913135201.GA22498@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Sept. 13, 2010, 1:52 p.m. UTC
Hi,
here is updated patch.  It bootstrapped/regtested C only, I am doing full testing now.
OK if it passes? (x86-64-linux)

Honza

/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-ccp2" } */

struct a {int a,b;};
const static struct a a;
static int b[10];
int c;
test()
{
  return a.a+b[c];
}
/* { dg-final { scan-tree-dump "return 0;" "ccp2" } } */
/* { dg-final { cleanup-tree-dump "ccp2" } } */
	* tree.c (build_zero_cst): New.
	* tree.h (build_zero_cst): Declare.
	* tree-ssa-ccp.c (get_constant_value): Accept general operands.
	(get_base_constructor): Break out from ...
	(fold_const_aggregate_ref): Here; handle empty constructors.

	* testsuite/gcc.dg/torture/pr23821.c: Drop static keyword.
	* testsuite/gcc.dg/tree-ssa/loop-19.c: Likewise.
     }
 }
 
+/* See if we can find constructor defining value of BASE
+   possibly return offset of the definition in OFFSET.
+
+   As a special case, return error_mark_node when constructor
+   is not explicitly available, but it is known to be zero
+   such as 'static const int a;'.  */
+static tree
+get_base_constructor (tree base, tree *offset)
+{
+  *offset = NULL;
+  if (TREE_CODE (base) == MEM_REF)
+    {
+      if (!integer_zerop (TREE_OPERAND (base, 1)))
+        *offset = TREE_OPERAND (base, 1);
+
+      base = get_constant_value (TREE_OPERAND (base, 0));
+      if (!base || TREE_CODE (base) != ADDR_EXPR)
+        return NULL_TREE;
+      base = TREE_OPERAND (base, 0);
+    }
+
+  /* Get a CONSTRUCTOR.  If BASE is a VAR_DECL, get its
+     DECL_INITIAL.  If BASE is a nested reference into another
+     ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
+     the inner reference.  */
+  switch (TREE_CODE (base))
+    {
+    case VAR_DECL:
+      if (!TREE_READONLY (base)
+	  || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
+	      && !varpool_get_node (base)->const_value_known))
+	return NULL_TREE;
+
+      /* Fallthru.  */
+    case CONST_DECL:
+      if (!DECL_INITIAL (base)
+	  && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
+        return error_mark_node;
+      return DECL_INITIAL (base);
+      
+      break;
+
+    case ARRAY_REF:
+    case COMPONENT_REF:
+      return fold_const_aggregate_ref (base);
+      break;
+
+    case STRING_CST:
+    case CONSTRUCTOR:
+      return base;
+      break;
+
+    default:
+      return NULL_TREE;
+    }
+}
+
 /* Return the tree representing the element referenced by T if T is an
    ARRAY_REF or COMPONENT_REF into constant aggregates.  Return
    NULL_TREE otherwise.  */
@@ -1315,7 +1378,7 @@ ccp_fold (gimple stmt)
 tree
 fold_const_aggregate_ref (tree t)
 {
-  tree base, ctor, idx, field;
+  tree ctor, idx, field;
   unsigned HOST_WIDE_INT cnt;
   tree cfield, cval;
   tree tem;
@@ -1330,46 +1393,13 @@ fold_const_aggregate_ref (tree t)
   switch (TREE_CODE (t))
     {
     case ARRAY_REF:
-      /* Get a CONSTRUCTOR.  If BASE is a VAR_DECL, get its
-	 DECL_INITIAL.  If BASE is a nested reference into another
-	 ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
-	 the inner reference.  */
-      base = TREE_OPERAND (t, 0);
-      switch (TREE_CODE (base))
-	{
-	case MEM_REF:
-	  /* ???  We could handle this case.  */
-	  if (!integer_zerop (TREE_OPERAND (base, 1)))
-	    return NULL_TREE;
-	  base = get_base_address (base);
-	  if (!base
-	      || TREE_CODE (base) != VAR_DECL)
-	    return NULL_TREE;
+      ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx);
 
-	  /* Fallthru.  */
-	case VAR_DECL:
-	  if (!TREE_READONLY (base)
-	      || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
-	      || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
-		  && !varpool_get_node (base)->const_value_known))
-	    return NULL_TREE;
-
-	  ctor = DECL_INITIAL (base);
-	  break;
-
-	case ARRAY_REF:
-	case COMPONENT_REF:
-	  ctor = fold_const_aggregate_ref (base);
-	  break;
-
-	case STRING_CST:
-	case CONSTRUCTOR:
-	  ctor = base;
-	  break;
+      if (idx)
+	return NULL_TREE;
 
-	default:
-	  return NULL_TREE;
-	}
+      if (ctor == error_mark_node)
+	return build_zero_cst (TREE_TYPE (t));
 
       if (ctor == NULL_TREE
 	  || (TREE_CODE (ctor) != CONSTRUCTOR
@@ -1436,27 +1466,13 @@ fold_const_aggregate_ref (tree t)
 	 DECL_INITIAL.  If BASE is a nested reference into another
 	 ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
 	 the inner reference.  */
-      base = TREE_OPERAND (t, 0);
-      switch (TREE_CODE (base))
-	{
-	case VAR_DECL:
-	  if (!TREE_READONLY (base)
-	      || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE
-	      || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
-		  && !varpool_get_node (base)->const_value_known))
-	    return NULL_TREE;
+      ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx);
 
-	  ctor = DECL_INITIAL (base);
-	  break;
+      if (idx)
+	return NULL_TREE;
 
-	case ARRAY_REF:
-	case COMPONENT_REF:
-	  ctor = fold_const_aggregate_ref (base);
-	  break;
-
-	default:
-	  return NULL_TREE;
-	}
+      if (ctor == error_mark_node)
+	return build_zero_cst (TREE_TYPE (t));
 
       if (ctor == NULL_TREE
 	  || TREE_CODE (ctor) != CONSTRUCTOR)
@@ -1482,47 +1498,24 @@ fold_const_aggregate_ref (tree t)
       }
 
     case MEM_REF:
-      /* Get the base object we are accessing.  */
-      base = TREE_OPERAND (t, 0);
-      if (TREE_CODE (base) == SSA_NAME
-	  && (tem = get_constant_value (base)))
-	base = tem;
-      if (TREE_CODE (base) != ADDR_EXPR)
-	return NULL_TREE;
-      base = TREE_OPERAND (base, 0);
-      switch (TREE_CODE (base))
-	{
-	case VAR_DECL:
-	  if (DECL_P (base)
-	      && !AGGREGATE_TYPE_P (TREE_TYPE (base))
-	      && integer_zerop (TREE_OPERAND (t, 1)))
-	    {
-	      tree res = get_symbol_constant_value (base);
-	      if (res
-		  && !useless_type_conversion_p
-		        (TREE_TYPE (t), TREE_TYPE (res)))
-		res = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), res);
-	      return res;
-	    }
-
-	  if (!TREE_READONLY (base)
-	      || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
-	      || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
-		  && !varpool_get_node (base)->const_value_known))
-	    return NULL_TREE;
-
-	  ctor = DECL_INITIAL (base);
-	  break;
-
-	case STRING_CST:
-	case CONSTRUCTOR:
-	  ctor = base;
-	  break;
-
-	default:
-	  return NULL_TREE;
+      ctor = get_base_constructor (t, &idx);
+      if (!idx)
+	idx = integer_zero_node;
+
+      if (ctor == error_mark_node)
+	return build_zero_cst (TREE_TYPE (t));
+
+      if (ctor && !AGGREGATE_TYPE_P (TREE_TYPE (ctor))
+	  && integer_zerop (TREE_OPERAND (t, 1)))
+	{
+	  if (ctor
+	      && !useless_type_conversion_p
+		    (TREE_TYPE (t), TREE_TYPE (ctor)))
+	    ctor = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), ctor);
+	  return ctor;
 	}
 
+
       if (ctor == NULL_TREE
 	  || (TREE_CODE (ctor) != CONSTRUCTOR
 	      && TREE_CODE (ctor) != STRING_CST))

Comments

Richard Biener Sept. 13, 2010, 2:20 p.m. UTC | #1
On Mon, 13 Sep 2010, Jan Hubicka wrote:

> Hi,
> here is updated patch.  It bootstrapped/regtested C only, I am doing full testing now.
> OK if it passes? (x86-64-linux)
> 
> Honza
> 
> /* { dg-do compile } */
> /* { dg-options "-O -fdump-tree-ccp2" } */
> 
> struct a {int a,b;};
> const static struct a a;
> static int b[10];
> int c;
> test()
> {
>   return a.a+b[c];
> }
> /* { dg-final { scan-tree-dump "return 0;" "ccp2" } } */
> /* { dg-final { cleanup-tree-dump "ccp2" } } */
> 	* tree.c (build_zero_cst): New.
> 	* tree.h (build_zero_cst): Declare.
> 	* tree-ssa-ccp.c (get_constant_value): Accept general operands.
> 	(get_base_constructor): Break out from ...
> 	(fold_const_aggregate_ref): Here; handle empty constructors.
> 
> 	* testsuite/gcc.dg/torture/pr23821.c: Drop static keyword.
> 	* testsuite/gcc.dg/tree-ssa/loop-19.c: Likewise.
> Index: tree.c
> ===================================================================
> --- tree.c	(revision 164197)
> +++ tree.c	(working copy)
> @@ -1583,6 +1583,18 @@ build_one_cst (tree type)
>      }
>  }
>  
> +/* Build 0 constant of type TYPE.  This is used by constructor folding and thus
> +   the constant should correspond zero in memory representation.  */
> +
> +tree
> +build_zero_cst (tree type)
> +{
> +  if (!AGGREGATE_TYPE_P (type))
> +    return fold_convert (type, integer_zero_node);
> +  return build_constructor (type, NULL);
> +}
> +
> +
>  /* Build a BINFO with LEN language slots.  */
>  
>  tree
> Index: tree.h
> ===================================================================
> --- tree.h	(revision 164197)
> +++ tree.h	(working copy)
> @@ -4038,6 +4038,7 @@ extern tree build_constructor_from_list 
>  extern tree build_real_from_int_cst (tree, const_tree);
>  extern tree build_complex (tree, tree, tree);
>  extern tree build_one_cst (tree);
> +extern tree build_zero_cst (tree);
>  extern tree build_string (int, const char *);
>  extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
>  #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
> Index: testsuite/gcc.dg/torture/pr23821.c
> ===================================================================
> --- testsuite/gcc.dg/torture/pr23821.c	(revision 164197)
> +++ testsuite/gcc.dg/torture/pr23821.c	(working copy)
> @@ -5,7 +5,7 @@
>  /* { dg-skip-if "" { *-*-* } { "-O1" } { "" } } */
>  /* { dg-options "-fdump-tree-ivcanon-details" } */
>  
> -static int a[199];
> +int a[199];
>  
>  extern void abort (void);
>  
> Index: testsuite/gcc.dg/tree-ssa/loop-19.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/loop-19.c	(revision 164197)
> +++ testsuite/gcc.dg/tree-ssa/loop-19.c	(working copy)
> @@ -9,7 +9,7 @@
>  /* { dg-options "-O3 -fno-prefetch-loop-arrays -fdump-tree-optimized" } */
>  
>  # define N      2000000
> -static double   a[N],c[N];
> +double   a[N],c[N];
>  void tuned_STREAM_Copy()
>  {
>    int j;
> Index: tree-ssa-ccp.c
> ===================================================================
> --- tree-ssa-ccp.c	(revision 164198)
> +++ tree-ssa-ccp.c	(working copy)
> @@ -315,7 +315,15 @@ get_value (tree var)
>  static inline tree
>  get_constant_value (tree var)
>  {
> -  prop_value_t *val = get_value (var);
> +  prop_value_t *val;
> +  if (TREE_CODE (var) != SSA_NAME)
> +    {
> +      if (is_gimple_min_invariant (var))
> +        return var;
> +      return NULL_TREE;
> +    }
> +  val = get_value (var);
>    if (val
>        && val->lattice_val == CONSTANT
>        && (TREE_CODE (val->value) != INTEGER_CST
> @@ -1308,6 +1315,62 @@ ccp_fold (gimple stmt)
>      }
>  }
>  
> +/* See if we can find constructor defining value of BASE
> +   possibly return offset of the definition in OFFSET.
> +
> +   As a special case, return error_mark_node when constructor
> +   is not explicitly available, but it is known to be zero
> +   such as 'static const int a;'.  */
> +static tree
> +get_base_constructor (tree base, tree *offset)
> +{
> +  *offset = NULL;
> +  if (TREE_CODE (base) == MEM_REF)
> +    {
> +      if (!integer_zerop (TREE_OPERAND (base, 1)))
> +        *offset = TREE_OPERAND (base, 1);
> +
> +      base = get_constant_value (TREE_OPERAND (base, 0));
> +      if (!base || TREE_CODE (base) != ADDR_EXPR)
> +        return NULL_TREE;
> +      base = TREE_OPERAND (base, 0);
> +    }
> +
> +  /* Get a CONSTRUCTOR.  If BASE is a VAR_DECL, get its
> +     DECL_INITIAL.  If BASE is a nested reference into another
> +     ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
> +     the inner reference.  */
> +  switch (TREE_CODE (base))
> +    {
> +    case VAR_DECL:
> +      if (!TREE_READONLY (base)
> +	  || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
> +	      && !varpool_get_node (base)->const_value_known))
> +	return NULL_TREE;
> +
> +      /* Fallthru.  */
> +    case CONST_DECL:
> +      if (!DECL_INITIAL (base)
> +	  && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
> +        return error_mark_node;
> +      return DECL_INITIAL (base);
> +      
> +      break;
> +
> +    case ARRAY_REF:
> +    case COMPONENT_REF:
> +      return fold_const_aggregate_ref (base);
> +      break;
> +
> +    case STRING_CST:
> +    case CONSTRUCTOR:
> +      return base;
> +      break;
> +
> +    default:
> +      return NULL_TREE;
> +    }
> +}
> +
>  /* Return the tree representing the element referenced by T if T is an
>     ARRAY_REF or COMPONENT_REF into constant aggregates.  Return
>     NULL_TREE otherwise.  */
> @@ -1315,7 +1378,7 @@ ccp_fold (gimple stmt)
>  tree
>  fold_const_aggregate_ref (tree t)
>  {
> -  tree base, ctor, idx, field;
> +  tree ctor, idx, field;
>    unsigned HOST_WIDE_INT cnt;
>    tree cfield, cval;
>    tree tem;
> @@ -1330,46 +1393,13 @@ fold_const_aggregate_ref (tree t)
>    switch (TREE_CODE (t))
>      {
>      case ARRAY_REF:
> -      /* Get a CONSTRUCTOR.  If BASE is a VAR_DECL, get its
> -	 DECL_INITIAL.  If BASE is a nested reference into another
> -	 ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
> -	 the inner reference.  */
> -      base = TREE_OPERAND (t, 0);
> -      switch (TREE_CODE (base))
> -	{
> -	case MEM_REF:
> -	  /* ???  We could handle this case.  */
> -	  if (!integer_zerop (TREE_OPERAND (base, 1)))
> -	    return NULL_TREE;
> -	  base = get_base_address (base);
> -	  if (!base
> -	      || TREE_CODE (base) != VAR_DECL)
> -	    return NULL_TREE;
> +      ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx);
>  
> -	  /* Fallthru.  */
> -	case VAR_DECL:
> -	  if (!TREE_READONLY (base)
> -	      || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
> -	      || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
> -		  && !varpool_get_node (base)->const_value_known))
> -	    return NULL_TREE;
> -
> -	  ctor = DECL_INITIAL (base);
> -	  break;
> -
> -	case ARRAY_REF:
> -	case COMPONENT_REF:
> -	  ctor = fold_const_aggregate_ref (base);
> -	  break;
> -
> -	case STRING_CST:
> -	case CONSTRUCTOR:
> -	  ctor = base;
> -	  break;
> +      if (idx)
> +	return NULL_TREE;
>  
> -	default:
> -	  return NULL_TREE;
> -	}
> +      if (ctor == error_mark_node)
> +	return build_zero_cst (TREE_TYPE (t));
>  
>        if (ctor == NULL_TREE
>  	  || (TREE_CODE (ctor) != CONSTRUCTOR
> @@ -1436,27 +1466,13 @@ fold_const_aggregate_ref (tree t)
>  	 DECL_INITIAL.  If BASE is a nested reference into another
>  	 ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
>  	 the inner reference.  */
> -      base = TREE_OPERAND (t, 0);
> -      switch (TREE_CODE (base))
> -	{
> -	case VAR_DECL:
> -	  if (!TREE_READONLY (base)
> -	      || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE
> -	      || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
> -		  && !varpool_get_node (base)->const_value_known))
> -	    return NULL_TREE;
> +      ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx);
>  
> -	  ctor = DECL_INITIAL (base);
> -	  break;
> +      if (idx)
> +	return NULL_TREE;
>  
> -	case ARRAY_REF:
> -	case COMPONENT_REF:
> -	  ctor = fold_const_aggregate_ref (base);
> -	  break;
> -
> -	default:
> -	  return NULL_TREE;
> -	}
> +      if (ctor == error_mark_node)
> +	return build_zero_cst (TREE_TYPE (t));
>  
>        if (ctor == NULL_TREE
>  	  || TREE_CODE (ctor) != CONSTRUCTOR)
> @@ -1482,47 +1498,24 @@ fold_const_aggregate_ref (tree t)
>        }
>  
>      case MEM_REF:
> -      /* Get the base object we are accessing.  */
> -      base = TREE_OPERAND (t, 0);
> -      if (TREE_CODE (base) == SSA_NAME
> -	  && (tem = get_constant_value (base)))
> -	base = tem;
> -      if (TREE_CODE (base) != ADDR_EXPR)
> -	return NULL_TREE;
> -      base = TREE_OPERAND (base, 0);
> -      switch (TREE_CODE (base))
> -	{
> -	case VAR_DECL:
> -	  if (DECL_P (base)
> -	      && !AGGREGATE_TYPE_P (TREE_TYPE (base))
> -	      && integer_zerop (TREE_OPERAND (t, 1)))
> -	    {
> -	      tree res = get_symbol_constant_value (base);
> -	      if (res
> -		  && !useless_type_conversion_p
> -		        (TREE_TYPE (t), TREE_TYPE (res)))
> -		res = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), res);
> -	      return res;
> -	    }
> -
> -	  if (!TREE_READONLY (base)
> -	      || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
> -	      || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
> -		  && !varpool_get_node (base)->const_value_known))
> -	    return NULL_TREE;
> -
> -	  ctor = DECL_INITIAL (base);
> -	  break;
> -
> -	case STRING_CST:
> -	case CONSTRUCTOR:
> -	  ctor = base;
> -	  break;
> -
> -	default:
> -	  return NULL_TREE;
> +      ctor = get_base_constructor (t, &idx);
> +      if (!idx)
> +	idx = integer_zero_node;
> +
> +      if (ctor == error_mark_node)
> +	return build_zero_cst (TREE_TYPE (t));
> +
> +      if (ctor && !AGGREGATE_TYPE_P (TREE_TYPE (ctor))
> +	  && integer_zerop (TREE_OPERAND (t, 1)))

That would be idx?

> +	{
> +	  if (ctor
> +	      && !useless_type_conversion_p
> +		    (TREE_TYPE (t), TREE_TYPE (ctor)))
> +	    ctor = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), ctor);
> +	  return ctor;
>  	}
>  
> +
>        if (ctor == NULL_TREE
>  	  || (TREE_CODE (ctor) != CONSTRUCTOR
>  	      && TREE_CODE (ctor) != STRING_CST))

Spurious whitespace change.  And below

      /* Get the byte offset.  */
      idx = TREE_OPERAND (t, 1);

this has already been set.

Ok with that fixed.

Thanks,
Richard.
diff mbox

Patch

Index: tree.c
===================================================================
--- tree.c	(revision 164197)
+++ tree.c	(working copy)
@@ -1583,6 +1583,18 @@  build_one_cst (tree type)
     }
 }
 
+/* Build 0 constant of type TYPE.  This is used by constructor folding and thus
+   the constant should correspond zero in memory representation.  */
+
+tree
+build_zero_cst (tree type)
+{
+  if (!AGGREGATE_TYPE_P (type))
+    return fold_convert (type, integer_zero_node);
+  return build_constructor (type, NULL);
+}
+
+
 /* Build a BINFO with LEN language slots.  */
 
 tree
Index: tree.h
===================================================================
--- tree.h	(revision 164197)
+++ tree.h	(working copy)
@@ -4038,6 +4038,7 @@  extern tree build_constructor_from_list 
 extern tree build_real_from_int_cst (tree, const_tree);
 extern tree build_complex (tree, tree, tree);
 extern tree build_one_cst (tree);
+extern tree build_zero_cst (tree);
 extern tree build_string (int, const char *);
 extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
 #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
Index: testsuite/gcc.dg/torture/pr23821.c
===================================================================
--- testsuite/gcc.dg/torture/pr23821.c	(revision 164197)
+++ testsuite/gcc.dg/torture/pr23821.c	(working copy)
@@ -5,7 +5,7 @@ 
 /* { dg-skip-if "" { *-*-* } { "-O1" } { "" } } */
 /* { dg-options "-fdump-tree-ivcanon-details" } */
 
-static int a[199];
+int a[199];
 
 extern void abort (void);
 
Index: testsuite/gcc.dg/tree-ssa/loop-19.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/loop-19.c	(revision 164197)
+++ testsuite/gcc.dg/tree-ssa/loop-19.c	(working copy)
@@ -9,7 +9,7 @@ 
 /* { dg-options "-O3 -fno-prefetch-loop-arrays -fdump-tree-optimized" } */
 
 # define N      2000000
-static double   a[N],c[N];
+double   a[N],c[N];
 void tuned_STREAM_Copy()
 {
   int j;
Index: tree-ssa-ccp.c
===================================================================
--- tree-ssa-ccp.c	(revision 164198)
+++ tree-ssa-ccp.c	(working copy)
@@ -315,7 +315,15 @@  get_value (tree var)
 static inline tree
 get_constant_value (tree var)
 {
-  prop_value_t *val = get_value (var);
+  prop_value_t *val;
+  if (TREE_CODE (var) != SSA_NAME)
+    {
+      if (is_gimple_min_invariant (var))
+        return var;
+      return NULL_TREE;
+    }
+  val = get_value (var);
   if (val
       && val->lattice_val == CONSTANT
       && (TREE_CODE (val->value) != INTEGER_CST
@@ -1308,6 +1315,62 @@  ccp_fold (gimple stmt)