Search code examples
llvmllvm-ir

Find pointer to the Instruction that assigns to value in LLVM


Suppose I have a pointer to some Value* val in LLVM. I want to get a pointer to Instruction that assigned value to the variable that val points to. How can I do it? This is an example of code

%add = add nsw i32 %aa, %bb
%div = sdiv i32 %add, %cc

I have a pointer to variable add and I want to get a pointer to the Instruction that assigned to variable add, which is pointer to %add = add nsw i32 %aa, %bb instruction

So far the only thing I found was a pointer to Basicblock that the variable belongs to. This is how I did it

Instruction * tmpI = dyn_cast<Instruction>(val);
BasicBlock * b = tmpI->getParent();


Solution

  • The correct answer was provided in the comments by jmmartinez:

    The LLVM-IR is a Static-Single-Assignment Intermediate Representation. The pointer to the instruction IS the pointer to the assignment. The add instruction and the assignment to the add register have a one-to-one matching since registers can only be assigned once, and instructions can only assign to a single register.

    [...] In your code example. if the variable val points to the register %add. It happens that val points to an llvm::Instruction (which inherits from llvm::Value). And this instruction is the addition you're looking for.

    To add a bit more detail, the LLVM Value type is a base class of the LLVM Instruction type. For IR values like %add in the example, the IR allocates a specific Instruction subtype, BinaryOperator in the case of an add instruction. So the pointer to a Value for %add is actually a pointer to the same object as the instruction, just using its base class.

    LLVM also has a special system for casting these pointers between types in the IR type hierarchy: https://llvm.org/docs/ProgrammersManual.html#the-isa-cast-and-dyn-cast-templates

    Here are some example functions that take a specific llvm::Value and return the llvm::Instruction that produces that value:

    #include <llvm/IR/Value.h>
    #include <llvm/IR/Instruction.h>
    
    using llvm::Value;
    using llvm::Instruction;
    using llvm::cast;
    using llvm::dyn_cast;
    using llvm::dyn_cast_or_null;
    using llvm::isa;
    
    // Either convert a `Value` to an `Instruction`
    // or return null.
    auto tryGetInstr(Value* value) -> Instruction* {
      return dyn_cast<Instruction>(value);
    }
    
    // Just test whether a value was computed with an
    // `Instruction` without converting it. Don't use
    // this if you'll just end up converting it, use
    // the above that combines the two.
    auto isInstr(Value* value) -> Instruction* {
      return isa<Instruction>(value);
    }
    
    // When you already know the value *must* be computed
    // by an instruction, you can assert this and convert
    // it in a way that will never produce a null.
    auto getInstr(Value* value) -> Instruction* {
      return cast<Instruction>(value);
    }
    
    // If `value` is non-null, try to convert it to an
    // `Instruction`. Returns null if `value` is null
    // or it isn't referencing an `Instruction`.
    auto tryGetInstrIfNonNull(Value* value) -> Instruction* {
      return dyn_cast_or_null<Instruction>(value);
    }
    

    https://cpp.compiler-explorer.com/z/f13bT4vb5