alienobserver
alienobserver

Reputation: 13

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();

Upvotes: 1

Views: 652

Answers (1)

Chandler Carruth
Chandler Carruth

Reputation: 3341

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

Upvotes: 3

Related Questions