On Thu, 16 Mar 2023, Jakub Jelinek wrote:

> On Fri, Nov 25, 2022 at 09:26:34PM +0100, Richard Biener via Gcc-patches 
> wrote:
> > > We could
> > > probably keep tract if any instrumented code was ever inlined into a
> > > given function and perhaps just start ignoring attributes set on types?
> > 
> > But ignoring attributes on types makes all indirect calls not
> > const/pure annotatable (OK, they are not pure annotatable because of
> > the above bug).  I really don't see how to conservatively solve this
> > issue?
> 
> > Maybe we can ignore all pure/const when the cgraph state is
> > in profile-instrumented state?  Of course we have multiple "APIs"
> > to query that.
> 
> I think that's the way to go.  But we'd need to arrange somewhere during IPA
> to add vops to all those pure/const calls if -fprofile-generate (direct or
> indirect; not sure what exact flags) and after that make sure all our APIs
> don't return ECF_CONST, ECF_PURE or ECF_LOOPING_CONST_OR_PURE.
> Could be e.g.
>   if (whatever)
>     flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
> at the end of flags_from_decl_or_type, internal_fn_flags, what else?
> Although, perhaps internal_fn_flags don't need to change, because internal
> calls don't really have callees.
> 
> Or is just ECF_CONST enough given that ECF_PURE is on fndecls and not
> types?
> 
> Or perhaps just start ignoring TYPE_READONLY -> ECF_CONST in
> flags_from_decl_or_type if that flag is on?
> 
> Is that rewriting currently what tree_profiling does in the
>   /* Update call statements and rebuild the cgraph.  */
>   FOR_EACH_DEFINED_FUNCTION (node)
> spot where it calls update_stmt on all call statements?
> 
> If so, could we just set that global? flag instead or in addition to
> doing those node->set_const_flag (false, false); calls and
> change flags_from_decl_or_type, plus I guess lto1 should set that
> flag if it is global on start as well if
> !flag_auto_profile
> && (flag_branch_probabilities || flag_test_coverage || profile_arc_flag)
> ?
> 
> I think just ignoring ECF_CONST from TYPE_READONLY might be best, if we
> have external functions like builtins from libc/libm and don't have their
> bodies, we can still treat them as const, the only problem is with the
> indirect calls where we don't know if we do or don't have a body for
> the callees and whether we've instrumented those or not.

I think we want something reflected on the IL.  Because of LTO I think
we cannot ignore externs (or we have to do massaging at stream-in).

The following brute-force works for the testcase.  I suppose since
we leave const/pure set on functions without body in the compile-time
TU (and ignore LTO there) we could do the same here.

I also wonder if that whole function walk is necessary if not
profile_arc_flag || flag_test_coverage ...

Honza - does this look OK to you?  I'll test guarding the whole
outer loop with profile_arc_flag || flag_test_coverage separately.

diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc
index ea9d7a23443..c8789618f96 100644
--- a/gcc/tree-profile.cc
+++ b/gcc/tree-profile.cc
@@ -840,9 +840,29 @@ tree_profiling (void)
          gimple_stmt_iterator gsi;
          for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
            {
-             gimple *stmt = gsi_stmt (gsi);
-             if (is_gimple_call (stmt))
-               update_stmt (stmt);
+             gcall *call = dyn_cast <gcall *> (gsi_stmt (gsi));
+             if (!call)
+               continue;
+
+             if (profile_arc_flag || flag_test_coverage)
+               {
+             /* We do not clear pure/const on decls without body.  */
+             tree fndecl = gimple_call_fndecl (call);
+             if (fndecl && !gimple_has_body_p (fndecl))
+               continue;
+
+             /* Drop the const attribute from the call type (the pure
+                attribute is not available on types).  */
+             tree fntype = gimple_call_fntype (call);
+             if (fntype && TYPE_READONLY (fntype))
+               gimple_call_set_fntype (call, build_qualified_type
+                                               (fntype, (TYPE_QUALS 
(fntype)
+                                                         & 
~TYPE_QUAL_CONST)));
+               }
+
+             /* Update virtual operands of calls to no longer const/pure
+                functions.  */
+             update_stmt (call);
            }
        }
 

Reply via email to