OSDN Git Service

2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
authorzadeck <zadeck@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 May 2008 20:48:07 +0000 (20:48 +0000)
committerzadeck <zadeck@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 May 2008 20:48:07 +0000 (20:48 +0000)
        PATCH rtl/7335
        PATCH rtl/33826
        * see.c (see_copy_insn): Copy new pure const attributes for new
        call.
        * c-decl.c (merge_decls): Ditto.
        * postreload.c (record_opr_changes): Change CONST_OR_PURE_CALL_P
        to RTL_CONST_OR_PURE_CALL_P.
        * tree.c (define_local_buitin): Rename DECL_IS_PURE to
        DECL_PURE_P.  Initialized DECL_LOOPING_CONST_PURE.
        (process_call_operands): Set tree_side_effects properly.
        * tree.h (TREE_READONLY_DECL_P): Removed.
        (DECL_IS_PURE): Renamed to DECL_PURE_P.
        (DECL_LOOPING_OR_CONST_P): New macro.
        (struct tree_function_decl): Added looping_const_or_pure_p.
        (ECF_*) Renumbered.
        (ECF_LOOPING_OR_CONST_P): New macro,
        * rtlanal.c (pure_const_p): Removed.
        * builtins.c (expand_builtin): Rename DECL_IS_PURE to DECL_PURE_P.
        * reorg.c (delete_prior_computation) Changed CONST_OR_PURE_CALL_P
        to RTL_CONST_CALL_P.
        * ipa-pure-const.c (pure_const_state_e): Added looping field.
        (check_decl, check_tree, check_call, scan_function): Initialize
        looping.
        (analyze_function): Rename DECL_IS_PURE to DECL_PURE_P.
        (static_execute): Set looping true for recursive functions.
        Undo setting state to IPA_NEITHER for recursive functions.
        * cse.c (cse_insn):
        * ifcvt.c (noce_can_store_speculate_p): Changed
        CONST_OR_PURE_CALL_P and pure_call_p to RTL_CONST_CALL_P or
        RTL_CONST_OR_PURE_CALL_P.
        * dse.c (scan_insn): Ditto.
        * local-alloc.c (validate_equiv_mem, memref_used_between_p): Ditto.
        * gcse.c (oprs_not_seen_p) Changed CONST_OR_PURE_CALL_P to
        RTL_CONST_OR_PURE_CALL_P.
        (store_killed_in_insn): Changed CONST_OR_PURE_CALL_P and
        pure_call_p to RTL_CONST_CALL_P.
        * gimplify.c (gimplify_call_expr): Clear side effects for
        non-looping pure and constant calls.
        * calls.c (emit_call_1): Set rtl flags from ecf flags.
        (flags_from_decl_or_type): Set ecf flags from decl flags.
        (initialize_argument_information): Turn off
        ECF_LOOPING_CONST_OR_PURE when turning off ECF_CONST.
        Change const to pure if callee_copies is true rather than just
        turning off const.
        (expand_call): Turn off ECF_LOOPING_PURE_CONST_CALL and remove old
        way of marking pure calls.
        (emit_library_call_value_1): Turn off ECF_LOOPING_PURE_CONST_CALL.
        Remove hack that was supposed to fix pr7335 and remove old
        way of marking pure calls.
        * emit-rtl.c (emit_copy_of_insn_after): Copy RTL_CONST_CALL_P,
        RTL_PURE_CALL_P, RTL_LOOPING_CONST_OR_PURE_CALL_P.
        * cselib.c (cselib_process_insn): Changed CONST_OR_PURE_CALL_P to
        RTL_CONST_OR_PURE_CALL_P.
        * tree-ssa-pre.c (can_value_number_call): Fixed spacing.
        * loop-invariant.c (find_exits, find_invariant_bb): Changed
        CONST_OR_PURE_CALL_P to RTL_CONST_OR_PURE_CALL_P.
        * sched-deps.c (schedule_analyze): Ditto.
        * rtl.h (struct rtx_def): Use call field, unchanging field, and
        return_val field of calls to represent pure and const function
        info.
        (CONST_OR_PURE_CALL_P): Deleted macro.
        (RTL_CONST_CALL_P, RTL_PURE_CALL_P,
        RTL_LOOPING_CONST_OR_PURE_CALL_P, RTL_CONST_OR_PURE_P): New macros.
        * tree-inline.c (copy_body_r): Changed TREE_READONLY_DECL_P to
        TREE_READONLY.
        * tree-optimize.c (execute_fixup_cfg): Added test for
        ECF_LOOPING_CONST_OR_PURE.
        * c-common.c (handle_pure_attribute): Changed DECL_IS_PURE to
        DECL_PURE_P.
        * tree-cfg.c (update_call_expr_flags): Do not clear tree side
        effects for looping pure or const calls.
        (verify_gimple_expr): Added verification code.
        * config/alpha/alpha.c (alpha_legitimize_address,
        alpha_emit_xfloating_libcall): Changed CONST_OR_PURE_CALL_P to
        RTL_CONST_CALL_P.
        * config/s390/s390.c (s390_emit_tls_call_insn): Ditto.
        * config/rs6000/rs6000.c (rs6000_legitimize_tls_address): Ditto.
        * config/mips/mips.c (mips_call_tls_get_addr): Ditto.
        * cfgrtl.c (need_fake_edge_p): Changed CONST_OR_PURE_CALL_P to
        RTL_CONST_OR_PURE_CALL_P.
        * dce.c (deletable_insn_p): Allow non looping, non sibling, pure
        and const calls to be deleted.

java:
2008-05-07  Kenneth Zadeck <zadeck@naturalbridge.com>

* decl.c (java_init_decl_processing): Change DECL_IS_PURE to
DECL_PURE_P.

cp:
2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>

 * decl.c (duplicate_decls): Merge in DECL_PURE_P, TREE_READONLY,
 DECL_LOOPING_CONST_OR_PURE_P attributes.
 * rtti.c (build_dynamic_cast_1): Rename DECL_IS_PURE to
 DECL_PURE_P.

gfortran:
2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>

 * trans-decl.c (gfc_get_extern_function_decl, build_function_decl):
 Rename DECL_IS_PURE to DECL_PURE_P.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@135053 138bc75d-0d04-0410-961f-82ee72b054a4

41 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/c-common.c
gcc/c-decl.c
gcc/calls.c
gcc/cfgrtl.c
gcc/config/alpha/alpha.c
gcc/config/i386/i386.c
gcc/config/mips/mips.c
gcc/config/rs6000/rs6000.c
gcc/config/s390/s390.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/rtti.c
gcc/cse.c
gcc/cselib.c
gcc/dce.c
gcc/dse.c
gcc/emit-rtl.c
gcc/fortran/ChangeLog
gcc/fortran/trans-decl.c
gcc/gcse.c
gcc/gimplify.c
gcc/ifcvt.c
gcc/ipa-pure-const.c
gcc/java/ChangeLog
gcc/java/decl.c
gcc/local-alloc.c
gcc/loop-invariant.c
gcc/postreload-gcse.c
gcc/reorg.c
gcc/rtl.h
gcc/rtlanal.c
gcc/sched-deps.c
gcc/see.c
gcc/tree-cfg.c
gcc/tree-inline.c
gcc/tree-optimize.c
gcc/tree-ssa-pre.c
gcc/tree.c
gcc/tree.h

index 32ee2a6..1104f77 100644 (file)
@@ -1,3 +1,89 @@
+2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
+
+        PATCH rtl/7335
+        PATCH rtl/33826
+        * see.c (see_copy_insn): Copy new pure const attributes for new
+        call.
+        * c-decl.c (merge_decls): Ditto.
+        * postreload.c (record_opr_changes): Change CONST_OR_PURE_CALL_P
+        to RTL_CONST_OR_PURE_CALL_P.
+        * tree.c (define_local_buitin): Rename DECL_IS_PURE to
+        DECL_PURE_P.  Initialized DECL_LOOPING_CONST_PURE.
+        (process_call_operands): Set tree_side_effects properly.
+        * tree.h (TREE_READONLY_DECL_P): Removed.
+        (DECL_IS_PURE): Renamed to DECL_PURE_P.
+        (DECL_LOOPING_OR_CONST_P): New macro.
+        (struct tree_function_decl): Added looping_const_or_pure_p.
+        (ECF_*) Renumbered.
+        (ECF_LOOPING_OR_CONST_P): New macro,
+        * rtlanal.c (pure_const_p): Removed.
+        * builtins.c (expand_builtin): Rename DECL_IS_PURE to DECL_PURE_P.
+        * reorg.c (delete_prior_computation) Changed CONST_OR_PURE_CALL_P
+        to RTL_CONST_CALL_P.
+        * ipa-pure-const.c (pure_const_state_e): Added looping field.
+        (check_decl, check_tree, check_call, scan_function): Initialize
+        looping.
+        (analyze_function): Rename DECL_IS_PURE to DECL_PURE_P.
+        (static_execute): Set looping true for recursive functions.
+        Undo setting state to IPA_NEITHER for recursive functions.
+        * cse.c (cse_insn): 
+        * ifcvt.c (noce_can_store_speculate_p): Changed
+        CONST_OR_PURE_CALL_P and pure_call_p to RTL_CONST_CALL_P or 
+        RTL_CONST_OR_PURE_CALL_P.
+        * dse.c (scan_insn): Ditto.
+        * local-alloc.c (validate_equiv_mem, memref_used_between_p): Ditto.
+        * gcse.c (oprs_not_seen_p) Changed CONST_OR_PURE_CALL_P to
+        RTL_CONST_OR_PURE_CALL_P.
+        (store_killed_in_insn): Changed CONST_OR_PURE_CALL_P and
+        pure_call_p to RTL_CONST_CALL_P.
+        * gimplify.c (gimplify_call_expr): Clear side effects for
+        non-looping pure and constant calls.
+        * calls.c (emit_call_1): Set rtl flags from ecf flags.
+        (flags_from_decl_or_type): Set ecf flags from decl flags.
+        (initialize_argument_information): Turn off
+        ECF_LOOPING_CONST_OR_PURE when turning off ECF_CONST.
+        Change const to pure if callee_copies is true rather than just
+        turning off const.
+        (expand_call): Turn off ECF_LOOPING_PURE_CONST_CALL and remove old
+        way of marking pure calls.
+        (emit_library_call_value_1): Turn off ECF_LOOPING_PURE_CONST_CALL.
+        Remove hack that was supposed to fix pr7335 and remove old
+        way of marking pure calls.
+        * emit-rtl.c (emit_copy_of_insn_after): Copy RTL_CONST_CALL_P,
+        RTL_PURE_CALL_P, RTL_LOOPING_CONST_OR_PURE_CALL_P.
+        * cselib.c (cselib_process_insn): Changed CONST_OR_PURE_CALL_P to
+        RTL_CONST_OR_PURE_CALL_P.
+        * tree-ssa-pre.c (can_value_number_call): Fixed spacing.
+        * loop-invariant.c (find_exits, find_invariant_bb): Changed
+        CONST_OR_PURE_CALL_P to RTL_CONST_OR_PURE_CALL_P.
+        * sched-deps.c (schedule_analyze): Ditto.
+        * rtl.h (struct rtx_def): Use call field, unchanging field, and
+        return_val field of calls to represent pure and const function
+        info.
+        (CONST_OR_PURE_CALL_P): Deleted macro.
+        (RTL_CONST_CALL_P, RTL_PURE_CALL_P,
+        RTL_LOOPING_CONST_OR_PURE_CALL_P, RTL_CONST_OR_PURE_P): New macros.
+        * tree-inline.c (copy_body_r): Changed TREE_READONLY_DECL_P to
+        TREE_READONLY.
+        * tree-optimize.c (execute_fixup_cfg): Added test for
+        ECF_LOOPING_CONST_OR_PURE.
+        * c-common.c (handle_pure_attribute): Changed DECL_IS_PURE to
+        DECL_PURE_P.
+        * tree-cfg.c (update_call_expr_flags): Do not clear tree side
+        effects for looping pure or const calls.
+        (verify_gimple_expr): Added verification code. 
+        * config/alpha/alpha.c (alpha_legitimize_address,
+        alpha_emit_xfloating_libcall): Changed CONST_OR_PURE_CALL_P to
+        RTL_CONST_CALL_P.
+        * config/s390/s390.c (s390_emit_tls_call_insn): Ditto.
+        * config/rs6000/rs6000.c (rs6000_legitimize_tls_address): Ditto.
+        * config/mips/mips.c (mips_call_tls_get_addr): Ditto.
+        * cfgrtl.c (need_fake_edge_p): Changed CONST_OR_PURE_CALL_P to
+        RTL_CONST_OR_PURE_CALL_P.
+        * dce.c (deletable_insn_p): Allow non looping, non sibling, pure
+        and const calls to be deleted.
+
+
 2008-05-08  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/35714
index 2cb8fa0..61b4272 100644 (file)
@@ -6098,7 +6098,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
      none of its arguments are volatile, we can avoid expanding the
      built-in call and just evaluate the arguments for side-effects.  */
   if (target == const0_rtx
-      && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
+      && (DECL_PURE_P (fndecl) || TREE_READONLY (fndecl)))
     {
       bool volatilep = false;
       tree arg;
index 5858523..0c27b3e 100644 (file)
@@ -6019,7 +6019,7 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                       int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
-    DECL_IS_PURE (*node) = 1;
+    DECL_PURE_P (*node) = 1;
   /* ??? TODO: Support types.  */
   else
     {
index a51f76e..9abb4df 100644 (file)
@@ -1729,10 +1729,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
          DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
          TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
-         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
          DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
          DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
-         DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+         DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
          DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
        }
 
index 126037d..429ccb4 100644 (file)
@@ -359,21 +359,20 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
   /* Find the call we just emitted.  */
   call_insn = last_call_insn ();
 
-  /* Mark memory as used for "pure" function call.  */
-  if (ecf_flags & ECF_PURE)
-    call_fusage
-      = gen_rtx_EXPR_LIST
-       (VOIDmode,
-        gen_rtx_USE (VOIDmode,
-                     gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))),
-        call_fusage);
-
   /* Put the register usage information there.  */
   add_function_usage_to (call_insn, call_fusage);
 
   /* If this is a const call, then set the insn's unchanging bit.  */
-  if (ecf_flags & (ECF_CONST | ECF_PURE))
-    CONST_OR_PURE_CALL_P (call_insn) = 1;
+  if (ecf_flags & ECF_CONST)
+    RTL_CONST_CALL_P (call_insn) = 1;
+
+  /* If this is a pure call, then set the insn's unchanging bit.  */
+  if (ecf_flags & ECF_PURE)
+    RTL_PURE_CALL_P (call_insn) = 1;
+
+  /* If this is a const call, then set the insn's unchanging bit.  */
+  if (ecf_flags & ECF_LOOPING_CONST_OR_PURE)
+    RTL_LOOPING_CONST_OR_PURE_CALL_P (call_insn) = 1;
 
   /* If this call can't throw, attach a REG_EH_REGION reg note to that
      effect.  */
@@ -580,9 +579,13 @@ flags_from_decl_or_type (const_tree exp)
       if (DECL_IS_RETURNS_TWICE (exp))
        flags |= ECF_RETURNS_TWICE;
 
-      /* The function exp may have the `pure' attribute.  */
-      if (DECL_IS_PURE (exp))
+      /* Process the pure and const attributes.  */
+      if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
+       flags |= ECF_CONST;
+      if (DECL_PURE_P (exp))
        flags |= ECF_PURE;
+      if (DECL_LOOPING_CONST_OR_PURE_P (exp))
+       flags |= ECF_LOOPING_CONST_OR_PURE;
 
       if (DECL_IS_NOVOPS (exp))
        flags |= ECF_NOVOPS;
@@ -590,9 +593,6 @@ flags_from_decl_or_type (const_tree exp)
       if (TREE_NOTHROW (exp))
        flags |= ECF_NOTHROW;
 
-      if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
-       flags |= ECF_CONST;
-
       flags = special_function_p (exp, flags);
     }
   else if (TYPE_P (exp) && TYPE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
@@ -1038,7 +1038,9 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
              args[i].tree_value = build_fold_addr_expr (args[i].tree_value);
              type = TREE_TYPE (args[i].tree_value);
 
-             *ecf_flags &= ~(ECF_CONST | ECF_LIBCALL_BLOCK);
+             if (*ecf_flags & ECF_CONST)
+               *ecf_flags &= ~(ECF_CONST | ECF_LOOPING_CONST_OR_PURE);
+             *ecf_flags &= ~ECF_LIBCALL_BLOCK;
            }
          else
            {
@@ -1073,10 +1075,19 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
 
              store_expr (args[i].tree_value, copy, 0, false);
 
-             if (callee_copies)
-               *ecf_flags &= ~(ECF_CONST | ECF_LIBCALL_BLOCK);
-             else
-               *ecf_flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+             *ecf_flags &= ~(ECF_LIBCALL_BLOCK);
+
+             /* Just change the const function to pure and then let
+                the next test clear the pure based on
+                callee_copies.  */
+             if (*ecf_flags & ECF_CONST)
+               {
+                 *ecf_flags &= ~ECF_CONST;
+                 *ecf_flags |= ECF_PURE;
+               }
+
+             if (!callee_copies && *ecf_flags & ECF_PURE)
+               *ecf_flags &= ~(ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
 
              args[i].tree_value
                = build_fold_addr_expr (make_tree (type, copy));
@@ -2022,10 +2033,12 @@ expand_call (tree exp, rtx target, int ignore)
   if (AGGREGATE_TYPE_P (TREE_TYPE (exp)))
     warning (OPT_Waggregate_return, "function call has aggregate value");
 
-  /* If the result of a pure or const function call is ignored (or void),
-     and none of its arguments are volatile, we can avoid expanding the
-     call and just evaluate the arguments for side-effects.  */
+  /* If the result of a non looping pure or const function call is
+     ignored (or void), and none of its arguments are volatile, we can
+     avoid expanding the call and just evaluate the arguments for
+     side-effects.  */
   if ((flags & (ECF_CONST | ECF_PURE))
+      && (!(flags & ECF_LOOPING_CONST_OR_PURE))
       && (ignore || target == const0_rtx
          || TYPE_MODE (TREE_TYPE (exp)) == VOIDmode))
     {
@@ -2061,7 +2074,8 @@ expand_call (tree exp, rtx target, int ignore)
   if (aggregate_value_p (exp, fndecl))
     {
       /* This call returns a big structure.  */
-      flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+      flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE 
+                | ECF_LIBCALL_BLOCK);
 
 #ifdef PCC_STATIC_STRUCT_RETURN
       {
@@ -2852,13 +2866,6 @@ expand_call (tree exp, rtx target, int ignore)
                    note = gen_rtx_EXPR_LIST (VOIDmode,
                                              args[i].initial_value, note);
                  note = gen_rtx_EXPR_LIST (VOIDmode, funexp, note);
-
-                 if (flags & ECF_PURE)
-                   note = gen_rtx_EXPR_LIST (VOIDmode,
-                       gen_rtx_USE (VOIDmode,
-                                    gen_rtx_MEM (BLKmode,
-                                                 gen_rtx_SCRATCH (VOIDmode))),
-                       note);
                }
              emit_libcall_block (insns, temp, valreg, note);
 
@@ -3369,7 +3376,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
            mem_value = assign_temp (tfom, 0, 1, 1);
 #endif
          /* This call returns a big structure.  */
-         flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+         flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE 
+                    | ECF_LIBCALL_BLOCK);
        }
     }
   else
@@ -3472,10 +3480,9 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
              end_sequence ();
              emit_insn (insns);
            }
-         flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
 
-         /* If this was a CONST function, it is now PURE since
-            it now reads memory.  */
+         /* If this was a CONST function, it is now PURE since it now
+            reads memory.  */
          if (flags & ECF_CONST)
            {
              flags &= ~ECF_CONST;
@@ -3901,14 +3908,6 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 
          insns = get_insns ();
          end_sequence ();
-
-         if (flags & ECF_PURE)
-           note = gen_rtx_EXPR_LIST (VOIDmode,
-                       gen_rtx_USE (VOIDmode,
-                                    gen_rtx_MEM (BLKmode,
-                                                 gen_rtx_SCRATCH (VOIDmode))),
-                       note);
-
          emit_libcall_block (insns, temp, valreg, note);
 
          valreg = temp;
index 4c17fe5..994fb16 100644 (file)
@@ -2745,7 +2745,7 @@ need_fake_edge_p (const_rtx insn)
   if ((CALL_P (insn)
        && !SIBLING_CALL_P (insn)
        && !find_reg_note (insn, REG_NORETURN, NULL)
-       && !CONST_OR_PURE_CALL_P (insn)))
+       && !(RTL_CONST_OR_PURE_CALL_P (insn))))
     return true;
 
   return ((GET_CODE (PATTERN (insn)) == ASM_OPERANDS
index ed44a88..21b0590 100644 (file)
@@ -986,7 +986,7 @@ alpha_legitimize_address (rtx x, rtx scratch,
          emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq));
          insn = gen_call_value_osf_tlsgd (r0, tga, seq);
          insn = emit_call_insn (insn);
-         CONST_OR_PURE_CALL_P (insn) = 1;
+         RTL_CONST_CALL_P (insn) = 1;
          use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
 
           insn = get_insns ();
@@ -1007,7 +1007,7 @@ alpha_legitimize_address (rtx x, rtx scratch,
          emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq));
          insn = gen_call_value_osf_tlsldm (r0, tga, seq);
          insn = emit_call_insn (insn);
-         CONST_OR_PURE_CALL_P (insn) = 1;
+         RTL_CONST_CALL_P (insn) = 1;
          use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
 
           insn = get_insns ();
@@ -3013,7 +3013,7 @@ alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[],
   tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
                                        const0_rtx, const0_rtx));
   CALL_INSN_FUNCTION_USAGE (tmp) = usage;
-  CONST_OR_PURE_CALL_P (tmp) = 1;
+  RTL_CONST_CALL_P (tmp) = 1;
 
   tmp = get_insns ();
   end_sequence ();
index 825bf3d..7d254fe 100644 (file)
@@ -7859,7 +7859,7 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
          insns = get_insns ();
          end_sequence ();
 
-         CONST_OR_PURE_CALL_P (insns) = 1;
+         RTL_CONST_CALL_P (insns) = 1;
          emit_libcall_block (insns, dest, rax, x);
        }
       else if (TARGET_64BIT && TARGET_GNU2_TLS)
@@ -7890,7 +7890,7 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
 
          note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
          note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
-         CONST_OR_PURE_CALL_P (insns) = 1;
+         RTL_CONST_CALL_P (insns) = 1;
          emit_libcall_block (insns, base, rax, note);
        }
       else if (TARGET_64BIT && TARGET_GNU2_TLS)
index 86072ac..de2e42a 100644 (file)
@@ -2371,7 +2371,7 @@ mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
   emit_insn (gen_rtx_SET (Pmode, a0,
                          gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc)));
   insn = mips_expand_call (v0, mips_tls_symbol, const0_rtx, const0_rtx, false);
-  CONST_OR_PURE_CALL_P (insn) = 1;
+  RTL_CONST_CALL_P (insn) = 1;
   use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
   insn = get_insns ();
 
index 20cfe95..2e0031a 100644 (file)
@@ -3902,7 +3902,7 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
          tga = gen_rtx_MEM (Pmode, rs6000_tls_get_addr ());
          insn = gen_call_value (r3, tga, const0_rtx, const0_rtx);
          insn = emit_call_insn (insn);
-         CONST_OR_PURE_CALL_P (insn) = 1;
+         RTL_CONST_CALL_P (insn) = 1;
          use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r3);
          insn = get_insns ();
          end_sequence ();
@@ -3920,7 +3920,7 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
          tga = gen_rtx_MEM (Pmode, rs6000_tls_get_addr ());
          insn = gen_call_value (r3, tga, const0_rtx, const0_rtx);
          insn = emit_call_insn (insn);
-         CONST_OR_PURE_CALL_P (insn) = 1;
+         RTL_CONST_CALL_P (insn) = 1;
          use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r3);
          insn = get_insns ();
          end_sequence ();
index 6dab692..95fee4d 100644 (file)
@@ -3178,7 +3178,7 @@ s390_emit_tls_call_insn (rtx result_reg, rtx tls_call)
                         gen_rtx_REG (Pmode, RETURN_REGNUM));
 
   use_reg (&CALL_INSN_FUNCTION_USAGE (insn), result_reg);
-  CONST_OR_PURE_CALL_P (insn) = 1;
+  RTL_CONST_CALL_P (insn) = 1;
 }
 
 /* ADDR contains a thread-local SYMBOL_REF.  Generate code to compute
index 5bbeda6..473db14 100644 (file)
@@ -1,3 +1,11 @@
+2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
+
+        * decl.c (duplicate_decls): Merge in DECL_PURE_P, TREE_READONLY,
+        DECL_LOOPING_CONST_OR_PURE_P attributes.
+        * rtti.c (build_dynamic_cast_1): Rename DECL_IS_PURE to
+        DECL_PURE_P.
+
+
 2008-05-02  Simon Baldwin <simonb@google.com>
 
        PR bootstrap/36108
index 221b300..8b9b211 100644 (file)
@@ -1802,11 +1802,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
          DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
          TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
-         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
          TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl);
          DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
          DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
-         DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+         DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
+         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+         DECL_LOOPING_CONST_OR_PURE_P (newdecl) 
+           |= DECL_LOOPING_CONST_OR_PURE_P (olddecl);
          /* Keep the old RTL.  */
          COPY_DECL_RTL (olddecl, newdecl);
        }
index 2d2ef5b..1dcd785 100644 (file)
@@ -707,7 +707,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
                   (NULL_TREE, ptrdiff_type_node, void_list_node))));
              tmp = build_function_type (ptr_type_node, tmp);
              dcast_fn = build_library_fn_ptr (name, tmp);
-             DECL_IS_PURE (dcast_fn) = 1;
+             DECL_PURE_P (dcast_fn) = 1;
              pop_abi_namespace ();
              dynamic_cast_node = dcast_fn;
            }
index ef135e9..23b6134 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -5249,7 +5249,7 @@ cse_insn (rtx insn, rtx libcall_insn)
 
   if (CALL_P (insn))
     {
-      if (! CONST_OR_PURE_CALL_P (insn))
+      if (!(RTL_CONST_OR_PURE_CALL_P (insn)))
        invalidate_memory ();
       invalidate_for_call ();
     }
index c4c77c2..5d49094 100644 (file)
@@ -1693,7 +1693,11 @@ cselib_process_insn (rtx insn)
                      GET_MODE (REG_VALUES (i)->elt->val_rtx))))
          cselib_invalidate_regno (i, reg_raw_mode[i]);
 
-      if (! CONST_OR_PURE_CALL_P (insn))
+      /* Since it is not clear how cselib is going to be used, be
+        conservative here and treat looping pure or const functions
+        as if they were regular functions.  */
+      if (RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)
+         || !(RTL_CONST_OR_PURE_CALL_P (insn)))
        cselib_invalidate_mem (callmem);
     }
 
index 7b2ffe9..403d099 100644 (file)
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -99,6 +99,15 @@ deletable_insn_p (rtx insn, bool fast)
   rtx body, x;
   int i;
 
+  /* We can delete dead const or pure calls as long as they do not
+     infinite loop and are not sibling calls.  The problem with
+     sibling calls is that it is hard to see the result.  */
+  if (CALL_P (insn) 
+      && (!SIBLING_CALL_P (insn))
+      && (RTL_CONST_OR_PURE_CALL_P (insn)
+         && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
+    return true;
+
   if (!NONJUMP_INSN_P (insn))
     return false;
 
index 6984e19..c228938 100644 (file)
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1967,7 +1967,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
       /* Const functions cannot do anything bad i.e. read memory,
         however, they can read their parameters which may have
         been pushed onto the stack.  */
-      if (CONST_OR_PURE_CALL_P (insn) && !pure_call_p (insn))
+      if (RTL_CONST_CALL_P (insn))
        {
          insn_info_t i_ptr = active_local_stores;
          insn_info_t last = NULL;
index 2fc2f92..aec0151 100644 (file)
@@ -5464,7 +5464,10 @@ emit_copy_of_insn_after (rtx insn, rtx after)
        CALL_INSN_FUNCTION_USAGE (new)
          = copy_insn (CALL_INSN_FUNCTION_USAGE (insn));
       SIBLING_CALL_P (new) = SIBLING_CALL_P (insn);
-      CONST_OR_PURE_CALL_P (new) = CONST_OR_PURE_CALL_P (insn);
+      RTL_CONST_CALL_P (new) = RTL_CONST_CALL_P (insn);
+      RTL_PURE_CALL_P (new) = RTL_PURE_CALL_P (insn);
+      RTL_LOOPING_CONST_OR_PURE_CALL_P (new) 
+       = RTL_LOOPING_CONST_OR_PURE_CALL_P (insn);
       break;
 
     default:
index 66873c0..4906bbe 100644 (file)
@@ -1,3 +1,8 @@
+2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
+
+        * trans-decl.c (gfc_get_extern_function_decl, build_function_decl):
+        Rename DECL_IS_PURE to DECL_PURE_P.
+
 2008-05-06  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
 
        * arith.c: (gfc_arith_concat, gfc_compare_string,
index d204579..6e0b542 100644 (file)
@@ -1197,7 +1197,7 @@ gfc_get_extern_function_decl (gfc_symbol * sym)
   if (sym->attr.pure || sym->attr.elemental)
     {
       if (sym->attr.function && !gfc_return_by_reference (sym))
-       DECL_IS_PURE (fndecl) = 1;
+       DECL_PURE_P (fndecl) = 1;
       /* TODO: check if pure SUBROUTINEs don't have INTENT(OUT)
         parameters and don't use alternate returns (is this
         allowed?). In that case, calls to them are meaningless, and
@@ -1324,7 +1324,7 @@ build_function_decl (gfc_symbol * sym)
         including an alternate return. In that case it can also be
         marked as PURE. See also in gfc_get_extern_function_decl().  */
       if (attr.function && !gfc_return_by_reference (sym))
-       DECL_IS_PURE (fndecl) = 1;
+       DECL_PURE_P (fndecl) = 1;
       TREE_SIDE_EFFECTS (fndecl) = 0;
     }
 
index 477d4d3..e881e86 100644 (file)
@@ -2309,7 +2309,7 @@ oprs_not_set_p (const_rtx x, const_rtx insn)
 static void
 mark_call (rtx insn)
 {
-  if (! CONST_OR_PURE_CALL_P (insn))
+  if (! RTL_CONST_OR_PURE_CALL_P (insn))
     record_last_mem_set_info (insn);
 }
 
@@ -5987,7 +5987,7 @@ store_killed_in_insn (const_rtx x, const_rtx x_regs, const_rtx insn, int after)
     {
       /* A normal or pure call might read from pattern,
         but a const call will not.  */
-      if (! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn))
+      if (RTL_CONST_CALL_P (insn))
        return true;
 
       /* But even a const call reads its parameters.  Check whether the
index e36d5db..fc90fa3 100644 (file)
@@ -2274,10 +2274,14 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
   /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
      decl.  This allows us to eliminate redundant or useless
      calls to "const" functions.  */
-  if (TREE_CODE (*expr_p) == CALL_EXPR
-      && (call_expr_flags (*expr_p) & (ECF_CONST | ECF_PURE)))
-    TREE_SIDE_EFFECTS (*expr_p) = 0;
-
+  if (TREE_CODE (*expr_p) == CALL_EXPR)
+    {
+      int flags = call_expr_flags (*expr_p);
+      if (flags & (ECF_CONST | ECF_PURE)
+         /* An infinite loop is considered a side effect.  */
+         && !(flags & (ECF_LOOPING_CONST_OR_PURE)))
+       TREE_SIDE_EFFECTS (*expr_p) = 0;
+    }
   return ret;
 }
 
index 98b707a..26ff968 100644 (file)
@@ -2168,9 +2168,7 @@ noce_can_store_speculate_p (basic_block top_bb, const_rtx mem)
             unconditionally before the barrier.  */
          if (INSN_P (insn)
              && (volatile_insn_p (PATTERN (insn))
-                 || (CALL_P (insn)
-                     && (!CONST_OR_PURE_CALL_P (insn)
-                         || pure_call_p (insn)))))
+                 || (CALL_P (insn) && (!RTL_CONST_CALL_P (insn)))))
            return false;
 
          if (memory_modified_in_insn_p (mem, insn))
index c180e35..a2c9206 100644 (file)
@@ -19,7 +19,8 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 /* This file mark functions as being either const (TREE_READONLY) or
-   pure (DECL_IS_PURE).
+   pure (DECL_PURE_P).  It can also set the a variant of these that
+   are allowed to infinite loop (DECL_LOOPING_CONST_PURE_P).
 
    This must be run after inlining decisions have been made since
    otherwise, the local sets will not contain information that is
@@ -69,6 +70,7 @@ enum pure_const_state_e
 struct funct_state_d 
 {
   enum pure_const_state_e pure_const_state;
+  bool looping;
   bool state_set_in_source;
 };
 
@@ -95,6 +97,7 @@ check_decl (funct_state local,
   if (lookup_attribute ("used", DECL_ATTRIBUTES (t)))
     {
       local->pure_const_state = IPA_NEITHER;
+      local->looping = false;
       return;
     }
 
@@ -103,6 +106,7 @@ check_decl (funct_state local,
   if (TREE_THIS_VOLATILE (t)) 
     { 
       local->pure_const_state = IPA_NEITHER;
+      local->looping = false;
       return;
     }
 
@@ -116,6 +120,7 @@ check_decl (funct_state local,
   if (checking_write) 
     {
       local->pure_const_state = IPA_NEITHER;
+      local->looping = false;
       return;
     }
 
@@ -174,6 +179,7 @@ check_tree (funct_state local, tree t, bool checking_write)
   if (TREE_THIS_VOLATILE (t))
     {
       local->pure_const_state = IPA_NEITHER;
+      local->looping = false;
       return;
     }
 
@@ -199,6 +205,7 @@ check_tree (funct_state local, tree t, bool checking_write)
       if (checking_write) 
        {
          local->pure_const_state = IPA_NEITHER;
+         local->looping = false;
          return;
        }
       else if (local->pure_const_state == IPA_CONST)
@@ -346,7 +353,10 @@ check_call (funct_state local, tree call_expr)
       /* When bad things happen to bad functions, they cannot be const
         or pure.  */
       if (setjmp_call_p (callee_t))
-       local->pure_const_state = IPA_NEITHER;
+       {
+         local->pure_const_state = IPA_NEITHER;
+         local->looping = false;
+       }
 
       if (DECL_BUILT_IN_CLASS (callee_t) == BUILT_IN_NORMAL)
        switch (DECL_FUNCTION_CODE (callee_t))
@@ -354,6 +364,7 @@ check_call (funct_state local, tree call_expr)
          case BUILT_IN_LONGJMP:
          case BUILT_IN_NONLOCAL_GOTO:
            local->pure_const_state = IPA_NEITHER;
+           local->looping = false;
            break;
          default:
            break;
@@ -480,7 +491,10 @@ scan_function (tree *tp,
     case LABEL_EXPR:
       if (DECL_NONLOCAL (TREE_OPERAND (t, 0)))
        /* Target of long jump. */
-       local->pure_const_state = IPA_NEITHER;
+       {
+         local->pure_const_state = IPA_NEITHER;
+         local->looping = false;
+       }
       break;
 
     case CALL_EXPR: 
@@ -513,6 +527,10 @@ analyze_function (struct cgraph_node *fn)
 
   l->pure_const_state = IPA_CONST;
   l->state_set_in_source = false;
+  if (DECL_LOOPING_CONST_OR_PURE_P (decl))
+    l->looping = true;
+  else
+    l->looping = false;
 
   /* If this function does not return normally or does not bind local,
      do not touch this unless it has been marked as const or pure by the
@@ -529,7 +547,7 @@ analyze_function (struct cgraph_node *fn)
       l->pure_const_state = IPA_CONST;
       l->state_set_in_source = true;
     }
-  if (DECL_IS_PURE (decl))
+  if (DECL_PURE_P (decl))
     {
       l->pure_const_state = IPA_PURE;
       l->state_set_in_source = true;
@@ -644,6 +662,7 @@ static_execute (void)
   for (i = 0; i < order_pos; i++ )
     {
       enum pure_const_state_e pure_const_state = IPA_CONST;
+      bool looping = false;
       int count = 0;
       node = order[i];
 
@@ -655,6 +674,9 @@ static_execute (void)
          if (pure_const_state < w_l->pure_const_state)
            pure_const_state = w_l->pure_const_state;
 
+         if (w_l->looping)
+           looping = true;
+
          if (pure_const_state == IPA_NEITHER) 
            break;
 
@@ -663,24 +685,8 @@ static_execute (void)
              struct cgraph_edge *e;
              count++;
 
-             /* FIXME!!!  Because of pr33826, we cannot have either
-                immediate or transitive recursive functions marked as
-                pure or const because dce can delete a function that
-                is in reality an infinite loop.  A better solution
-                than just outlawing them is to add another bit the
-                functions to distinguish recursive from non recursive
-                pure and const function.  This would allow the
-                recursive ones to be cse'd but not dce'd.  In this
-                same vein, we could allow functions with loops to
-                also be cse'd but not dce'd.
-
-                Unfortunately we are late in stage 3, and the fix
-                described above is is not appropriate.  */
              if (count > 1)
-               {
-                 pure_const_state = IPA_NEITHER;
-                 break;
-               }
+               looping = true;
                    
              for (e = w->callees; e; e = e->next_callee) 
                {
@@ -688,13 +694,8 @@ static_execute (void)
                  /* Only look at the master nodes and skip external nodes.  */
                  y = cgraph_master_clone (y);
 
-                 /* Check for immediate recursive functions.  See the
-                    FIXME above.  */
                  if (w == y)
-                   {
-                     pure_const_state = IPA_NEITHER;
-                     break;
-                   }
+                   looping = true;
                  if (y)
                    {
                      funct_state y_l = get_function_state (y);
@@ -702,6 +703,8 @@ static_execute (void)
                        pure_const_state = y_l->pure_const_state;
                      if (pure_const_state == IPA_NEITHER) 
                        break;
+                     if (y_l->looping)
+                       looping = true;
                    }
                }
            }
@@ -724,15 +727,19 @@ static_execute (void)
                {
                case IPA_CONST:
                  TREE_READONLY (w->decl) = 1;
+                 DECL_LOOPING_CONST_OR_PURE_P (w->decl) = looping;
                  if (dump_file)
-                   fprintf (dump_file, "Function found to be const: %s\n",  
+                   fprintf (dump_file, "Function found to be %sconst: %s\n",  
+                            looping ? "looping " : "",
                             lang_hooks.decl_printable_name(w->decl, 2)); 
                  break;
                  
                case IPA_PURE:
-                 DECL_IS_PURE (w->decl) = 1;
+                 DECL_PURE_P (w->decl) = 1;
+                 DECL_LOOPING_CONST_OR_PURE_P (w->decl) = looping;
                  if (dump_file)
-                   fprintf (dump_file, "Function found to be pure: %s\n",  
+                   fprintf (dump_file, "Function found to be %spure: %s\n",  
+                            looping ? "looping " : "",
                             lang_hooks.decl_printable_name(w->decl, 2)); 
                  break;
                  
index a9487a9..411806a 100644 (file)
@@ -1,3 +1,8 @@
+2008-05-07  Kenneth Zadeck <zadeck@naturalbridge.com>
+
+       * decl.c (java_init_decl_processing): Change DECL_IS_PURE to
+       DECL_PURE_P.
+
 2008-04-23  Paolo Bonzini  <bonzini@gnu.org>
 
        * class.c (build_utf8_ref): Don't set TREE_INVARIANT.
index d449e39..fcc1c12 100644 (file)
@@ -906,7 +906,7 @@ java_init_decl_processing (void)
     = add_builtin_function ("_Jv_ResolvePoolEntry",
                            build_function_type (ptr_type_node, t),
                            0,NOT_BUILT_IN, NULL, NULL_TREE);
-  DECL_IS_PURE (soft_resolvepoolentry_node) = 1;
+  DECL_PURE_P (soft_resolvepoolentry_node) = 1;
   throw_node = add_builtin_function ("_Jv_Throw",
                                     build_function_type (void_type_node, t),
                                     0, NOT_BUILT_IN, NULL, NULL_TREE);
@@ -1000,7 +1000,7 @@ java_init_decl_processing (void)
     = add_builtin_function ("_Jv_IsInstanceOf",
                            build_function_type (boolean_type_node, t),
                            0, NOT_BUILT_IN, NULL, NULL_TREE);
-  DECL_IS_PURE (soft_instanceof_node) = 1;
+  DECL_PURE_P (soft_instanceof_node) = 1;
   t = tree_cons (NULL_TREE, object_ptr_type_node,
                 tree_cons (NULL_TREE, object_ptr_type_node, endlink));
   soft_checkarraystore_node
@@ -1014,7 +1014,7 @@ java_init_decl_processing (void)
     = add_builtin_function ("_Jv_LookupInterfaceMethodIdx",
                            build_function_type (ptr_type_node, t),
                            0, NOT_BUILT_IN, NULL, NULL_TREE);
-  DECL_IS_PURE (soft_lookupinterfacemethod_node) = 1;
+  DECL_PURE_P (soft_lookupinterfacemethod_node) = 1;
   t = tree_cons (NULL_TREE, ptr_type_node,
                 tree_cons (NULL_TREE, ptr_type_node,
                            tree_cons (NULL_TREE, ptr_type_node, endlink)));
index af97caf..9194d11 100644 (file)
@@ -505,7 +505,7 @@ validate_equiv_mem (rtx start, rtx reg, rtx memref)
        return 1;
 
       if (CALL_P (insn) && ! MEM_READONLY_P (memref)
-         && ! CONST_OR_PURE_CALL_P (insn))
+         && ! RTL_CONST_OR_PURE_CALL_P (insn))
        return 0;
 
       note_stores (PATTERN (insn), validate_equiv_mem_from_store, NULL);
@@ -781,9 +781,7 @@ memref_used_between_p (rtx memref, rtx start, rtx end)
        return 1;
 
       /* Nonconst functions may access memory.  */
-      if (CALL_P (insn)
-         && (! CONST_OR_PURE_CALL_P (insn)
-             || pure_call_p (insn)))
+      if (CALL_P (insn) && (! RTL_CONST_CALL_P (insn)))
        return 1;
     }
 
index f043884..c586cf9 100644 (file)
@@ -563,7 +563,8 @@ find_exits (struct loop *loop, basic_block *body,
          FOR_BB_INSNS (body[i], insn)
            {
              if (CALL_P (insn)
-                 && !CONST_OR_PURE_CALL_P (insn))
+                 && (RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)
+                     || !RTL_CONST_OR_PURE_CALL_P (insn)))
                {
                  has_call = true;
                  bitmap_set_bit (may_exit, i);
@@ -904,7 +905,8 @@ find_invariants_bb (basic_block bb, bool always_reached, bool always_executed)
 
       if (always_reached
          && CALL_P (insn)
-         && !CONST_OR_PURE_CALL_P (insn))
+         && (RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)
+             || ! RTL_CONST_OR_PURE_CALL_P (insn)))
        always_reached = false;
     }
 }
index ef78fde..4dc312d 100644 (file)
@@ -758,7 +758,7 @@ record_opr_changes (rtx insn)
              }
          }
 
-      if (! CONST_OR_PURE_CALL_P (insn))
+      if (! RTL_CONST_OR_PURE_CALL_P (insn))
        record_last_mem_set_info (insn);
     }
 }
index 7739509..c20c337 100644 (file)
@@ -3155,7 +3155,7 @@ delete_prior_computation (rtx note, rtx insn)
       /* If we reach a CALL which is not calling a const function
         or the callee pops the arguments, then give up.  */
       if (CALL_P (our_prev)
-         && (! CONST_OR_PURE_CALL_P (our_prev)
+         && (! RTL_CONST_CALL_P (our_prev)
              || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
        break;
 
index aaa1a92..b747a27 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -253,14 +253,17 @@ struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
      In a CODE_LABEL, part of the two-bit alternate entry field.  */
   unsigned int jump : 1;
   /* In a CODE_LABEL, part of the two-bit alternate entry field.
-     1 in a MEM if it cannot trap.  */
+     1 in a MEM if it cannot trap.  
+     1 in a CALL_INSN logically equivalent to
+       ECF_LOOPING_CONST_OR_PURE and DECL_LOOPING_CONST_OR_PURE_P. */
   unsigned int call : 1;
   /* 1 in a REG, MEM, or CONCAT if the value is set at most once, anywhere.
      1 in a SUBREG if it references an unsigned object whose mode has been
      from a promoted to a wider mode.
      1 in a SYMBOL_REF if it addresses something in the per-function
      constants pool.
-     1 in a CALL_INSN, NOTE, or EXPR_LIST for a const or pure call.
+     1 in a CALL_INSN logically equivalent to ECF_CONST and TREE_READONLY. 
+     1 in a NOTE, or EXPR_LIST for a const call.
      1 in a JUMP_INSN, CALL_INSN, or INSN of an annulling branch.  */
   unsigned int unchanging : 1;
   /* 1 in a MEM or ASM_OPERANDS expression if the memory reference is volatile.
@@ -303,7 +306,8 @@ struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
   unsigned frame_related : 1;
   /* 1 in a REG or PARALLEL that is the current function's return value.
      1 in a MEM if it refers to a scalar.
-     1 in a SYMBOL_REF for a weak symbol.  */
+     1 in a SYMBOL_REF for a weak symbol. 
+     1 in a CALL_INSN logically equivalent to ECF_PURE and DECL_PURE_P. */ 
   unsigned return_val : 1;
 
   /* The first element of the operands of this rtx.
@@ -765,10 +769,24 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
   (RTL_FLAG_CHECK6("INSN_DELETED_P", (RTX), INSN, CALL_INSN, JUMP_INSN,        \
                   CODE_LABEL, BARRIER, NOTE)->volatil)
 
+/* 1 if RTX is a call to a const function.  Built from ECF_CONST and
+   TREE_READONLY.  */
+#define RTL_CONST_CALL_P(RTX)                                  \
+  (RTL_FLAG_CHECK1("RTL_CONST_CALL_P", (RTX), CALL_INSN)->unchanging)
+
+/* 1 if RTX is a call to a pure function.  Built from ECF_PURE and
+   DECL_PURE_P.  */
+#define RTL_PURE_CALL_P(RTX)                                   \
+  (RTL_FLAG_CHECK1("RTL_PURE_CALL_P", (RTX), CALL_INSN)->return_val)
+
 /* 1 if RTX is a call to a const or pure function.  */
-#define CONST_OR_PURE_CALL_P(RTX)                                      \
-  (RTL_FLAG_CHECK3("CONST_OR_PURE_CALL_P", (RTX), CALL_INSN, NOTE,     \
-                  EXPR_LIST)->unchanging)
+#define RTL_CONST_OR_PURE_CALL_P(RTX) \
+  (RTL_CONST_CALL_P(RTX) || RTL_PURE_CALL_P(RTX))
+
+/* 1 if RTX is a call to a looping const or pure function.  Built from
+   ECF_LOOPING_CONST_OR_PURE and DECL_LOOPING_CONST_OR_PURE_P.  */
+#define RTL_LOOPING_CONST_OR_PURE_CALL_P(RTX)                                  \
+  (RTL_FLAG_CHECK1("CONST_OR_PURE_CALL_P", (RTX), CALL_INSN)->call)
 
 /* 1 if RTX is a call_insn for a sibling call.  */
 #define SIBLING_CALL_P(RTX)                                            \
@@ -1733,7 +1751,6 @@ extern rtx find_reg_equal_equiv_note (const_rtx);
 extern rtx find_constant_src (const_rtx);
 extern int find_reg_fusage (const_rtx, enum rtx_code, const_rtx);
 extern int find_regno_fusage (const_rtx, enum rtx_code, unsigned int);
-extern int pure_call_p (const_rtx);
 extern void remove_note (rtx, const_rtx);
 extern void remove_reg_equal_equiv_notes (rtx);
 extern int side_effects_p (const_rtx);
index 93833a3..f0dc512 100644 (file)
@@ -1846,29 +1846,6 @@ find_regno_fusage (const_rtx insn, enum rtx_code code, unsigned int regno)
   return 0;
 }
 
-/* Return true if INSN is a call to a pure function.  */
-
-int
-pure_call_p (const_rtx insn)
-{
-  const_rtx link;
-
-  if (!CALL_P (insn) || ! CONST_OR_PURE_CALL_P (insn))
-    return 0;
-
-  /* Look for the note that differentiates const and pure functions.  */
-  for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
-    {
-      rtx u, m;
-
-      if (GET_CODE (u = XEXP (link, 0)) == USE
-         && MEM_P (m = XEXP (u, 0)) && GET_MODE (m) == BLKmode
-         && GET_CODE (XEXP (m, 0)) == SCRATCH)
-       return 1;
-    }
-
-  return 0;
-}
 \f
 /* Remove register note NOTE from the REG_NOTES of INSN.  */
 
index 1f85781..b62797f 100644 (file)
@@ -2304,7 +2304,8 @@ sched_analyze (struct deps *deps, rtx head, rtx tail)
             all pending reads and writes, and start new dependencies starting
             from here.  But only flush writes for constant calls (which may
             be passed a pointer to something we haven't written yet).  */
-         flush_pending_lists (deps, insn, true, !CONST_OR_PURE_CALL_P (insn));
+         flush_pending_lists (deps, insn, true, 
+                              ! RTL_CONST_OR_PURE_CALL_P (insn));
 
          /* Remember the last function call for limiting lifetimes.  */
          free_INSN_LIST_list (&deps->last_function_call);
index c6f584c..6e5260b 100644 (file)
--- a/gcc/see.c
+++ b/gcc/see.c
@@ -2430,7 +2430,10 @@ see_copy_insn (rtx insn)
        CALL_INSN_FUNCTION_USAGE (ret)
          = copy_rtx (CALL_INSN_FUNCTION_USAGE (insn));
       SIBLING_CALL_P (ret) = SIBLING_CALL_P (insn);
-      CONST_OR_PURE_CALL_P (ret) = CONST_OR_PURE_CALL_P (insn);
+      RTL_CONST_CALL_P (ret) = RTL_CONST_CALL_P (insn);
+      RTL_PURE_CALL_P (ret) = RTL_PURE_CALL_P (insn);
+      RTL_LOOPING_CONST_OR_PURE_CALL_P (ret) 
+       = RTL_LOOPING_CONST_OR_PURE_CALL_P (insn);
     }
   else
     gcc_unreachable ();
index add7362..f559030 100644 (file)
@@ -1792,9 +1792,11 @@ static void
 update_call_expr_flags (tree call)
 {
   tree decl = get_callee_fndecl (call);
+  int flags;
   if (!decl)
     return;
-  if (call_expr_flags (call) & (ECF_CONST | ECF_PURE))
+  flags = call_expr_flags (call);
+  if (flags & (ECF_CONST | ECF_PURE) && !(flags & ECF_LOOPING_CONST_OR_PURE))
     TREE_SIDE_EFFECTS (call) = 0;
   if (TREE_NOTHROW (decl))
     TREE_NOTHROW (call) = 1;
@@ -3906,7 +3908,19 @@ verify_gimple_expr (tree expr)
     case CALL_EXPR:
       /* FIXME.  The C frontend passes unpromoted arguments in case it
         didn't see a function declaration before the call.  */
-      return false;
+      {
+       tree decl = CALL_EXPR_FN (expr);
+
+       if (TREE_CODE (decl) == FUNCTION_DECL 
+           && DECL_LOOPING_CONST_OR_PURE_P (decl)
+           && (!DECL_PURE_P (decl))
+           && (!TREE_READONLY (decl)))
+         {
+           error ("invalid pure const state for function");
+           return true;
+         }
+       return false;
+      }
 
     case OBJ_TYPE_REF:
       /* FIXME.  */
index 687ed95..28727cc 100644 (file)
@@ -671,7 +671,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
            {
              value = *n;
              STRIP_TYPE_NOPS (value);
-             if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
+             if (TREE_CONSTANT (value) || TREE_READONLY (value))
                {
                  *tp = build_empty_stmt ();
                  return copy_body_r (tp, walk_subtrees, data);
index 8c53e6f..2703536 100644 (file)
@@ -299,7 +299,8 @@ execute_fixup_cfg (void)
            tree call = get_call_expr_in (stmt);
            tree decl = call ? get_callee_fndecl (call) : NULL;
 
-           if (decl && call_expr_flags (call) & (ECF_CONST | ECF_PURE)
+           if (decl && call_expr_flags (call) & (ECF_CONST | ECF_PURE 
+                                                 | ECF_LOOPING_CONST_OR_PURE)
                && TREE_SIDE_EFFECTS (call))
              {
                if (gimple_in_ssa_p (cfun))
index 13c4e97..a8db47d 100644 (file)
@@ -2077,7 +2077,7 @@ can_value_number_call (tree stmt)
 {
   tree call = get_call_expr_in (stmt);
 
-  if (call_expr_flags (call)  & (ECF_PURE | ECF_CONST))
+  if (call_expr_flags (call) & (ECF_PURE | ECF_CONST))
     return true;
   return false;
 }
index 73adaa1..182d86a 100644 (file)
@@ -7373,7 +7373,9 @@ local_define_builtin (const char *name, tree type, enum built_in_function code,
   if (ecf_flags & ECF_CONST)
     TREE_READONLY (decl) = 1;
   if (ecf_flags & ECF_PURE)
-    DECL_IS_PURE (decl) = 1;
+    DECL_PURE_P (decl) = 1;
+  if (ecf_flags & ECF_LOOPING_CONST_OR_PURE)
+    DECL_LOOPING_CONST_OR_PURE_P (decl) = 1;
   if (ecf_flags & ECF_NORETURN)
     TREE_THIS_VOLATILE (decl) = 1;
   if (ecf_flags & ECF_NOTHROW)
@@ -7766,7 +7768,7 @@ process_call_operands (tree t)
       /* Calls have side-effects, except those to const or
         pure functions.  */
       i = call_expr_flags (t);
-      if (!(i & (ECF_CONST | ECF_PURE)))
+      if ((i & ECF_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE)))
        side_effects = 1;
     }
   TREE_SIDE_EFFECTS (t) = side_effects;
index d52c760..0b4b443 100644 (file)
@@ -788,7 +788,7 @@ enum tree_node_structure_enum {
     &__t->phi.a[__i]; }))
 
 #define OMP_CLAUSE_ELT_CHECK(T, I) __extension__                       \
-(*({__typeof (T) const __t = (T);                                              \
+(*({__typeof (T) const __t = (T);                                      \
     const int __i = (I);                                               \
     if (TREE_CODE (__t) != OMP_CLAUSE)                                 \
       tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,        \
@@ -1281,13 +1281,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
 #define TREE_THIS_NOTRAP(NODE) ((NODE)->base.nothrow_flag)
 
 /* In a VAR_DECL, PARM_DECL or FIELD_DECL, or any kind of ..._REF node,
-   nonzero means it may not be the lhs of an assignment.  */
+   nonzero means it may not be the lhs of an assignment.  
+   Nonzero in a FUNCTION_DECL means this function should be treated
+   as "const" function (can only read its arguments).  */
 #define TREE_READONLY(NODE) (NON_TYPE_CHECK (NODE)->base.readonly_flag)
 
-/* Nonzero if NODE is a _DECL with TREE_READONLY set.  */
-#define TREE_READONLY_DECL_P(NODE)\
-       (DECL_P (NODE) && TREE_READONLY (NODE))
-
 /* Value of expression is constant.  Always on in all ..._CST nodes.  May
    also appear in an expression or decl where the value is constant.  */
 #define TREE_CONSTANT(NODE) (NON_TYPE_CHECK (NODE)->base.constant_flag)
@@ -3256,7 +3254,16 @@ struct tree_decl_non_common GTY(())
 
 /* Nonzero in a FUNCTION_DECL means this function should be treated
    as "pure" function (like const function, but may read global memory).  */
-#define DECL_IS_PURE(NODE) (FUNCTION_DECL_CHECK (NODE)->function_decl.pure_flag)
+#define DECL_PURE_P(NODE) (FUNCTION_DECL_CHECK (NODE)->function_decl.pure_flag)
+
+/* Nonzero only if one of TREE_READONLY or DECL_PURE_P is nonzero AND
+   the const or pure function may not terminate.  When this is nonzero
+   for a const or pure function, it can be dealt with by cse passes
+   but cannot be removed by dce passes since you are not allowed to
+   change an infinite looping program into one that terminates without
+   error.  */
+#define DECL_LOOPING_CONST_OR_PURE_P(NODE) \
+  (FUNCTION_DECL_CHECK (NODE)->function_decl.looping_const_or_pure_flag)
 
 /* Nonzero in a FUNCTION_DECL means this function should be treated
    as "novops" function (function that does not read global memory,
@@ -3354,7 +3361,6 @@ struct tree_function_decl GTY(())
   unsigned returns_twice_flag : 1;
   unsigned malloc_flag : 1;
   unsigned operator_new_flag : 1;
-  unsigned pure_flag : 1;
   unsigned declared_inline_flag : 1;
   unsigned regdecl_flag : 1;
 
@@ -3362,8 +3368,11 @@ struct tree_function_decl GTY(())
   unsigned no_instrument_function_entry_exit : 1;
   unsigned no_limit_stack : 1;
   unsigned disregard_inline_limits : 1;
+  unsigned pure_flag : 1;
+  unsigned looping_const_or_pure_flag : 1;
+
 
-  /* 4 bits left */
+  /* 3 bits left */
 };
 
 /* For a TYPE_DECL, holds the "original" type.  (TREE_TYPE has the copy.) */
@@ -4987,28 +4996,34 @@ extern tree build_duplicate_type (tree);
 
 /* Nonzero if this is a call to a function whose return value depends
    solely on its arguments, has no side effects, and does not read
-   global memory.  */
-#define ECF_CONST              1
+   global memory.  This corresponds to TREE_READONLY for function
+   decls.  */
+#define ECF_CONST                (1 << 0)
+/* Nonzero if this is a call to "pure" function (like const function,
+   but may read memory.  This corresponds to DECL_PURE_P for function
+   decls.  */
+#define ECF_PURE                 (1 << 1)
+/* Nonzero if this is ECF_CONST or ECF_PURE but cannot be proven to no
+   infinite loop.  This corresponds to DECL_LOOPING_CONST_OR_PURE_P
+   for function decls.*/
+#define ECF_LOOPING_CONST_OR_PURE (1 << 2)
 /* Nonzero if this call will never return.  */
-#define ECF_NORETURN           2
+#define ECF_NORETURN             (1 << 3)
 /* Nonzero if this is a call to malloc or a related function.  */
-#define ECF_MALLOC             4
+#define ECF_MALLOC               (1 << 4)
 /* Nonzero if it is plausible that this is a call to alloca.  */
-#define ECF_MAY_BE_ALLOCA      8
+#define ECF_MAY_BE_ALLOCA        (1 << 5)
 /* Nonzero if this is a call to a function that won't throw an exception.  */
-#define ECF_NOTHROW            16
+#define ECF_NOTHROW              (1 << 6)
 /* Nonzero if this is a call to setjmp or a related function.  */
-#define ECF_RETURNS_TWICE      32
+#define ECF_RETURNS_TWICE        (1 << 7)
 /* Nonzero if this call replaces the current stack frame.  */
-#define ECF_SIBCALL            64
-/* Nonzero if this is a call to "pure" function (like const function,
-   but may read memory.  */
-#define ECF_PURE               128
+#define ECF_SIBCALL              (1 << 8)
 /* Create libcall block around the call.  */
-#define ECF_LIBCALL_BLOCK      256
+#define ECF_LIBCALL_BLOCK        (1 << 9)
 /* Function does not read or write memory (but may have side effects, so
    it does not necessarily fit ECF_CONST).  */
-#define ECF_NOVOPS             512
+#define ECF_NOVOPS               (1 << 10)
 
 extern int flags_from_decl_or_type (const_tree);
 extern int call_expr_flags (const_tree);