Retrieving numeric value of instruction operand

Hello Everyone,

I need some help in retrieving the numeric value of an instruction operand from LLVM IR.

this is what the IR looks like for a simple add function that adds two i32 integers

define i32 @summ(i32 %a, i32 %b) #0 {
entry:
%add = add nsw i32 %b, %a
ret i32 %add
}

i would like to know the integer value of %a and %b.

I’ve tried

-i->getOpcodeName() which gives me the string add

-i->getOperand(0) which gives me the string i32 %b

-i->getOperand(0)->getName() which gives me the string a

what method exists to get the actual integer value of the operands?
for example we called summ(1,2), how to retrieve the values 1 and 2 held in the operands?

Any help and guidance is greatly appreciated! :slight_smile:

Best,
Ammar

Dear Ammar,

It is not clear what you are asking. %a and %b in your code below are not constants; there is no way, at compile time, to determine what numeric values they will hold at run-time.

Are you asking how to write an LLVM pass that will add code to summ() to print out its result?

Regards,

John Criswell

hey john,

yes indeed, that’s what I’m trying, retreiving the values of %a and %b in an LLVM pass, sorry about the confusion.

If you want to add an instruction that uses the values %a and %b, then your solution is easy: in the LLVM IR, a value and the instruction that creates it are one and the same, and they are both represented by the same object. For example, in the following instruction: %s = add %a, %b The “%s” and the “add %a, %b” are the same thing (because SSA only allows one assignment to a virtual register). Therefore, in memory, there is one object (a sub-class of the Value class) that has name “%s” and represents the instruction “add %a, %b.” So, let’s say you have the following code to get an operand from an object of class Instruction: Instruction * i = ; Value * Va = i->getOperand(0); The variable Va points to the object representing the first operand of the instruction (in your case, %a). You can then create new instructions that use this value as an operand: BinaryOperator * Sub = BinaryOperator::CreateNeg (Va, “name”, InsertPt); The above would create the following instruction (which is an integer negation instruction): %name = sub 0, %a Regards, John Criswell

Hi John,

Thank you so much for the valuable answer! :slight_smile:

However, i have one tough issue that i need to solve, in my pass :

let’s say here

%s = add %a, %b

I need to check if the value of %a or %b is 2 or 4 and then apply a transformation to the other operand accordingly,

for example if the value of %a = 2 the i’ll multiply %b by 2 in my transform pass.

I’m having a hard time getting the integer value of variables since it is so simple in regular languages, it can’t be possible that LLVM does not have a way for that, I’ve also tried casting the operand to a ConstantInt which wasn’t successful.

I’m a beginner with LLVM and i do apologize for my naivety.

Best Regards,
Ammar

Let me repeat the above;
%a is a variable. It could have any value.
There could be any number of other calls to @summ(a,b) in other
translation units, or linked at runtime, which pass any value at all.

However, if you have a call site which calls @summ with constant
arguments, the method could be inlined at that call site...

There is a very big difference between compiling a method, and
interpreting a method.

You can write an LLVM pass to modify the method and change what it
does. For example you can add code to inspect the values of a and b at
run time.

It might help to think about what the final version of your function
would look like if you wrote it in your source language. eg;

int summ(int a, int b) {return a+b;} ==> int summ(int a, int b) {if
(a==2) return b*2; else return a+b;}

Then compile both versions to LLVM so you can start thinking about
what LLVM operations need to be performed to turn one into the other.

Hey Jeremy,

thank you for the response,I see what you’re saying,

The simplified version of the question is can i compare a Value to check if it is 1, is there a way to do if(i32 %b==1) in LLVM through a pass?

foo.c;
int foo(int a, int b){
  if (b==1)
    return 0;
  return a+b;
}

$ clang -c foo.c -emit-llvm
$ llvm-dis foo.bc
$ cat foo.ll
...
  %5 = icmp eq i32 %4, 1
  br i1 %5, label %6, label %7
...
$ llc -march=cpp foo.bc
$ cat foo.cpp
...
  ICmpInst* int1_14 = new ICmpInst(*label_4, ICmpInst::ICMP_EQ,
int32_13, const_int32_2, "");
  BranchInst::Create(label_5, label_6, int1_14, label_4);
...

You can get a rough idea of what to do from clang and llvm itself.