Index: llvm/include/llvm/Transforms/Utils/FunctionComparator.h =================================================================== --- llvm/include/llvm/Transforms/Utils/FunctionComparator.h +++ llvm/include/llvm/Transforms/Utils/FunctionComparator.h @@ -18,6 +18,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/ValueMap.h" #include "llvm/Support/AtomicOrdering.h" @@ -109,6 +111,12 @@ void beginCompare() { sn_mapL.clear(); sn_mapR.clear(); + + auto *M = FnL->getParent(); + Fn_dbg_declare = M->getFunction(Intrinsic::getName(Intrinsic::dbg_declare)); + Fn_dbg_value = M->getFunction(Intrinsic::getName(Intrinsic::dbg_value)); + Fn_dbg_addr = M->getFunction(Intrinsic::getName(Intrinsic::dbg_addr)); + Fn_dbg_label = M->getFunction(Intrinsic::getName(Intrinsic::dbg_label)); } /// Compares the signature and other general attributes of the two functions. @@ -243,7 +251,8 @@ /// then left value is greater. /// In another words, we compare serial numbers, for more details /// see comments for sn_mapL and sn_mapR. - int cmpValues(const Value *L, const Value *R) const; + int cmpValues(const Value *L, const Value *R, + bool needToCmpMetadata = true) const; /// Compare two Instructions for equivalence, similar to /// Instruction::isSameOperationAs. @@ -275,7 +284,7 @@ /// still must be compared afterwards. In this case it's already guaranteed /// that both instructions have the same number of operands. int cmpOperations(const Instruction *L, const Instruction *R, - bool &needToCmpOperands) const; + bool &needToCmpOperands, bool &needToCmpMetadata) const; /// cmpType - compares two types, /// defines total ordering among the types set. @@ -329,6 +338,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; @@ -385,6 +396,12 @@ // The global state we will use GlobalNumberState* GlobalNumbers; + + // @llvm.dbg.* functions, or null if not used in the module + Function *Fn_dbg_declare; + Function *Fn_dbg_value; + Function *Fn_dbg_addr; + Function *Fn_dbg_label; }; } // end namespace llvm Index: llvm/lib/Transforms/Utils/FunctionComparator.cpp =================================================================== --- llvm/lib/Transforms/Utils/FunctionComparator.cpp +++ llvm/lib/Transforms/Utils/FunctionComparator.cpp @@ -512,8 +512,10 @@ // Read method declaration comments for more details. int FunctionComparator::cmpOperations(const Instruction *L, const Instruction *R, - bool &needToCmpOperands) const { + bool &needToCmpOperands, + bool &needToCmpMetadata) const { needToCmpOperands = true; + needToCmpMetadata = true; if (int Res = cmpValues(L, R)) return Res; @@ -601,6 +603,15 @@ if (int Res = cmpNumbers(CI->getTailCallKind(), cast(R)->getTailCallKind())) return Res; + // Ignore metadata values in debug info intrinsic calls. + if (CBL->getCalledFunction() == Fn_dbg_declare) + needToCmpMetadata = false; + if (CBL->getCalledFunction() == Fn_dbg_value) + needToCmpMetadata = false; + if (CBL->getCalledFunction() == Fn_dbg_addr) + needToCmpMetadata = false; + if (CBL->getCalledFunction() == Fn_dbg_label) + needToCmpMetadata = false; return cmpRangeMetadata(L->getMetadata(LLVMContext::MD_range), R->getMetadata(LLVMContext::MD_range)); } @@ -720,6 +731,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 @@ -746,7 +767,8 @@ /// this is the first time the values are seen, they're added to the mapping so /// that we will detect mismatches on next use. /// See comments in declaration for more details. -int FunctionComparator::cmpValues(const Value *L, const Value *R) const { +int FunctionComparator::cmpValues(const Value *L, const Value *R, + bool needToCmpMetadata) const { // Catch self-reference case. if (L == FnL) { if (R == FnR) @@ -772,6 +794,21 @@ if (ConstR) return -1; + if (needToCmpMetadata) { + 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); @@ -796,7 +833,9 @@ do { bool needToCmpOperands = true; - if (int Res = cmpOperations(&*InstL, &*InstR, needToCmpOperands)) + bool needToCmpMetadata = true; + if (int Res = cmpOperations(&*InstL, &*InstR, needToCmpOperands, + needToCmpMetadata)) return Res; if (needToCmpOperands) { assert(InstL->getNumOperands() == InstR->getNumOperands()); @@ -804,7 +843,7 @@ for (unsigned i = 0, e = InstL->getNumOperands(); i != e; ++i) { Value *OpL = InstL->getOperand(i); Value *OpR = InstR->getOperand(i); - if (int Res = cmpValues(OpL, OpR)) + if (int Res = cmpValues(OpL, OpR, needToCmpMetadata)) return Res; // cmpValues should ensure this is true. assert(cmpTypes(OpL->getType(), OpR->getType()) == 0); 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 +}