Index: include/llvm/IR/LLVMContext.h =================================================================== --- include/llvm/IR/LLVMContext.h +++ include/llvm/IR/LLVMContext.h @@ -18,6 +18,7 @@ #include "llvm-c/Core.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Options.h" namespace llvm { @@ -163,6 +164,11 @@ void emitError(const Instruction *I, const Twine &ErrorStr); void emitError(const Twine &ErrorStr); + template + ValT getOption() const { + return OptionRegistry::instance().template get(); + } + private: LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; Index: include/llvm/PassSupport.h =================================================================== --- include/llvm/PassSupport.h +++ include/llvm/PassSupport.h @@ -82,6 +82,15 @@ CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ } +#define INITIALIZE_PASS_WITH_OPTIONS(passName, arg, name, cfg, analysis) \ + INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis) \ + passName::RegisterOptions(); \ + INITIALIZE_PASS_END(passName, arg, name, cfg, analysis) + +#define INITIALIZE_PASS_WITH_OPTIONS_BEGIN(passName, arg, name, cfg, analysis) \ + INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis) \ + passName::RegisterOptions(); \ + template Pass *callDefaultCtor() { return new PassName(); } Index: include/llvm/Support/Options.h =================================================================== --- /dev/null +++ include/llvm/Support/Options.h @@ -0,0 +1,65 @@ +//===- llvm/Support/Options.h - Debug options support -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares helper objects for defining debug options that can be +// configured via the command line. The new API currently builds on the cl::opt +// API, but does not require the use of static globals. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +// The option keys are unique based on the base type, value type and member +// offset of the option's final storage. +typedef char LLVMOptionKey; + +template class OptionKey { +public: + static LLVMOptionKey ID; +}; + +template +LLVMOptionKey OptionKey::ID = 0; + +//===----------------------------------------------------------------------===// +// OptionRegistry class +// +class OptionRegistry { +private: + DenseMap Options; + + /// addOption - Adds a cl::Option to the registry. Allocated cl::Options are + /// owened by the OptionRegistry and are deallocated on destruction or removal + void addOption(LLVMOptionKey *Key, cl::Option *O); + +public: + ~OptionRegistry(); + OptionRegistry() {} + + static OptionRegistry &instance(); + + template + static void registerOption(const char *ArgStr, const char *Desc, + const ValT &InitValue) { + cl::opt *Option = new cl::opt(ArgStr, cl::desc(Desc), + cl::Hidden, cl::init(InitValue)); + instance().addOption(&OptionKey::ID, Option); + } + + template ValT get() const { + auto It = Options.find(&OptionKey::ID); + assert(It != Options.end() && "Option not in OptionRegistry"); + return *(cl::opt *)It->second; + } +}; + +} // namespace llvm Index: lib/Support/CMakeLists.txt =================================================================== --- lib/Support/CMakeLists.txt +++ lib/Support/CMakeLists.txt @@ -40,6 +40,7 @@ MemoryBuffer.cpp MemoryObject.cpp MD5.cpp + Options.cpp PluginLoader.cpp PrettyStackTrace.cpp RandomNumberGenerator.cpp Index: lib/Support/CommandLine.cpp =================================================================== --- lib/Support/CommandLine.cpp +++ lib/Support/CommandLine.cpp @@ -113,9 +113,15 @@ } void Option::removeArgument() { - assert(NextRegistered && "argument never registered"); - assert(RegisteredOptionList == this && "argument is not the last registered"); - RegisteredOptionList = NextRegistered; + if (RegisteredOptionList == this) { + RegisteredOptionList = NextRegistered; + MarkOptionsChanged(); + return; + } + Option *O = RegisteredOptionList; + for (; O->NextRegistered != this; O = O->NextRegistered) + ; + O->NextRegistered = NextRegistered; MarkOptionsChanged(); } Index: lib/Support/Options.cpp =================================================================== --- /dev/null +++ lib/Support/Options.cpp @@ -0,0 +1,33 @@ +//===- llvm/Support/Options.cpp - Debug options support ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the helper objects for defining debug options using the +// new API built on cl::opt, but not requiring the use of static globals. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Options.h" +#include "llvm/Support/ManagedStatic.h" + +using namespace llvm; + +OptionRegistry::~OptionRegistry() { + for (auto IT = Options.begin(); IT != Options.end(); ++IT) + delete IT->second; +} + +void OptionRegistry::addOption(LLVMOptionKey *Key, cl::Option *O) { + assert(Options.find(Key) == Options.end() && + "Argument with this key already registerd"); + Options.insert(std::make_pair(Key, O)); +} + +static ManagedStatic OR; + +OptionRegistry &OptionRegistry::instance() { return *OR; } Index: lib/Transforms/Scalar/Scalarizer.cpp =================================================================== --- lib/Transforms/Scalar/Scalarizer.cpp +++ lib/Transforms/Scalar/Scalarizer.cpp @@ -150,6 +150,16 @@ bool visitLoadInst(LoadInst &); bool visitStoreInst(StoreInst &); + static void RegisterOptions() { + // This is disabled by default because having separate loads and stores + // makes it more likely that the -combiner-alias-analysis limits will be + // reached. + OptionRegistry::registerOption( + "scalarize-load-store", + "Allow the scalarizer pass to scalarize loads and store", false); + } + private: Scatterer scatter(Instruction *, Value *); void gather(Instruction *, const ValueVector &); @@ -164,19 +174,14 @@ GatherList Gathered; unsigned ParallelLoopAccessMDKind; const DataLayout *DL; + bool ScalarizeLoadStore; }; char Scalarizer::ID = 0; } // end anonymous namespace -// This is disabled by default because having separate loads and stores makes -// it more likely that the -combiner-alias-analysis limits will be reached. -static cl::opt ScalarizeLoadStore - ("scalarize-load-store", cl::Hidden, cl::init(false), - cl::desc("Allow the scalarizer pass to scalarize loads and store")); - -INITIALIZE_PASS(Scalarizer, "scalarizer", "Scalarize vector operations", - false, false) +INITIALIZE_PASS_WITH_OPTIONS(Scalarizer, "scalarizer", + "Scalarize vector operations", false, false); Scatterer::Scatterer(BasicBlock *bb, BasicBlock::iterator bbi, Value *v, ValueVector *cachePtr) @@ -236,7 +241,10 @@ bool Scalarizer::doInitialization(Module &M) { ParallelLoopAccessMDKind = - M.getContext().getMDKindID("llvm.mem.parallel_loop_access"); + M.getContext().getMDKindID("llvm.mem.parallel_loop_access"); + ScalarizeLoadStore = + M.getContext() + .template getOption(); return false; }