[LLVMdev] Overhauling the command-line processing/codegen options code

Chris Lattner clattner at apple.com
Wed Feb 13 12:53:09 PST 2013


On Feb 13, 2013, at 11:37 AM, Justin Holewinski <justin.holewinski at gmail.com> wrote:
> Is anyone currently working on overhauling the command-line processing code?

Bill's attributes work is quite related, it will hopefully define away a number of the TargetOptions concepts, replacing them with per-function attributes.  It should also subsume a number of target-independent concepts like "omit frame pointers" and other codegen flags.

> We're currently having some design issues with this component, and I'd like to start a larger conversation on it.  For context, I am talking from an "LLVM as a library" perspective 

My favorite perspective :)

>  In a nut-shell, the problems we are facing are as follows:
> 
> 1. As per bug 11944, the command-line processing logic accounts for a non-trivial amount of global constructors and leads to memory that is allocated when the containing library is loaded, and not freed until the containing library is unloaded.  Granted, this is not a lot of data…

Yep, this sucks.  It has been a long-known problem.  In my ideal world, the only cl::opt's that would exist would be in leaf tools (e.g. in tools/opt, but not in optimization passes themselves).  There is some major design work required to make this happen though, and I'm not aware of anyone tackling it.

> 2. Command-line options are currently used for codegen options in inherently non-thread-safe ways.

Hopefully Bill's work will help address the majority of this.

> (1) is mostly self-explanatory and has a bug about it, but (2) requires a bit more explanation.  Take for example the "-unroll-threshold" option in LoopUnroll.  If I'm setting up a pass pipeline programmatically, I add the LoopUnroll pass to the PassManager, but I cannot set the unroll threshold without calling cl::ParseCommandLineOptions() [or perhaps some ugly hacks that involve getting at and modifying the global state].  In addition to being awkward, this is not thread safe!  I cannot run two PassManager pipelines concurrently with different unroll threshold values.  In this case, I am singling out the LoopUnroll pass, but this design is very prevalent within the LLVM analysis/transformation/codegen infrastructure.  This has no effect on users of opt/llc as tools, but library users can be greatly affected by this.

This is a very interesting one that is orthogonal to Bill's work.  The preferred approach for this sort of thing is to change the LoopUnroll pass to take the unroll threshold as a constructor argument or a struct that wraps up all of the configuration settings.  When the pass is *default* constructed (e.g. from opt -loop-unroll), it is acceptable to have the default ctor read cl::opt variables, but the optimization pipeline should not depend on cl::opts to configure the pass.

There is currently some gray area here for debug settings, and for things that are being staged in but are not on by default, but the default optimization pipeline should not be looking to cl::opt's for their settings (in an ideal world).

> Requirements
> 
> - Make it easy for passes to declare arbitrary options, just like they do now
> - Let different pass pipelines have different sets of option values
> - Keep the option registry dynamic, so plugins loaded with "-load" can register new options
> - Let option values be parseable from the command-line (for opt, llc, …)

All good requirements.

> Implementation
> 
> As a first design draft, I propose that cl::opt and friends be extended to support argument storage in an LLVMContext.  Instead of storing the value directly in a cl::opt instance or specifying a global variable, this new storage would utilize a StringMap stored in an LLVMContext.  As a consequence, parsing would be delayed until the option is read.

I'd really like to avoid going here.  With the direction sketched out above, is enough of your problem solved?  Taking loop unroll as an example, I'd much rather you refactor the code to have its constructor take a configuration struct setting its various settings, than have the various settings pulled out to llvmcontext.

-Chris






More information about the llvm-dev mailing list