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.
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:
ReturnInst
, BranchInst
, SwitchInst
, IndirectBrInst
, ResumeInst
, UnreachableInst
, CleanupReturnInst
, CatchReturnInst
StoreInst
, FenceInst
, AtomicRMWInst
, AtomicCmpXchgInst
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
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; }
// ...
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With