Billy
Billy

Reputation: 751

Optimize add zero with llvm pass

int func(int i){                                                                     
     int j;
     j = i + 0;
     return j;                                                                                                                       
 } 

I want to practise and learn LLVM transformation pass. For the above simple c function, I want to implement algebraic identification optimization X+0 -> X

I expect the optimized program to be

int func(int i){                                                                     
     int j;                                                                       
     j = i // remove the add instruction                                                                     
     return j;                                                                        
 } 

I read about the IRBuilder, I can create Add/Sub/Mul.... a lot of instructions. But for handling the above case, I can not find any matches.

what should I do to handle the above case?

I also think if I can just remove the instruction.

And the program would be

int func(int i){                                                                                                                                       
     return i;                                                                        
 } 

I am not sure if llvm will do this automatically, once I remove the useless add instruction.

Upvotes: 1

Views: 378

Answers (2)

Billy
Billy

Reputation: 751

To implement the avoid add zero optimization The required things to do are:

  • Find the instruction where y=x+0
  • Replace ALL the use of y with x
  • Record the pointer of the instruction
  • Remove it afterward

Upvotes: 0

arrowd
arrowd

Reputation: 34411

Running clang -O0 -S -emit-llvm -o - test.c on your code produces following IR:

define i32 @func(i32 %i) #0 {
entry:
  %i.addr = alloca i32, align 4
  %j = alloca i32, align 4
  store i32 %i, i32* %i.addr, align 4
  %0 = load i32, i32* %i.addr, align 4
  %add = add nsw i32 %0, 0
  store i32 %add, i32* %j, align 4
  %1 = load i32, i32* %j, align 4
  ret i32 %1
}

As you can see, there is add nsw i32 %0, 0 instruction. This means that clang doesn't optimize it right away (at least on -O0) and this is instruction we are going to process by our pass.

I'll omit boilerplate code that is required to add your own pass, as it is thoroughly described in the LLVM documentation.

The pass should do something like (pseudo-code)

runOnFunction(Function& F)
{
  for(each instruction in F)
    if(isa<BinaryOperator>(instruction))
      if(instruction.getOpcode() == BinaryInstruction::Add)
         if(isa<ConstantInt>(instruction.getOperand(1))
            if(extract value from constant operand and check if it is 0)
              instruction.eraseFromParent()
}

Upvotes: 1

Related Questions