如何判断 LLVM 指令是否有左侧

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

有没有办法判断 LLVM Instruction 是否有左侧?即是否产生价值?

例如,add 指令有左侧;但是,storebr 指令不会。

一般来说,您可以识别那些不能有结果赋值的指令,但您不能说指令是否会导致赋值,只能说它可能.

这是因为您没有分配运算结果。例如,以下代码行在 LLVM IR 中有效:

add nsw i32 %a, %b

但这毫无意义,因为它没有任何作用。任何理智的工具都不会发出该行,即使发出,它也会在死代码消除期间被优化器擦除。忽略 return 值真正有意义的唯一指令是 call。事实上,您可能只想为 side-effects 调用一个函数,即使它没有声明 void。想想 C 中的 printf,它的 return 值几乎总是被忽略。

由于这最后的考虑,您可以假设在实践中所有可以进行结果赋值的指令都会有一个,唯一的例外是 callinvokecall 非常相似,因此适用于前者的相同考虑。

您可能已经注意到,指令是否导致赋值取决于其 class。借助llvm/IR/Instruction.def, which contains the definition of all opcodes and classes, and the IR language reference,我们可以得出如下细分:

指令 classes 不能有结果赋值:

  • ReturnInstBranchInstSwitchInstIndirectBrInstResumeInstUnreachableInstCleanupReturnInstCatchReturnInst
  • StoreInstFenceInstAtomicRMWInstAtomicCmpXchgInst

指令 class(可能)有一个结果赋值:

  • CatchSwitchInst
  • BinaryOperator
  • AllocaInstLoadInstGetElementPtrInst
  • InvokeInst, CatchSwitchInst
  • TruncInstZExtInstSExtInstFPToUIInstFPToSIInstUIToFPInstSIToFPInstFPTruncInstFPExtInstPtrToIntInstIntToPtrInstBitCastInst
  • VAArgInst
  • CleanupPadCatchPad
  • ICmpInstFCmpInstPHINodeSelectInst
  • ExtractElementInstShuffleVectorInstExtractValueInstInsertElementInstInsertValueInst

指令 classes 可能有也可能没有结果赋值:

  • CallInstInvokeInst

您现在可以在 Instruction::getOpcode() 的结果上构建一个 switch,或者更好的是,一个 InstVisitor 到 class 化指令:

#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; }

  // ...
};

可以查看指令的return类型是否为void:

getType()->isVoidTy()