About writing a modulePass in addPreEmitPass() for NVPTX

Hello,

I want to write a modulePass in addPreEmitPass() for NVPTX, but I encounter an assertion failed when executing clang.

Here is my error message.

Are you sure you are initializing your pass properly? Can you show a stripped down version of your pass?

I write my pass in a mix way of NVPTXAllocaHoisting, NVPTXSplitBBatBar and
transforms/Hello.

The following is part of the codes:

in NVPTXTargetMachine.cpp

bool NVPTXPassConfig::addPreEmitPass()
{
    addPass(createTest());
    return false;
}

in NVPTXTest.h

namespace llvm{
class NVPTXTest : public ModulePass
{
    void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll(); }
};
extern ModulePass *createTest();
}

in NVPTXTest.cpp

namespace llvm
{
char NVPTXTest::ID = 0;
static RegisterPass<NVPTXTest> X("test", "Test Module Pass");
ModulePass *createTest() { return new NVPTXTest(); }
}

Thanks
Antony Yu

I try to use INITIALIZE_PASS instead of RegisterPass<> to register my pass,
though I don't understand what's their difference and how it works because
its documents doesn't exist. But it still doesn't work.

Parts of my codes is as follows:

in NVPTXTest.h

namespace llvm {

void initializeNVPTXTestPass(PassRegistry &r);

class NVPTXTest : public ModulePass
{
public:

    NVPTXTest() : ModulePass(ID){
        initializeNVPTXTestPass(*PassRegistry::getPassRegistry());
    }
    void getAnalysisUsage(AnalysisUsage &AU) const {
        AU.setPreservesAll();
        ModulePass::getAnalysisUsage(AU);
    }

};

in NVPTXTest.cpp

#include "NVPTXTest.h"

namespace llvm
{
    //static RegisterPass<NVPTXTest> X("test", "Test Module Pass");
    char NVPTXTest::ID = 0;
    ModulePass *createTest()
    {
        return new NVPTXTest();
    }
}
using namespace llvm;

INITIALIZE_PASS(NVPTXTest, "test", "TestModule Pass", true, true);

Sorry for the delay. Yeah, that error message is a bit confusing. What’s happening is that your pass sequence is invalid. Once the IR has been lowered to machine code, its too late to run LLVM IR passes (ModulePass, FunctionPass, CallGraphSCCPass, etc.). At that point, you need to run a Machine*Pass, e.g. MachineFunctionPass. If you need to run an IR level pass, you need to use addIRPasses().

So that's how it is !! Thanks!

Hmm, in fact, I want to get Call Graph information in machine code stage,
is there any way to get this?

I try CallGraph &g= getAnalysis<CallGraph>, but it prints the same error and
doesn't work as expected.

Antony Yu

Justin Holewinski-2 wrote

Oops! No need of Call Graph!
In fact, what I want to do is to find which function is the kernel function
and which function is called by that kernel. Since OpenCL will make all
functions called by kernels inline, I can use function attribute: Noinline
to distinguish them.

Sorry for bothering you.

Antony Yu

You shouldn’t rely on that, its an implementation detail. Instead, you can trace back to the original Function object and check for kernel metadata. See http://llvm.org/docs/NVPTXUsage.html#marking-functions-as-kernels

Nice!
It's really helpful. I will study on that.

Thanks.
Antony Yu