Reputation: 167
I'm new to LLVM, and I'm doing some experiments on it such as inserting an instruction.
My main.c
is shown below:
int foo(int e, int a) {
int b = a + 1;
int c = b * 2;
b = e << 1;
int d = b / 4;
return c * d;
}
I use the command below to generate the LLVM bytecode
clang-12 -O0 -Xclang -disable-O0-optnone -emit-llvm -c main.c -o main.bc
opt-12 -S -mem2reg main.bc -o main.ll
The bytecode is
; Function Attrs: noinline nounwind uwtable
define dso_local i32 @foo(i32 %0, i32 %1) #0 {
%3 = add nsw i32 %1, 1
%4 = mul nsw i32 %3, 2
%5 = shl i32 %0, 1
%6 = sdiv i32 %5, 4
%7 = mul nsw i32 %4, %6
ret i32 %7
}
And I use the code to insert an instruction after the first instruction:
bool runOnBasicBlock(BasicBlock &B) {
// get the first and second instruction
Instruction &Inst1st = *B.begin();
Instruction *NewInst = BinaryOperator::Create(
Instruction::Add, Inst1st.getOperand(0), Inst1st.getOperand(0));
NewInst->insertAfter(&Inst1st);
...
}
After I run this pass, the bytecode is changed to
; Function Attrs: noinline nounwind uwtable
define dso_local i32 @foo(i32 %0, i32 %1) #0 {
%3 = add nsw i32 %1, 1
%4 = add i32 %1, %1
%5 = mul nsw i32 %4, 2
%6 = shl i32 %0, 1
%7 = sdiv i32 %6, 4
%8 = mul nsw i32 %5, %7
ret i32 %8
}
It seems that the inserted instruction is equal to b = a + a;
, so the instruction %4 = mul nsw i32 %3, 2
is changed to %5 = mul nsw i32 %4, 2
. I cannot understand the reason. Any help?
Upvotes: 1
Views: 849
Reputation: 161
I could not reproduce your output bytecode. Any chance you forgot to mention something?
This question made me curious enough to try it myself.
I used the same c file as in the question and I used the same commands to generate the LLVM bytecode, the only difference was I used LLVM 16.
As expected I got the same initial bytecode as yours:
; Function Attrs: noinline nounwind uwtable
define dso_local i32 @foo(i32 noundef %e, i32 noundef %a) #0 {
entry:
%add = add nsw i32 %a, 1
%mul = mul nsw i32 %add, 2
%shl = shl i32 %e, 1
%div = sdiv i32 %shl, 4
%mul1 = mul nsw i32 %mul, %div
ret i32 %mul1
}
I wrote the following function pass using the code you provided to insert the add instruction after the first instruction:
#include "llvm/IR/Instructions.h"
...
PreservedAnalyses FuncPass::run(Function &F, FunctionAnalysisManager &AM) {
for (auto &B : F) {
Instruction &Inst1st = *B.begin();
Instruction *NewInst = BinaryOperator::Create(
Instruction::Add, Inst1st.getOperand(0), Inst1st.getOperand(0));
NewInst->insertAfter(&Inst1st);
}
return PreservedAnalyses::none();
}
Then I ran the bytecode through the above function pass but the result I got was different from yours:
; Function Attrs: noinline nounwind uwtable
define dso_local i32 @foo(i32 noundef %e, i32 noundef %a) #0 {
entry:
%add = add nsw i32 %a, 1
%0 = add i32 %a, %a
%mul = mul nsw i32 %add, 2
%shl = shl i32 %e, 1
%div = sdiv i32 %shl, 4
%mul1 = mul nsw i32 %mul, %div
ret i32 %mul1
}
My result bytecode, similar to yours, contains the new add instruction right after the first instruction, but despite your output bytecode, the result of this new add instruction does not replace the usage of variable b
in the next instruction.
Upvotes: 1
Reputation: 38893
As I know, NewInst->insertAfter(&Inst1st);
makes from the block
int b = a + 1;
int c = b * 2;
the following block
int b = a + 1, a + a;
int c = b * 2;
therefore b
drops off the previous value %3
and gets the new value %4
and further mul
uses that new value of b
.
Upvotes: 1