OSDN Git Service

2010-07-06 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / ipa-pure-const.c
index da8d442..7417429 100644 (file)
@@ -324,7 +324,7 @@ check_op (funct_state local, tree t, bool checking_write)
       return;
     }
   else if (t
-          && INDIRECT_REF_P (t)
+          && (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF)
           && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
           && !ptr_deref_may_alias_global_p (TREE_OPERAND (t, 0)))
     {
@@ -420,6 +420,40 @@ worse_state (enum pure_const_state_e *state, bool *looping,
   *looping = MAX (*looping, looping2);
 }
 
+/* Recognize special cases of builtins that are by themself not pure or const
+   but function using them is.  */
+static bool
+special_builtlin_state (enum pure_const_state_e *state, bool *looping,
+                       tree callee)
+{
+  if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+    switch (DECL_FUNCTION_CODE (callee))
+      {
+       case BUILT_IN_RETURN:
+       case BUILT_IN_UNREACHABLE:
+       case BUILT_IN_ALLOCA:
+       case BUILT_IN_STACK_SAVE:
+       case BUILT_IN_STACK_RESTORE:
+       case BUILT_IN_EH_POINTER:
+       case BUILT_IN_EH_FILTER:
+       case BUILT_IN_UNWIND_RESUME:
+       case BUILT_IN_CXA_END_CLEANUP:
+       case BUILT_IN_EH_COPY_VALUES:
+       case BUILT_IN_FRAME_ADDRESS:
+       case BUILT_IN_APPLY:
+       case BUILT_IN_APPLY_ARGS:
+       case BUILT_IN_ARGS_INFO:
+         *looping = false;
+         *state = IPA_CONST;
+         return true;
+       case BUILT_IN_PREFETCH:
+         *looping = true;
+         *state = IPA_CONST;
+         return true;
+      }
+  return false;
+}
+
 /* Check the parameters of a function call to CALL_EXPR to see if
    there are any references in the parameters that are not allowed for
    pure or const functions.  Also check to see if this is either an
@@ -470,9 +504,15 @@ check_call (funct_state local, gimple call, bool ipa)
      graph.  */
   if (callee_t)
     {
-      /* built_in_return is really just an return statemnt.  */
-      if (gimple_call_builtin_p (call, BUILT_IN_RETURN))
-       return;
+      enum pure_const_state_e call_state;
+      bool call_looping;
+
+      if (special_builtlin_state (&call_state, &call_looping, callee_t))
+       {
+         worse_state (&local->pure_const_state, &local->looping,
+                      call_state, call_looping);
+         return;
+       }
       /* When bad things happen to bad functions, they cannot be const
         or pure.  */
       if (setjmp_call_p (callee_t))
@@ -903,7 +943,7 @@ pure_const_write_summary (cgraph_node_set set,
       node = csi_node (csi);
       if (node->analyzed && has_function_state (node))
        {
-         struct bitpack_d *bp;
+         struct bitpack_d bp;
          funct_state fs;
          int node_ref;
          lto_cgraph_encoder_t encoder;
@@ -916,14 +956,13 @@ pure_const_write_summary (cgraph_node_set set,
 
          /* Note that flags will need to be read in the opposite
             order as we are pushing the bitflags into FLAGS.  */
-         bp = bitpack_create ();
-         bp_pack_value (bp, fs->pure_const_state, 2);
-         bp_pack_value (bp, fs->state_previously_known, 2);
-         bp_pack_value (bp, fs->looping_previously_known, 1);
-         bp_pack_value (bp, fs->looping, 1);
-         bp_pack_value (bp, fs->can_throw, 1);
-         lto_output_bitpack (ob->main_stream, bp);
-         bitpack_delete (bp);
+         bp = bitpack_create (ob->main_stream);
+         bp_pack_value (&bp, fs->pure_const_state, 2);
+         bp_pack_value (&bp, fs->state_previously_known, 2);
+         bp_pack_value (&bp, fs->looping_previously_known, 1);
+         bp_pack_value (&bp, fs->looping, 1);
+         bp_pack_value (&bp, fs->can_throw, 1);
+         lto_output_bitpack (&bp);
        }
     }
 
@@ -958,7 +997,7 @@ pure_const_read_summary (void)
            {
              unsigned int index;
              struct cgraph_node *node;
-             struct bitpack_d *bp;
+             struct bitpack_d bp;
              funct_state fs;
              lto_cgraph_encoder_t encoder;
 
@@ -973,12 +1012,12 @@ pure_const_read_summary (void)
                 pushed into FLAGS).  */
              bp = lto_input_bitpack (ib);
              fs->pure_const_state
-                       = (enum pure_const_state_e) bp_unpack_value (bp, 2);
+                       = (enum pure_const_state_e) bp_unpack_value (&bp, 2);
              fs->state_previously_known
-                       = (enum pure_const_state_e) bp_unpack_value (bp, 2);
-             fs->looping_previously_known = bp_unpack_value (bp, 1);
-             fs->looping = bp_unpack_value (bp, 1);
-             fs->can_throw = bp_unpack_value (bp, 1);
+                       = (enum pure_const_state_e) bp_unpack_value (&bp, 2);
+             fs->looping_previously_known = bp_unpack_value (&bp, 1);
+             fs->looping = bp_unpack_value (&bp, 1);
+             fs->can_throw = bp_unpack_value (&bp, 1);
              if (dump_file)
                {
                  int flags = flags_from_decl_or_type (node->decl);
@@ -1002,7 +1041,6 @@ pure_const_read_summary (void)
                  if (fs->can_throw)
                    fprintf (dump_file,"  function is locally throwing\n");
                }
-             bitpack_delete (bp);
            }
 
          lto_destroy_simple_input_block (file_data,
@@ -1153,10 +1191,13 @@ propagate_pure_const (void)
                      edge_looping = y_l->looping;
                    }
                }
+             else if (special_builtlin_state (&edge_state, &edge_looping,
+                                              y->decl))
+               ;
              else
                state_from_flags (&edge_state, &edge_looping,
-                                 flags_from_decl_or_type (y->decl),
-                                 cgraph_edge_cannot_lead_to_return (e));
+                                 flags_from_decl_or_type (y->decl),
+                                 cgraph_edge_cannot_lead_to_return (e));
 
              /* Merge the results with what we already know.  */
              better_state (&edge_state, &edge_looping,