Index: llvm/include/llvm/Transforms/Utils/FunctionComparator.h =================================================================== --- llvm/include/llvm/Transforms/Utils/FunctionComparator.h +++ llvm/include/llvm/Transforms/Utils/FunctionComparator.h @@ -329,6 +329,8 @@ private: int cmpOrderings(AtomicOrdering L, AtomicOrdering R) const; + int cmpMetadataAsValue(const MetadataAsValue *L, + const MetadataAsValue *R) const; int cmpInlineAsm(const InlineAsm *L, const InlineAsm *R) const; int cmpAttrs(const AttributeList L, const AttributeList R) const; int cmpRangeMetadata(const MDNode *L, const MDNode *R) const; Index: llvm/lib/Transforms/Utils/FunctionComparator.cpp =================================================================== --- llvm/lib/Transforms/Utils/FunctionComparator.cpp +++ llvm/lib/Transforms/Utils/FunctionComparator.cpp @@ -720,6 +720,16 @@ return 0; } +int FunctionComparator::cmpMetadataAsValue(const MetadataAsValue *L, + const MetadataAsValue *R) const { + if (L == R) + return 0; + + // Identical metadata is automatically merged, so let's just compare pointer + // identity. + return L < R ? -1 : 1; +} + int FunctionComparator::cmpInlineAsm(const InlineAsm *L, const InlineAsm *R) const { // InlineAsm's are uniqued. If they are the same pointer, obviously they are @@ -772,6 +782,19 @@ if (ConstR) return -1; + const MetadataAsValue *MDL = dyn_cast(L); + const MetadataAsValue *MDR = dyn_cast(R); + if (MDL && MDR) { + if (L == R) + return 0; + return cmpMetadataAsValue(MDL, MDR); + } + + if (MDL) + return 1; + if (MDR) + return -1; + const InlineAsm *InlineAsmL = dyn_cast(L); const InlineAsm *InlineAsmR = dyn_cast(R); @@ -791,8 +814,10 @@ // Test whether two basic blocks have equivalent behaviour. int FunctionComparator::cmpBasicBlocks(const BasicBlock *BBL, const BasicBlock *BBR) const { - BasicBlock::const_iterator InstL = BBL->begin(), InstLE = BBL->end(); - BasicBlock::const_iterator InstR = BBR->begin(), InstRE = BBR->end(); + auto WithoutDebugL = BBL->instructionsWithoutDebug(); + auto WithoutDebugR = BBR->instructionsWithoutDebug(); + auto InstL = WithoutDebugL.begin(), InstLE = WithoutDebugL.end(); + auto InstR = WithoutDebugR.begin(), InstRE = WithoutDebugR.end(); do { bool needToCmpOperands = true; @@ -962,7 +987,7 @@ // This random value acts as a block header, as otherwise the partition of // opcodes into BBs wouldn't affect the hash, only the order of the opcodes H.add(45798); - for (auto &Inst : *BB) { + for (auto &Inst : BB->instructionsWithoutDebug()) { H.add(Inst.getOpcode()); } const Instruction *Term = BB->getTerminator(); Index: llvm/test/Transforms/MergeFunc/merge-type-metadata.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/MergeFunc/merge-type-metadata.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -mergefunc < %s | FileCheck %s + +; CHECK: @call_vfunc1 +define internal i32 @call_vfunc1(i8* %vtable) unnamed_addr { + %a = tail call { i8*, i1 } @llvm.type.checked.load(i8* %vtable, i32 0, metadata !"vtype1") + ret i32 0 +} + +; CHECK-NOT: @call_vfunc2 +define internal i32 @call_vfunc2(i8* %vtable) unnamed_addr { + %a = tail call { i8*, i1 } @llvm.type.checked.load(i8* %vtable, i32 0, metadata !"vtype1") + ret i32 0 +} + +; CHECK: @call_vfunc3 +define internal i32 @call_vfunc3(i8* %vtable) unnamed_addr { + %a = tail call { i8*, i1 } @llvm.type.checked.load(i8* %vtable, i32 0, metadata !"vtype2") + ret i32 0 +} + +declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata) + +define void @main() { + %a = call i32 @call_vfunc1(i8* null) + ; CHECK: call i32 @call_vfunc1 + %b = call i32 @call_vfunc2(i8* null) + ; CHECK: call i32 @call_vfunc1 + %c = call i32 @call_vfunc3(i8* null) + ; CHECK: call i32 @call_vfunc3 + ret void +}