Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell if LLVM Instruction has a Left-Hand Side

Tags:

llvm

llvm-ir

Is there a way to tell if an LLVM Instruction has a left-hand side? That is, whether it produces a value?

For example, an add instruction would have a left-hand side; however, a store or br instruction would not.

like image 643
jgoeders Avatar asked Jan 18 '16 22:01

jgoeders


1 Answers

In general you can identify those instructions which cannot have a result assignment, but you cannot say if an instruction will result in an assignment, only that it might.

This is because you don't have to assign the result of an operation. For instance, the following line of code is valid in LLVM IR:

add nsw i32 %a, %b

but it's pointless because it has no effect whatsoever. No sane tool would emit that line, and even if emitted, it would be wiped away by the optimizer during dead code elimination. The only instruction for which ignoring the return value actually makes sense is call. In fact, you might want to call a function only for side-effects, even when it's not declared void. Think about printf in C, whose return value is almost invariably ignored.

Because of this last consideration, you can assume that in practice all the instructions that can have a result assignment will have one, with the only exception of call. invoke is very similar to call, so the same considerations made for the former apply.

As you might have noticed, whether an instruction results in an assignment depends on its class. With the help of llvm/IR/Instruction.def, which contains the definition of all opcodes and classes, and the IR language reference, we can come up with the following subdivision:

Instruction classes that cannot have a result assignment:

  • ReturnInst, BranchInst, SwitchInst, IndirectBrInst, ResumeInst, UnreachableInst, CleanupReturnInst, CatchReturnInst
  • StoreInst, FenceInst, AtomicRMWInst, AtomicCmpXchgInst

Instruction classes that (might) have a result assignment:

  • CatchSwitchInst
  • BinaryOperator
  • AllocaInst, LoadInst, GetElementPtrInst
  • InvokeInst, CatchSwitchInst
  • TruncInst, ZExtInst, SExtInst, FPToUIInst, FPToSIInst, UIToFPInst, SIToFPInst, FPTruncInst, FPExtInst, PtrToIntInst, IntToPtrInst, BitCastInst
  • VAArgInst
  • CleanupPad, CatchPad
  • ICmpInst, FCmpInst, PHINode, SelectInst
  • ExtractElementInst, ShuffleVectorInst, ExtractValueInst, InsertElementInst, InsertValueInst

Instruction classes that might or might not have a result assignment:

  • CallInst, InvokeInst

You can now build a switch on the result of Instruction::getOpcode() or, better, an InstVisitor to classify instructions:

#include <llvm/IR/InstVisitor.h>

enum HaveRetVal { DEFINITELY_NOT, MAYBE, PROBABLY_YES };

class HaveRetAssignment : public InstVisitor<HaveRetAssignment, HaveRetVal> {
public:
  HaveRetVal visitBinaryOperator(BinaryOperator &) { return PROBABLY_YES; }

  // ...

  HaveRetVal visitCallInst(CallInst&) { return MAYBE; }

  // ...

  HaveRetVal visitBranchInst(BranchInst&) { return DEFINITELY_NOT; }

  // ...
};
like image 137
Stefano Sanfilippo Avatar answered Sep 25 '22 08:09

Stefano Sanfilippo