Here's an idea that could make it easier to remove the "cfun" global.
"cfun" is a major piece of global state within gcc: it's the 5th most accessed variable in the build (accessed in ~4600 places within one stage of a build, based on [1]). This is an obstacle to making gcc's code be usable as a library. I can think of three approaches to "cfun": (a) status quo: a global variable, with macros to prevent direct assignment, and an API for changing cfun. (b) have a global "context" or "universe" object, and put cfun in there (perhaps with tricks to be able to make this a singleton in a non-library build, optimizing away the context lookups somehow - see [2] for discussion on this) (c) go through all of the places where cfun is used, and somehow ensure that they're passed in the data they need. Often it's not the function that's used, but its cfg. I think (c) is the ideal from a modularity perspective (it unlocks the ability to have optimization passes be working on different functions in different threads), but the most difficult. One part of the puzzle is that various header files in the build define macros that reference the "cfun" global, e.g.: #define n_basic_blocks (cfun->cfg->x_n_basic_blocks) This one isn't in block caps, which might mislead a new contributor into thinking it's a variable, rather than a macro, so there may be virtue in removing these macros for that reason alone. (I know that these confused me for a while when I first started writing my plugin) [3] So I had a go at removing these macros, to make usage of "cfun" be explicit. I wrote a script to do most of the gruntwork automatically: [4] The following patches introduce accessor methods to control_flow_graph, then remove all of the macros that reference cfun from basic-block.h, replacing all of the places that use them with explicit uses of "cfun->cfg->get_foo ()" as appropriate. There are various other headers that define macros that use cfun, but I thought I'd post this to get a sense of how maintainers feel about this approach. I notice that we're constantly accessing: some loop { ... use cfun->cfg->x_some_field; ... } Would it potentially be faster to replace some of these with: control_flow_graph &cfg = *cfun->cfg; some loop { ... use cfg.get_some_field () // assuming inlining of accessor ... } to avoid constantly derefing cfun->cfg? (That said, would -fstrict-aliasing be able to note that cfun->cfg doesn't change, or in a non-LTO build I'm guessing it can't make that assumption if the loop calls into functions it can't see inside?). I bootstrapped and tested the following on x86_64-unknown-linux-gnu against r199323, and it has the same test results as an unpatched bootstrap of that revision. If expanded to cover the other header files, this approach would at least make it explicit when we're using cfun, which may make approach (c) easier to implement (the "pass around the data we need" approach). (Potentially the fields in control_flow_graph could be made private also, but I haven't tested that out yet) Thoughts? Dave [1] http://gcc.gnu.org/ml/gcc/2013-05/msg00015.html [2] http://gcc.gnu.org/ml/gcc-patches/2013-05/msg01318.html [3] As an extra wrinkle, in testsuite/gcc.dg/tree-ssa/20041122-1.c there's a: extern int n_basic_blocks; that genuinely is a variable. [4] https://github.com/davidmalcolm/gcc-refactoring-scripts/blob/master/refactor_cfun.py along with a test suite: https://github.com/davidmalcolm/gcc-refactoring-scripts/blob/master/test_refactor_cfun.py David Malcolm (2): handwritten autogenerated gcc/ChangeLog | 634 +++++++++++++++++++++++++++++++ gcc/alias.c | 4 +- gcc/asan.c | 4 +- gcc/auto-inc-dec.c | 2 +- gcc/basic-block.h | 82 ++-- gcc/bb-reorder.c | 84 ++-- gcc/bt-load.c | 46 +-- gcc/caller-save.c | 8 +- gcc/cfg.c | 56 +-- gcc/cfganal.c | 124 +++--- gcc/cfgbuild.c | 34 +- gcc/cfgcleanup.c | 68 ++-- gcc/cfgexpand.c | 90 ++--- gcc/cfghooks.c | 38 +- gcc/cfgloop.c | 52 +-- gcc/cfgloopanal.c | 14 +- gcc/cfgloopmanip.c | 24 +- gcc/cfgrtl.c | 214 +++++------ gcc/cgraphbuild.c | 10 +- gcc/cgraphunit.c | 8 +- gcc/combine-stack-adj.c | 2 +- gcc/combine.c | 28 +- gcc/compare-elim.c | 2 +- gcc/config/alpha/alpha.c | 2 +- gcc/config/arm/arm.c | 8 +- gcc/config/bfin/bfin.c | 6 +- gcc/config/c6x/c6x.c | 6 +- gcc/config/epiphany/resolve-sw-modes.c | 6 +- gcc/config/frv/frv.c | 10 +- gcc/config/i386/i386.c | 20 +- gcc/config/ia64/ia64.c | 10 +- gcc/config/mips/mips.c | 10 +- gcc/config/picochip/picochip.c | 2 +- gcc/config/rs6000/rs6000.c | 4 +- gcc/config/s390/s390.c | 2 +- gcc/config/sh/sh.c | 2 +- gcc/config/spu/spu.c | 10 +- gcc/config/tilegx/tilegx.c | 4 +- gcc/config/tilepro/tilepro.c | 4 +- gcc/coverage.c | 4 +- gcc/cprop.c | 48 +-- gcc/cse.c | 14 +- gcc/dce.c | 10 +- gcc/df-core.c | 76 ++-- gcc/df-problems.c | 56 +-- gcc/df-scan.c | 44 +-- gcc/dominance.c | 62 +-- gcc/domwalk.c | 10 +- gcc/dse.c | 16 +- gcc/except.c | 6 +- gcc/final.c | 8 +- gcc/function.c | 70 ++-- gcc/fwprop.c | 4 +- gcc/gcse.c | 88 ++--- gcc/gimple-iterator.c | 8 +- gcc/gimple-ssa-strength-reduction.c | 4 +- gcc/gimple.c | 6 +- gcc/graph.c | 12 +- gcc/graphite-clast-to-gimple.c | 2 +- gcc/graphite-scop-detection.c | 12 +- gcc/graphite-sese-to-poly.c | 6 +- gcc/graphite.c | 8 +- gcc/haifa-sched.c | 34 +- gcc/hw-doloop.c | 10 +- gcc/ifcvt.c | 30 +- gcc/init-regs.c | 2 +- gcc/ipa-inline-analysis.c | 14 +- gcc/ipa-prop.c | 2 +- gcc/ipa-pure-const.c | 4 +- gcc/ipa-split.c | 46 +-- gcc/ira-build.c | 16 +- gcc/ira-color.c | 2 +- gcc/ira-costs.c | 2 +- gcc/ira-emit.c | 26 +- gcc/ira-int.h | 2 +- gcc/ira.c | 32 +- gcc/jump.c | 2 +- gcc/lcm.c | 158 ++++---- gcc/loop-init.c | 6 +- gcc/loop-invariant.c | 2 +- gcc/loop-iv.c | 4 +- gcc/loop-unroll.c | 12 +- gcc/loop-unswitch.c | 2 +- gcc/lower-subreg.c | 8 +- gcc/lra-assigns.c | 4 +- gcc/lra-coalesce.c | 4 +- gcc/lra-constraints.c | 6 +- gcc/lra-eliminations.c | 2 +- gcc/lra-lives.c | 8 +- gcc/lra-spills.c | 6 +- gcc/lra.c | 16 +- gcc/lto-streamer-in.c | 6 +- gcc/lto-streamer-out.c | 4 +- gcc/mcf.c | 26 +- gcc/mode-switching.c | 32 +- gcc/modulo-sched.c | 6 +- gcc/omp-low.c | 6 +- gcc/optabs.c | 2 +- gcc/postreload-gcse.c | 10 +- gcc/postreload.c | 4 +- gcc/predict.c | 70 ++-- gcc/profile.c | 72 ++-- gcc/recog.c | 6 +- gcc/ree.c | 2 +- gcc/reg-stack.c | 20 +- gcc/regcprop.c | 8 +- gcc/reginfo.c | 2 +- gcc/regmove.c | 6 +- gcc/regrename.c | 14 +- gcc/regs.h | 2 +- gcc/regstat.c | 8 +- gcc/reload.c | 6 +- gcc/reload1.c | 16 +- gcc/reorg.c | 2 +- gcc/resource.c | 16 +- gcc/sched-deps.c | 2 +- gcc/sched-ebb.c | 10 +- gcc/sched-int.h | 8 +- gcc/sched-rgn.c | 134 +++---- gcc/sched-vis.c | 2 +- gcc/sel-sched-dump.c | 2 +- gcc/sel-sched-ir.c | 60 +-- gcc/sel-sched-ir.h | 10 +- gcc/sel-sched.c | 22 +- gcc/sese.c | 6 +- gcc/stack-ptr-mod.c | 2 +- gcc/store-motion.c | 40 +- gcc/testsuite/ChangeLog | 12 + gcc/testsuite/g++.dg/plugin/selfassign.c | 2 +- gcc/testsuite/gcc.dg/plugin/selfassign.c | 2 +- gcc/tracer.c | 12 +- gcc/trans-mem.c | 28 +- gcc/tree-call-cdce.c | 2 +- gcc/tree-cfg.c | 144 +++---- gcc/tree-cfgcleanup.c | 22 +- gcc/tree-complex.c | 8 +- gcc/tree-dfa.c | 6 +- gcc/tree-eh.c | 6 +- gcc/tree-emutls.c | 2 +- gcc/tree-if-conv.c | 4 +- gcc/tree-inline.c | 54 +-- gcc/tree-into-ssa.c | 60 +-- gcc/tree-loop-distribution.c | 2 +- gcc/tree-mudflap.c | 6 +- gcc/tree-nrv.c | 6 +- gcc/tree-object-size.c | 2 +- gcc/tree-optimize.c | 10 +- gcc/tree-outof-ssa.c | 8 +- gcc/tree-profile.c | 4 +- gcc/tree-scalar-evolution.c | 2 +- gcc/tree-scalar-evolution.h | 2 +- gcc/tree-sra.c | 26 +- gcc/tree-ssa-ccp.c | 10 +- gcc/tree-ssa-coalesce.c | 8 +- gcc/tree-ssa-copy.c | 2 +- gcc/tree-ssa-copyrename.c | 4 +- gcc/tree-ssa-dce.c | 52 +-- gcc/tree-ssa-dom.c | 14 +- gcc/tree-ssa-dse.c | 2 +- gcc/tree-ssa-forwprop.c | 2 +- gcc/tree-ssa-ifcombine.c | 2 +- gcc/tree-ssa-live.c | 46 +-- gcc/tree-ssa-live.h | 8 +- gcc/tree-ssa-loop-ch.c | 6 +- gcc/tree-ssa-loop-im.c | 14 +- gcc/tree-ssa-loop-ivopts.c | 2 +- gcc/tree-ssa-loop-manip.c | 28 +- gcc/tree-ssa-loop-niter.c | 4 +- gcc/tree-ssa-loop-prefetch.c | 2 +- gcc/tree-ssa-loop-unswitch.c | 2 +- gcc/tree-ssa-math-opts.c | 14 +- gcc/tree-ssa-phiopt.c | 14 +- gcc/tree-ssa-phiprop.c | 2 +- gcc/tree-ssa-pre.c | 36 +- gcc/tree-ssa-propagate.c | 16 +- gcc/tree-ssa-reassoc.c | 18 +- gcc/tree-ssa-sccvn.c | 6 +- gcc/tree-ssa-sink.c | 8 +- gcc/tree-ssa-strlen.c | 2 +- gcc/tree-ssa-structalias.c | 4 +- gcc/tree-ssa-tail-merge.c | 38 +- gcc/tree-ssa-ter.c | 2 +- gcc/tree-ssa-threadupdate.c | 4 +- gcc/tree-ssa-uncprop.c | 12 +- gcc/tree-ssa-uninit.c | 16 +- gcc/tree-ssa.c | 10 +- gcc/tree-stdarg.c | 10 +- gcc/tree-switch-conversion.c | 2 +- gcc/tree-tailcall.c | 16 +- gcc/tree-vect-generic.c | 2 +- gcc/tree-vectorizer.c | 2 +- gcc/tree-vrp.c | 20 +- gcc/tsan.c | 6 +- gcc/value-prof.c | 6 +- gcc/var-tracking.c | 54 +-- gcc/varasm.c | 2 +- gcc/web.c | 6 +- 197 files changed, 2533 insertions(+), 1849 deletions(-) -- 1.7.11.7