diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -521,9 +521,8 @@ TypeCheckedLoadConstVCalls.takeVector(), std::move(ParamAccesses)); if (NonRenamableLocal) CantBePromoted.insert(F.getGUID()); - // errs() << "MM Going to add F " << F.getName() << " with global identifier - // as " << F.getGlobalIdentifier() - // << " to global value summary\n"; + errs() << "MM Going to add F " << F.getName() << " with global identifier as " + << F.getGlobalIdentifier() << " to global value summary\n"; Index.addGlobalValueSummary(F, std::move(FuncSummary)); } diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -948,13 +948,26 @@ bool DevirtModule::mustBeUnreachableFunction(Function *TheFn, ModuleSummaryIndex *ExportSummary, bool IsExported) { - // ExportSummary is absent. No sufficient information to determine - // if the function is reachable. + // ExportSummary is absent, so analyze IR directly. if (ExportSummary == nullptr) { + if (!TheFn->empty()) { + const BasicBlock &entryBlock = TheFn->getEntryBlock(); + // A function must be unreachable if its basic block + // ends with an 'unreachable'. + if (!entryBlock.empty()) { + const Instruction *inst = &(*entryBlock.rbegin()); + if (inst->getOpcode() == Instruction::Unreachable) { + return true; + } + } + } return false; } assert((TheFn != nullptr) && "Caller guarantees that TheFn is not nullptr"); + errs() << "\tGlobal identifier with current linkage is " + << TheFn->getGlobalIdentifier() << "\n"; + // If a function will be exported, use external linkage to get its // global identifier. const std::string rewrittenFuncGlobalIdentifier = @@ -962,6 +975,8 @@ IsExported ? GlobalValue::ExternalLinkage : TheFn->getLinkage(), TheFn->getParent()->getSourceFileName()); + errs() << "\tGlobal identifier with rewritten linkage is " + << rewrittenFuncGlobalIdentifier << "\n"; if (ValueInfo TheFnVI = ExportSummary->getValueInfo( GlobalValue::getGUID(rewrittenFuncGlobalIdentifier))) { @@ -969,8 +984,13 @@ return false; } bool AllSummariesAreFunctionSummary = true; + bool AllSummariesAreLive = true; bool AllFunctionSummariesIndicateUnreachable = true; for (auto &Summary : TheFnVI.getSummaryList()) { + if (!Summary->isLive()) { + AllSummariesAreLive = false; + break; + } if (auto *FS = dyn_cast(Summary.get())) { if (!FS->fflags().MustBeUnreachable) { AllFunctionSummariesIndicateUnreachable = false; @@ -982,9 +1002,10 @@ } } // Identifies a function as unreachable if and only if - // 1) All summaries are function summaries. - // 2) All function summaries indicate it's unreachable. - if (AllSummariesAreFunctionSummary && + // 1) All summaries are live. + // 2) All summaries are function summaries. + // 3) All function summaries indicate it's unreachable. + if (AllSummariesAreLive && AllSummariesAreFunctionSummary && AllFunctionSummariesIndicateUnreachable) { return true; } @@ -1030,6 +1051,10 @@ std::vector &TargetsForSlot, const std::set &TypeMemberInfos, uint64_t ByteOffset, ModuleSummaryIndex *ExportSummary, const bool IsExported) { + if (ExportSummary != nullptr) { + errs() << "Dump export summary: "; + ExportSummary->dump(); + } for (const TypeMemberInfo &TM : TypeMemberInfos) { if (!TM.Bits->GV->isConstant()) return false; diff --git a/llvm/test/ThinLTO/X86/Inputs/d1.ll b/llvm/test/ThinLTO/X86/Inputs/d1.ll new file mode 100644 --- /dev/null +++ b/llvm/test/ThinLTO/X86/Inputs/d1.ll @@ -0,0 +1,204 @@ +; ModuleID = '/usr/local/google/home/mingmingl/test/d1.cc' +source_filename = "/usr/local/google/home/mingmingl/test/d1.cc" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%class.Derived = type { %class.Base } +%class.Base = type { i32 (...)** } + +$_ZN7DerivedD2Ev = comdat any + +$_ZN7DerivedD0Ev = comdat any + +$__clang_call_terminate = comdat any + +$_ZN4BaseD2Ev = comdat any + +$_ZN4BaseD0Ev = comdat any + +$_ZTS4Base = comdat any + +$_ZTI4Base = comdat any + +$_ZTV4Base = comdat any + +@.str = private unnamed_addr constant [12 x i8] c"Derived::x\0A\00", align 1 +@_ZTV7Derived = hidden unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI7Derived to i8*), i8* bitcast (void (%class.Derived*)* @_ZN7DerivedD2Ev to i8*), i8* bitcast (void (%class.Derived*)* @_ZN7DerivedD0Ev to i8*), i8* bitcast (void (%class.Derived*)* @_ZN7Derived1xEv to i8*)] }, align 8, !type !0, !type !1, !type !2, !type !3, !vcall_visibility !4 +@_ZTVN10__cxxabiv120__si_class_type_infoE = external dso_local global i8* +@_ZTS7Derived = hidden constant [9 x i8] c"7Derived\00", align 1 +@_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global i8* +@_ZTS4Base = linkonce_odr hidden constant [6 x i8] c"4Base\00", comdat, align 1 +@_ZTI4Base = linkonce_odr hidden constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @_ZTS4Base, i32 0, i32 0) }, comdat, align 8 +@_ZTI7Derived = hidden constant { i8*, i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @_ZTS7Derived, i32 0, i32 0), i8* bitcast ({ i8*, i8* }* @_ZTI4Base to i8*) }, align 8 +@.str.1 = private unnamed_addr constant [24 x i8] c"In Derived::~Derived()\0A\00", align 1 +@_ZTV4Base = linkonce_odr hidden unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI4Base to i8*), i8* bitcast (void (%class.Base*)* @_ZN4BaseD2Ev to i8*), i8* bitcast (void (%class.Base*)* @_ZN4BaseD0Ev to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*)] }, comdat, align 8, !type !0, !type !1, !vcall_visibility !4 +@.str.2 = private unnamed_addr constant [18 x i8] c"In Base::~Base()\0A\00", align 1 + +; Function Attrs: mustprogress noinline optnone uwtable +define hidden void @_ZN7Derived1xEv(%class.Derived* nonnull align 8 dereferenceable(8) %this) unnamed_addr #0 align 2 { +entry: + %this.addr = alloca %class.Derived*, align 8 + store %class.Derived* %this, %class.Derived** %this.addr, align 8 + %this1 = load %class.Derived*, %class.Derived** %this.addr, align 8 + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i64 0, i64 0)) + ret void +} + +declare dso_local i32 @printf(i8*, ...) #1 + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define hidden void @_Z3fooP4Base(%class.Base* %b) #2 { +entry: + %b.addr = alloca %class.Base*, align 8 + store %class.Base* %b, %class.Base** %b.addr, align 8 + %0 = load %class.Base*, %class.Base** %b.addr, align 8 + %isnull = icmp eq %class.Base* %0, null + br i1 %isnull, label %delete.end, label %delete.notnull + +delete.notnull: ; preds = %entry + %1 = bitcast %class.Base* %0 to void (%class.Base*)*** + %vtable = load void (%class.Base*)**, void (%class.Base*)*** %1, align 8 + %2 = bitcast void (%class.Base*)** %vtable to i8* + %3 = call i1 @llvm.type.test(i8* %2, metadata !"_ZTS4Base") + call void @llvm.assume(i1 %3) + %vfn = getelementptr inbounds void (%class.Base*)*, void (%class.Base*)** %vtable, i64 1 + %4 = load void (%class.Base*)*, void (%class.Base*)** %vfn, align 8 + call void %4(%class.Base* nonnull align 8 dereferenceable(8) %0) #9 + br label %delete.end + +delete.end: ; preds = %delete.notnull, %entry + ret void +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare i1 @llvm.type.test(i8*, metadata) #3 + +; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn +declare void @llvm.assume(i1 noundef) #4 + +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr hidden void @_ZN7DerivedD2Ev(%class.Derived* nonnull align 8 dereferenceable(8) %this) unnamed_addr #5 comdat align 2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + %this.addr = alloca %class.Derived*, align 8 + %exn.slot = alloca i8*, align 8 + %ehselector.slot = alloca i32, align 4 + store %class.Derived* %this, %class.Derived** %this.addr, align 8 + %this1 = load %class.Derived*, %class.Derived** %this.addr, align 8 + %0 = bitcast %class.Derived* %this1 to i32 (...)*** + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTV7Derived, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %0, align 8 + %call = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.1, i64 0, i64 0)) + to label %invoke.cont unwind label %lpad + +invoke.cont: ; preds = %entry + %1 = bitcast %class.Derived* %this1 to %class.Base* + call void @_ZN4BaseD2Ev(%class.Base* nonnull align 8 dereferenceable(8) %1) #9 + ret void + +lpad: ; preds = %entry + %2 = landingpad { i8*, i32 } + catch i8* null + %3 = extractvalue { i8*, i32 } %2, 0 + store i8* %3, i8** %exn.slot, align 8 + %4 = extractvalue { i8*, i32 } %2, 1 + store i32 %4, i32* %ehselector.slot, align 4 + %5 = bitcast %class.Derived* %this1 to %class.Base* + call void @_ZN4BaseD2Ev(%class.Base* nonnull align 8 dereferenceable(8) %5) #9 + br label %terminate.handler + +terminate.handler: ; preds = %lpad + %exn = load i8*, i8** %exn.slot, align 8 + call void @__clang_call_terminate(i8* %exn) #10 + unreachable +} + +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr hidden void @_ZN7DerivedD0Ev(%class.Derived* nonnull align 8 dereferenceable(8) %this) unnamed_addr #5 comdat align 2 { +entry: + %this.addr = alloca %class.Derived*, align 8 + store %class.Derived* %this, %class.Derived** %this.addr, align 8 + %this1 = load %class.Derived*, %class.Derived** %this.addr, align 8 + call void @_ZN7DerivedD2Ev(%class.Derived* nonnull align 8 dereferenceable(8) %this1) #9 + %0 = bitcast %class.Derived* %this1 to i8* + call void @_ZdlPv(i8* %0) #11 + ret void +} + +declare dso_local i32 @__gxx_personality_v0(...) + +; Function Attrs: noinline noreturn nounwind +define linkonce_odr hidden void @__clang_call_terminate(i8* %0) #6 comdat { + %2 = call i8* @__cxa_begin_catch(i8* %0) #9 + call void @_ZSt9terminatev() #10 + unreachable +} + +declare dso_local i8* @__cxa_begin_catch(i8*) + +declare dso_local void @_ZSt9terminatev() + +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr hidden void @_ZN4BaseD2Ev(%class.Base* nonnull align 8 dereferenceable(8) %this) unnamed_addr #5 comdat align 2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + %this.addr = alloca %class.Base*, align 8 + store %class.Base* %this, %class.Base** %this.addr, align 8 + %this1 = load %class.Base*, %class.Base** %this.addr, align 8 + %0 = bitcast %class.Base* %this1 to i32 (...)*** + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTV4Base, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %0, align 8 + %call = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.2, i64 0, i64 0)) + to label %invoke.cont unwind label %terminate.lpad + +invoke.cont: ; preds = %entry + ret void + +terminate.lpad: ; preds = %entry + %1 = landingpad { i8*, i32 } + catch i8* null + %2 = extractvalue { i8*, i32 } %1, 0 + call void @__clang_call_terminate(i8* %2) #10 + unreachable +} + +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr hidden void @_ZN4BaseD0Ev(%class.Base* nonnull align 8 dereferenceable(8) %this) unnamed_addr #5 comdat align 2 { +entry: + %this.addr = alloca %class.Base*, align 8 + store %class.Base* %this, %class.Base** %this.addr, align 8 + %this1 = load %class.Base*, %class.Base** %this.addr, align 8 + call void @llvm.trap() #10 + unreachable +} + +declare dso_local void @__cxa_pure_virtual() unnamed_addr + +; Function Attrs: cold noreturn nounwind +declare void @llvm.trap() #7 + +; Function Attrs: nobuiltin nounwind +declare dso_local void @_ZdlPv(i8*) #8 + +attributes #0 = { mustprogress noinline optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #2 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { nofree nosync nounwind readnone speculatable willreturn } +attributes #4 = { inaccessiblememonly nofree nosync nounwind willreturn } +attributes #5 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #6 = { noinline noreturn nounwind } +attributes #7 = { cold noreturn nounwind } +attributes #8 = { nobuiltin nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #9 = { nounwind } +attributes #10 = { noreturn nounwind } +attributes #11 = { builtin nounwind } + +!llvm.module.flags = !{!5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = !{i64 16, !"_ZTS4Base"} +!1 = !{i64 32, !"_ZTSM4BaseFvvE.virtual"} +!2 = !{i64 16, !"_ZTS7Derived"} +!3 = !{i64 32, !"_ZTSM7DerivedFvvE.virtual"} +!4 = !{i64 1} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 1, !"Virtual Function Elim", i32 0} +!7 = !{i32 7, !"uwtable", i32 1} +!8 = !{i32 7, !"frame-pointer", i32 2} +!9 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git f6ae8e8cc7f495dad86e97bd9bbd828f9079fc9b)"} diff --git a/llvm/test/ThinLTO/X86/d.ll b/llvm/test/ThinLTO/X86/d.ll new file mode 100644 --- /dev/null +++ b/llvm/test/ThinLTO/X86/d.ll @@ -0,0 +1,238 @@ +; RUN: opt -thinlto-bc -thinlto-split-lto-unit %s -o %t-main.bc +; RUN: opt -thinlto-bc -thinlto-split-lto-unit %p/Inputs/d1.ll -o %t-foo.bc +; RUN: llvm-lto2 run -save-temps %t-main.bc %t-foo.bc -pass-remarks=. -o %t \ +; RUN: -whole-program-visibility \ +; RUN: -wholeprogramdevirt-print-index-based \ +; RUN: -r=%t-main.bc,main,plx \ +; RUN: -r=%t-main.bc,_Znwm,px \ +; RUN: -r=%t-main.bc,_ZN7DerivedC2Ev, \ +; RUN: -r=%t-main.bc,__gxx_personality_v0, \ +; RUN: -r=%t-foo.bc,__gxx_personality_v0, \ +; RUN: -r=%t-main.bc,_ZdlPv, \ +; RUN: -r=%t-foo.bc,_ZdlPv, \ +; RUN: -r=%t-foo.bc,_ZTS7Derived, \ +; RUN: -r=%t-main.bc,_Z3fooP4Base, \ +; RUN: -r=%t-main.bc,_ZN4BaseC2Ev, \ +; RUN: -r=%t-main.bc,_ZN4BaseD2Ev, \ +; RUN: -r=%t-main.bc,_ZN4BaseD2Ev, \ +; RUN: -r=%t-foo.bc,_ZN4BaseD2Ev, \ +; RUN: -r=%t-foo.bc,_ZN4BaseD2Ev, \ +; RUN: -r=%t-main.bc,_ZN4BaseD0Ev, \ +; RUN: -r=%t-main.bc,_ZN4BaseD0Ev, \ +; RUN: -r=%t-foo.bc,_ZN4BaseD0Ev, \ +; RUN: -r=%t-main.bc,__cxa_pure_virtual, \ +; RUN: -r=%t-main.bc,__cxa_pure_virtual, \ +; RUN: -r=%t-foo.bc,__cxa_pure_virtual, \ +; RUN: -r=%t-foo.bc,__cxa_pure_virtual, \ +; RUN: -r=%t-main.bc,printf, \ +; RUN: -r=%t-main.bc,__clang_call_terminate, \ +; RUN: -r=%t-main.bc,__cxa_begin_catch, \ +; RUN: -r=%t-foo.bc,__clang_call_terminate, \ +; RUN: -r=%t-foo.bc,__cxa_begin_catch, \ +; RUN: -r=%t-main.bc,_ZSt9terminatev, \ +; RUN: -r=%t-foo.bc,_ZSt9terminatev, \ +; RUN: -r=%t-main.bc,_ZTV7Derived, \ +; RUN: -r=%t-foo.bc,_ZTV7Derived, \ +; RUN: -r=%t-foo.bc,_ZTV7Derived, \ +; RUN: -r=%t-main.bc,_ZTV4Base, \ +; RUN: -r=%t-main.bc,_ZTV4Base, \ +; RUN: -r=%t-foo.bc,_ZTV4Base, \ +; RUN: -r=%t-main.bc,_ZTVN10__cxxabiv117__class_type_infoE, \ +; RUN: -r=%t-foo.bc,_ZTVN10__cxxabiv117__class_type_infoE, \ +; RUN: -r=%t-foo.bc,_ZTVN10__cxxabiv120__si_class_type_infoE, \ +; RUN: -r=%t-main.bc,_ZTS4Base, \ +; RUN: -r=%t-foo.bc,_ZTS4Base, \ +; RUN: -r=%t-foo.bc,_ZTI7Derived, \ +; RUN: -r=%t-foo.bc,_ZTI7Derived, \ +; RUN: -r=%t-main.bc,_ZTI4Base, \ +; RUN: -r=%t-main.bc,_ZTI4Base, \ +; RUN: -r=%t-foo.bc,_ZTI4Base, \ +; RUN: -r=%t-foo.bc,_ZTI4Base, \ +; RUN: -r=%t-foo.bc,_ZN4BaseD0Ev, \ +; RUN: -r=%t-foo.bc,_ZN7Derived1xEv, \ +; RUN: -r=%t-foo.bc,_ZN7Derived1xEv, \ +; RUN: -r=%t-foo.bc,printf, \ +; RUN: -r=%t-foo.bc,_Z3fooP4Base, \ +; RUN: -r=%t-foo.bc,_ZN7DerivedD2Ev,plx \ +; RUN: -r=%t-foo.bc,_ZN7DerivedD2Ev,x \ +; RUN: -r=%t-foo.bc,_ZN7DerivedD0Ev,plx \ +; RUN: -r=%t-foo.bc,_ZN7DerivedD0Ev,x \ +; RUN: -r=%t-foo.bc,_ZTV4Base, 2>&1 | FileCheck %s --check-prefix=REMARK + +; REMARK-COUNT-1: single-impl: devirtualized a call to _ZN7DerivedD0Ev + +; ModuleID = '/usr/local/google/home/mingmingl/test/d2.cc' +source_filename = "/usr/local/google/home/mingmingl/test/d2.cc" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%class.Derived = type { %class.Base } +%class.Base = type { i32 (...)** } + +$_ZN7DerivedC2Ev = comdat any + +$_ZN4BaseC2Ev = comdat any + +$_ZN4BaseD2Ev = comdat any + +$_ZN4BaseD0Ev = comdat any + +$__clang_call_terminate = comdat any + +$_ZTV4Base = comdat any + +$_ZTS4Base = comdat any + +$_ZTI4Base = comdat any + +@_ZTV7Derived = external dso_local unnamed_addr constant { [5 x i8*] }, align 8 +@_ZTV4Base = linkonce_odr hidden unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI4Base to i8*), i8* bitcast (void (%class.Base*)* @_ZN4BaseD2Ev to i8*), i8* bitcast (void (%class.Base*)* @_ZN4BaseD0Ev to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*)] }, comdat, align 8, !type !0, !type !1, !vcall_visibility !2 +@_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global i8* +@_ZTS4Base = linkonce_odr hidden constant [6 x i8] c"4Base\00", comdat, align 1 +@_ZTI4Base = linkonce_odr hidden constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @_ZTS4Base, i32 0, i32 0) }, comdat, align 8 +@.str = private unnamed_addr constant [18 x i8] c"In Base::~Base()\0A\00", align 1 + +; Function Attrs: mustprogress noinline norecurse optnone uwtable +define hidden i32 @main() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + %d = alloca %class.Derived*, align 8 + %exn.slot = alloca i8*, align 8 + %ehselector.slot = alloca i32, align 4 + %call = call noalias nonnull i8* @_Znwm(i64 8) #8 + %0 = bitcast i8* %call to %class.Derived* + invoke void @_ZN7DerivedC2Ev(%class.Derived* nonnull align 8 dereferenceable(8) %0) + to label %invoke.cont unwind label %lpad + +invoke.cont: ; preds = %entry + store %class.Derived* %0, %class.Derived** %d, align 8 + %1 = load %class.Derived*, %class.Derived** %d, align 8 + %2 = bitcast %class.Derived* %1 to %class.Base* + call void @_Z3fooP4Base(%class.Base* %2) + ret i32 0 + +lpad: ; preds = %entry + %3 = landingpad { i8*, i32 } + cleanup + %4 = extractvalue { i8*, i32 } %3, 0 + store i8* %4, i8** %exn.slot, align 8 + %5 = extractvalue { i8*, i32 } %3, 1 + store i32 %5, i32* %ehselector.slot, align 4 + call void @_ZdlPv(i8* %call) #9 + br label %eh.resume + +eh.resume: ; preds = %lpad + %exn = load i8*, i8** %exn.slot, align 8 + %sel = load i32, i32* %ehselector.slot, align 4 + %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn, 0 + %lpad.val1 = insertvalue { i8*, i32 } %lpad.val, i32 %sel, 1 + resume { i8*, i32 } %lpad.val1 +} + +; Function Attrs: nobuiltin allocsize(0) +declare dso_local nonnull i8* @_Znwm(i64) #1 + +; Function Attrs: noinline optnone uwtable +define linkonce_odr hidden void @_ZN7DerivedC2Ev(%class.Derived* nonnull align 8 dereferenceable(8) %this) unnamed_addr #2 comdat align 2 { +entry: + %this.addr = alloca %class.Derived*, align 8 + store %class.Derived* %this, %class.Derived** %this.addr, align 8 + %this1 = load %class.Derived*, %class.Derived** %this.addr, align 8 + %0 = bitcast %class.Derived* %this1 to %class.Base* + call void @_ZN4BaseC2Ev(%class.Base* nonnull align 8 dereferenceable(8) %0) + %1 = bitcast %class.Derived* %this1 to i32 (...)*** + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTV7Derived, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %1, align 8 + ret void +} + +declare dso_local i32 @__gxx_personality_v0(...) + +; Function Attrs: nobuiltin nounwind +declare dso_local void @_ZdlPv(i8*) #3 + +declare dso_local void @_Z3fooP4Base(%class.Base*) #4 + +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr hidden void @_ZN4BaseC2Ev(%class.Base* nonnull align 8 dereferenceable(8) %this) unnamed_addr #5 comdat align 2 { +entry: + %this.addr = alloca %class.Base*, align 8 + store %class.Base* %this, %class.Base** %this.addr, align 8 + %this1 = load %class.Base*, %class.Base** %this.addr, align 8 + %0 = bitcast %class.Base* %this1 to i32 (...)*** + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTV4Base, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %0, align 8 + ret void +} + +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr hidden void @_ZN4BaseD2Ev(%class.Base* nonnull align 8 dereferenceable(8) %this) unnamed_addr #5 comdat align 2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + %this.addr = alloca %class.Base*, align 8 + store %class.Base* %this, %class.Base** %this.addr, align 8 + %this1 = load %class.Base*, %class.Base** %this.addr, align 8 + %0 = bitcast %class.Base* %this1 to i32 (...)*** + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTV4Base, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %0, align 8 + %call = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str, i64 0, i64 0)) + to label %invoke.cont unwind label %terminate.lpad + +invoke.cont: ; preds = %entry + ret void + +terminate.lpad: ; preds = %entry + %1 = landingpad { i8*, i32 } + catch i8* null + %2 = extractvalue { i8*, i32 } %1, 0 + call void @__clang_call_terminate(i8* %2) #10 + unreachable +} + +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr hidden void @_ZN4BaseD0Ev(%class.Base* nonnull align 8 dereferenceable(8) %this) unnamed_addr #5 comdat align 2 { +entry: + %this.addr = alloca %class.Base*, align 8 + store %class.Base* %this, %class.Base** %this.addr, align 8 + %this1 = load %class.Base*, %class.Base** %this.addr, align 8 + call void @llvm.trap() #10 + unreachable +} + +declare dso_local void @__cxa_pure_virtual() unnamed_addr + +declare dso_local i32 @printf(i8*, ...) #4 + +; Function Attrs: noinline noreturn nounwind +define linkonce_odr hidden void @__clang_call_terminate(i8* %0) #6 comdat { + %2 = call i8* @__cxa_begin_catch(i8* %0) #11 + call void @_ZSt9terminatev() #10 + unreachable +} + +declare dso_local i8* @__cxa_begin_catch(i8*) + +declare dso_local void @_ZSt9terminatev() + +; Function Attrs: cold noreturn nounwind +declare void @llvm.trap() #7 + +attributes #0 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nobuiltin allocsize(0) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #2 = { noinline optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { nobuiltin nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #4 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #5 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #6 = { noinline noreturn nounwind } +attributes #7 = { cold noreturn nounwind } +attributes #8 = { builtin allocsize(0) } +attributes #9 = { builtin nounwind } +attributes #10 = { noreturn nounwind } +attributes #11 = { nounwind } + +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = !{i64 16, !"_ZTS4Base"} +!1 = !{i64 32, !"_ZTSM4BaseFvvE.virtual"} +!2 = !{i64 1} +!3 = !{i32 1, !"wchar_size", i32 4} +!4 = !{i32 1, !"Virtual Function Elim", i32 0} +!5 = !{i32 7, !"uwtable", i32 1} +!6 = !{i32 7, !"frame-pointer", i32 2} +!7 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git f6ae8e8cc7f495dad86e97bd9bbd828f9079fc9b)"} diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp --- a/llvm/tools/llvm-lto2/llvm-lto2.cpp +++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp @@ -229,7 +229,8 @@ return 1; } } - //llvm::errs() << "Insert [" << std::string(FileName) << ", " << std::string(SymbolName) << "] into map\n"; + // llvm::errs() << "Insert [" << std::string(FileName) << ", " << + // std::string(SymbolName) << "] into map\n"; CommandLineResolutions[{std::string(FileName), std::string(SymbolName)}] .push_back(Res); }