Confused by how to register a pass with opt

I have a pre instruction selection pass that is registered by calling addPass from Target::addPreISel. This works fine - it runs at the appropriate point in the pipeline and does what it is supposed to.

I would like to call the pass from opt in order to write some test cases in IR. Unfortunately I’m missing something - despite a determined attempt to do what other passes do, mine doesn’t show up in opt. With variables renamed, the pass amounts to:

#define DEBUG_TYPE “my-pass”
#define EXAMPLE_NAME “A longer description of my pass”

namespace {
class MyExample : public FunctionPass {
public:
static char ID;
MyExample() : FunctionPass(ID) {
initializeMyExamplePass(*PassRegistry::getPassRegistry());
}

bool runOnFunction(Function &) override;
StringRef getPassName() const override { return EXAMPLE_NAME; }

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired();
AU.addRequired();
AU.addRequired();
}
};
} // namespace
char MyExample::ID = 0;

INITIALIZE_PASS_BEGIN(MyExample, DEBUG_TYPE, EXAMPLE_NAME, false, false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
INITIALIZE_PASS_END(MyExample, DEBUG_TYPE, EXAMPLE_NAME, false, false)

FunctionPass *llvm::createMyExamplePass() { return new MyExample(); }

I think the problem is that addPreISel isn’t called by opt, so the constructor is never run and the pass never added to the list. This is somewhat confirmed by the following hack:

static struct once_t {
once_t() { createMyExamplePass(); }
} unused_variable;

which creates an instance of the pass then immediately throws it away, in which case opt will let me run the pass as desired.

So while I have a workaround, said workaround looks absurd - what’s the correct way to use this API?

Thanks!

Jon

You need to call "initializeMyExamplePass" ahead of time. Look at include/llvm/InitializePasses.h, and for the actual calls that initialize individual passes, at lib/Analysis/Analysis.cpp, lib/Transforms/Scalar/Scalar.cpp, etc.

These are all called from "main" in opt.cpp.

-Krzysztof