通常,您可以标识那些不能进行结果分配的指令,但是您不能说说一条指令是否会导致赋值,只能说它可能导致结果。
这是因为你不具备分配一个操作的结果。例如,以下代码行在LLVM IR中有效:
add nsw i32 %a, %b
Run Code Online (Sandbox Code Playgroud)
但这毫无意义,因为它毫无作用。没有理智的工具会发出该行,即使发出,在消除死代码的过程中,优化程序也会将其擦除。真正忽略返回值的唯一指令是call。实际上,您可能只想为副作用调用一个函数,即使未声明它也是如此void。考虑一下printfC,它的返回值几乎总是被忽略。
出于最后的考虑,您可以假定实际上所有可以进行结果分配的指令都将具有一个指令,唯一的例外是call。invoke与十分相似call,因此适用于前者的相同考虑。
您可能已经注意到,一条指令是否导致赋值取决于其类。借助llvm/IR/Instruction.def,它包含所有操作码和类的定义以及IR语言参考,我们可以提出以下细分:
ReturnInst,BranchInst,SwitchInst,IndirectBrInst,ResumeInst,UnreachableInst,CleanupReturnInst,CatchReturnInstStoreInst,FenceInst,AtomicRMWInst,AtomicCmpXchgInstCatchSwitchInstBinaryOperatorAllocaInst,LoadInst,GetElementPtrInstInvokeInst, CatchSwitchInstTruncInst,ZExtInst,SExtInst,FPToUIInst,FPToSIInst,UIToFPInst,SIToFPInst,FPTruncInst,FPExtInst,PtrToIntInst,IntToPtrInst,BitCastInstVAArgInstCleanupPad, CatchPadICmpInst,FCmpInst,PHINode,SelectInstExtractElementInst,ShuffleVectorInst,ExtractValueInst,InsertElementInst,InsertValueInstCallInst, InvokeInst现在,您可以switch根据Instruction::getOpcode()或更好的结果InstVisitor对指令进行分类:
#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; }
// ...
};
Run Code Online (Sandbox Code Playgroud)