Search code examples
llvmllvm-clangllvm-irllvm-c++-api

llvm: visitInstruction does not visit every instruction in a basic block?


I am trying to write a Simple pass on basic block and the code is as follows:

struct SimplePass : BasicBlockPass, InstVisitor<SimplePass>
{
   ... some initialisation and some finalization code 
    virtual bool runOnBasicBlock(BasicBlock& B) {
        std::cout << "---This is a block divider---" << B.size() << std::endl;
        visit(B);
        return false;
    }
    void visitInstruction(Instruction& I){
        std::cout << "Visiting every single instruction:" << I.getOpcodeName(I.getOpcode()) << std::endl;
    }
    void visitBranchInst(BranchInst& I) {
        if(I.isUnconditional()) {
            std::cout << "Encountered an unconditional branch!" << std::endl;
        }
    }

}

and very strangely I get some output like this:

...
---This is a block divider---5
Visiting every single instruction:call
Visiting every single instruction:load
Visiting every single instruction:add
Visiting every single instruction:store
Encountered an unconditional branch!
---This is a block divider---7 
Visiting every single instruction:phi 
Visiting every single instruction:load
Visiting every single instruction:sub
Visiting every single instruction:call
Visiting every single instruction:load
Visiting every single instruction:icmp
---This is a block divider---3
......

It is easy to see that in both blocks above the actual number of instructions should be 5 and 7, however the visitInstrucion function sometimes do not visit the last instruction of a basic block, why does this happen? Is this supposed to happen?


Solution

  • In the first block:

    Visiting every single instruction:call
    Visiting every single instruction:load
    Visiting every single instruction:add
    Visiting every single instruction:store
    Encountered an unconditional branch!
    

    It is 5 though! The last line comes from your void visitBranchInst(BranchInst& I) which takes precedence over visitInstruction. More specific visitors take precedence over more generic ones. If you want visitInstruction to be called anyway, you have to do it explicitly from more specific visitors - it won't happen automatically.

    As for the next block, maybe it ends with a branch that is conditional? Then your visitBranchInst doesn't print anything, and doesn't propagate to visitInstruction.