OSDN Git Service

2009-05-28 Kai Tietz <kai.tietz@onevision.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ccp.c
index 437d426..fb6eb4d 100644 (file)
@@ -958,6 +958,30 @@ ccp_fold (gimple stmt)
                        }
                    }
                }
+             else if (TREE_CODE (rhs) == CONSTRUCTOR
+                      && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE
+                      && (CONSTRUCTOR_NELTS (rhs)
+                          == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
+               {
+                 unsigned i;
+                 tree val, list;
+
+                 list = NULL_TREE;
+                 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
+                   {
+                     if (TREE_CODE (val) == SSA_NAME
+                         && get_value (val)->lattice_val == CONSTANT)
+                       val = get_value (val)->value;
+                     if (TREE_CODE (val) == INTEGER_CST
+                         || TREE_CODE (val) == REAL_CST
+                         || TREE_CODE (val) == FIXED_CST)
+                       list = tree_cons (NULL_TREE, val, list);
+                     else
+                       return NULL_TREE;
+                   }
+
+                 return build_vector (TREE_TYPE (rhs), nreverse (list));
+               }
 
               if (kind == tcc_reference)
                {
@@ -2654,6 +2678,25 @@ fold_gimple_assign (gimple_stmt_iterator *si)
                                     build_fold_addr_expr (tem));
          }
 
+       else if (TREE_CODE (rhs) == CONSTRUCTOR
+                && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE
+                && (CONSTRUCTOR_NELTS (rhs)
+                    == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
+         {
+           /* Fold a constant vector CONSTRUCTOR to VECTOR_CST.  */
+           unsigned i;
+           tree val;
+
+           FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
+             if (TREE_CODE (val) != INTEGER_CST
+                 && TREE_CODE (val) != REAL_CST
+                 && TREE_CODE (val) != FIXED_CST)
+               return NULL_TREE;
+
+           return build_vector_from_ctor (TREE_TYPE (rhs),
+                                          CONSTRUCTOR_ELTS (rhs));
+         }
+
         /* If we couldn't fold the RHS, hand over to the generic
            fold routines.  */
         if (result == NULL_TREE)
@@ -3023,14 +3066,9 @@ optimize_stack_restore (gimple_stmt_iterator i)
     return NULL_TREE;
 
   stack_save_gsi = gsi_for_stmt (stack_save);
-  push_stmt_changes (gsi_stmt_ptr (&stack_save_gsi));
   rhs = build_int_cst (TREE_TYPE (gimple_call_arg (call, 0)), 0);
   if (!update_call_from_tree (&stack_save_gsi, rhs))
-    {
-      discard_stmt_changes (gsi_stmt_ptr (&stack_save_gsi));
-      return NULL_TREE;
-    }
-  pop_stmt_changes (gsi_stmt_ptr (&stack_save_gsi));
+    return NULL_TREE;
 
   /* No effect, so the statement will be deleted.  */
   return integer_zero_node;
@@ -3252,8 +3290,6 @@ execute_fold_all_builtins (void)
            }
 
           old_stmt = stmt;
-         push_stmt_changes (gsi_stmt_ptr (&i));
-
           if (!update_call_from_tree (&i, result))
            {
              gimplify_and_update_call_from_tree (&i, result);
@@ -3261,7 +3297,7 @@ execute_fold_all_builtins (void)
            }
 
          stmt = gsi_stmt (i);
-         pop_stmt_changes (gsi_stmt_ptr (&i));
+         update_stmt (stmt);
 
          if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt)
              && gimple_purge_dead_eh_edges (bb))