如何判断 LLVM 指令是否有左侧
How to tell if LLVM Instruction has a Left-Hand Side
有没有办法判断 LLVM Instruction
是否有左侧?即是否产生价值?
例如,add
指令有左侧;但是,store
或 br
指令不会。
一般来说,您可以识别那些不能有结果赋值的指令,但您不能说指令是否会导致赋值,只能说它可能.
这是因为您没有分配运算结果。例如,以下代码行在 LLVM IR 中有效:
add nsw i32 %a, %b
但这毫无意义,因为它没有任何作用。任何理智的工具都不会发出该行,即使发出,它也会在死代码消除期间被优化器擦除。忽略 return 值真正有意义的唯一指令是 call
。事实上,您可能只想为 side-effects 调用一个函数,即使它没有声明 void
。想想 C 中的 printf
,它的 return 值几乎总是被忽略。
由于这最后的考虑,您可以假设在实践中所有可以进行结果赋值的指令都会有一个,唯一的例外是 call
。 invoke
与 call
非常相似,因此适用于前者的相同考虑。
您可能已经注意到,指令是否导致赋值取决于其 class。借助llvm/IR/Instruction.def
, which contains the definition of all opcodes and classes, and the IR language reference,我们可以得出如下细分:
指令 classes 不能有结果赋值:
ReturnInst
、BranchInst
、SwitchInst
、IndirectBrInst
、ResumeInst
、UnreachableInst
、CleanupReturnInst
、CatchReturnInst
StoreInst
、FenceInst
、AtomicRMWInst
、AtomicCmpXchgInst
指令 class(可能)有一个结果赋值:
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
指令 classes 可能有也可能没有结果赋值:
CallInst
、InvokeInst
您现在可以在 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()
有没有办法判断 LLVM Instruction
是否有左侧?即是否产生价值?
例如,add
指令有左侧;但是,store
或 br
指令不会。
一般来说,您可以识别那些不能有结果赋值的指令,但您不能说指令是否会导致赋值,只能说它可能.
这是因为您没有分配运算结果。例如,以下代码行在 LLVM IR 中有效:
add nsw i32 %a, %b
但这毫无意义,因为它没有任何作用。任何理智的工具都不会发出该行,即使发出,它也会在死代码消除期间被优化器擦除。忽略 return 值真正有意义的唯一指令是 call
。事实上,您可能只想为 side-effects 调用一个函数,即使它没有声明 void
。想想 C 中的 printf
,它的 return 值几乎总是被忽略。
由于这最后的考虑,您可以假设在实践中所有可以进行结果赋值的指令都会有一个,唯一的例外是 call
。 invoke
与 call
非常相似,因此适用于前者的相同考虑。
您可能已经注意到,指令是否导致赋值取决于其 class。借助llvm/IR/Instruction.def
, which contains the definition of all opcodes and classes, and the IR language reference,我们可以得出如下细分:
指令 classes 不能有结果赋值:
ReturnInst
、BranchInst
、SwitchInst
、IndirectBrInst
、ResumeInst
、UnreachableInst
、CleanupReturnInst
、CatchReturnInst
StoreInst
、FenceInst
、AtomicRMWInst
、AtomicCmpXchgInst
指令 class(可能)有一个结果赋值:
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
指令 classes 可能有也可能没有结果赋值:
CallInst
、InvokeInst
您现在可以在 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()