Index: include/llvm/Analysis/ModuleSummaryAnalysis.h =================================================================== --- include/llvm/Analysis/ModuleSummaryAnalysis.h +++ include/llvm/Analysis/ModuleSummaryAnalysis.h @@ -21,6 +21,7 @@ namespace llvm { class BlockFrequencyInfo; +class ProfileSummaryInfo; /// Direct function to compute a \c ModuleSummaryIndex from a given module. /// @@ -30,8 +31,8 @@ /// that information. ModuleSummaryIndex buildModuleSummaryIndex( const Module &M, - std::function GetBFICallback = - nullptr); + std::function GetBFICallback, + ProfileSummaryInfo &PSI); /// Analysis pass to provide the ModuleSummaryIndex object. class ModuleSummaryIndexAnalysis Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -194,20 +194,20 @@ // and combined index cases. enum GlobalValueSummarySymtabCodes { // PERMODULE: [valueid, flags, instcount, numrefs, numrefs x valueid, - // n x (valueid, callsitecount)] + // n x (valueid)] FS_PERMODULE = 1, // PERMODULE_PROFILE: [valueid, flags, instcount, numrefs, // numrefs x valueid, - // n x (valueid, callsitecount, profilecount)] + // n x (valueid, hotness)] FS_PERMODULE_PROFILE = 2, // PERMODULE_GLOBALVAR_INIT_REFS: [valueid, flags, n x valueid] FS_PERMODULE_GLOBALVAR_INIT_REFS = 3, // COMBINED: [valueid, modid, flags, instcount, numrefs, numrefs x valueid, - // n x (valueid, callsitecount)] + // n x (valueid)] FS_COMBINED = 4, // COMBINED_PROFILE: [valueid, modid, flags, instcount, numrefs, // numrefs x valueid, - // n x (valueid, callsitecount, profilecount)] + // n x (valueid, hotness)] FS_COMBINED_PROFILE = 5, // COMBINED_GLOBALVAR_INIT_REFS: [valueid, modid, flags, n x valueid] FS_COMBINED_GLOBALVAR_INIT_REFS = 6, Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -30,18 +30,14 @@ /// \brief Class to accumulate and hold information about a callee. struct CalleeInfo { - /// The static number of callsites calling corresponding function. - unsigned CallsiteCount; - /// The cumulative profile count of calls to corresponding function - /// (if using PGO, otherwise 0). - uint64_t ProfileCount; - CalleeInfo() : CallsiteCount(0), ProfileCount(0) {} - CalleeInfo(unsigned CallsiteCount, uint64_t ProfileCount) - : CallsiteCount(CallsiteCount), ProfileCount(ProfileCount) {} - CalleeInfo &operator+=(uint64_t RHSProfileCount) { - CallsiteCount++; - ProfileCount += RHSProfileCount; - return *this; + enum class HotnessType : uint8_t { Unknown = 0, Cold = 1, None = 2, Hot = 3 }; + HotnessType Hotness = HotnessType::Unknown; + + CalleeInfo() = default; + explicit CalleeInfo(HotnessType Hotness) : Hotness(Hotness) {} + + void updateHotness(const HotnessType OtherHotness) { + Hotness = std::max(Hotness, OtherHotness); } }; Index: lib/Analysis/ModuleSummaryAnalysis.cpp =================================================================== --- lib/Analysis/ModuleSummaryAnalysis.cpp +++ lib/Analysis/ModuleSummaryAnalysis.cpp @@ -18,6 +18,7 @@ #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/IndirectCallPromotionAnalysis.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/InstIterator.h" @@ -63,8 +64,18 @@ } } +static CalleeInfo::HotnessType getHotness(uint64_t ProfileCount, + ProfileSummaryInfo &PSI) { + if (PSI.isHotCount(ProfileCount)) + return CalleeInfo::HotnessType::Hot; + if (PSI.isColdCount(ProfileCount)) + return CalleeInfo::HotnessType::Cold; + return CalleeInfo::HotnessType::None; +} + static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M, - const Function &F, BlockFrequencyInfo *BFI) { + const Function &F, BlockFrequencyInfo *BFI, + ProfileSummaryInfo &PSI) { // Summary not currently supported for anonymous functions, they must // be renamed. if (!F.hasName()) @@ -97,7 +108,9 @@ auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None; auto *CalleeId = M.getValueSymbolTable().lookup(CalledFunction->getName()); - CallGraphEdges[CalleeId] += (ScaledCount ? ScaledCount.getValue() : 0); + CallGraphEdges[CalleeId].updateHotness( + ScaledCount ? getHotness(ScaledCount.getValue(), PSI) + : CalleeInfo::HotnessType::Unknown); } else { const auto *CI = dyn_cast(&I); // Skip inline assembly calls. @@ -113,7 +126,8 @@ ICallAnalysis.getPromotionCandidatesForInstruction( &I, NumVals, TotalCount, NumCandidates); for (auto &Candidate : CandidateProfileData) - IndirectCallEdges[Candidate.Value] += Candidate.Count; + IndirectCallEdges[Candidate.Value].updateHotness( + getHotness(Candidate.Count, PSI)); } } @@ -140,7 +154,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex( const Module &M, - std::function GetBFICallback) { + std::function GetBFICallback, + ProfileSummaryInfo &PSI) { ModuleSummaryIndex Index; // Check if the module can be promoted, otherwise just disable importing from // it by not emitting any summary. @@ -165,7 +180,7 @@ BFI = BFIPtr.get(); } - computeFunctionSummary(Index, M, F, BFI); + computeFunctionSummary(Index, M, F, BFI, PSI); } // Compute summaries for all variables defined in module, and save in the @@ -182,10 +197,15 @@ ModuleSummaryIndex ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) { + ProfileSummaryInfo &PSI = AM.getResult(M); auto &FAM = AM.getResult(M).getManager(); - return buildModuleSummaryIndex(M, [&FAM](const Function &F) { - return &FAM.getResult(*const_cast(&F)); - }); + return buildModuleSummaryIndex( + M, + [&FAM](const Function &F) { + return &FAM.getResult( + *const_cast(&F)); + }, + PSI); } char ModuleSummaryIndexWrapperPass::ID = 0; @@ -205,11 +225,15 @@ } bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) { - Index = buildModuleSummaryIndex(M, [this](const Function &F) { - return &(this->getAnalysis( - *const_cast(&F)) - .getBFI()); - }); + auto &PSI = *getAnalysis().getPSI(M); + Index = buildModuleSummaryIndex( + M, + [this](const Function &F) { + return &(this->getAnalysis( + *const_cast(&F)) + .getBFI()); + }, + PSI); return false; } @@ -221,6 +245,7 @@ void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); + AU.addRequired(); } bool llvm::moduleCanBeRenamedForThinLTO(const Module &M) { Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -6217,8 +6217,10 @@ return error("Invalid Summary Block: version expected"); } const uint64_t Version = Record[0]; - if (Version != 1) - return error("Invalid summary version " + Twine(Version) + ", 1 expected"); + const bool IsOldProfileFormat = Version == 1; + if (!IsOldProfileFormat && Version != 2) + return error("Invalid summary version " + Twine(Version) + + ", 1 or 2 expected"); Record.clear(); // Keep around the last seen summary to be used when we see an optional @@ -6263,10 +6265,10 @@ default: // Default behavior: ignore. break; // FS_PERMODULE: [valueid, flags, instcount, numrefs, numrefs x valueid, - // n x (valueid, callsitecount)] + // n x (valueid)] // FS_PERMODULE_PROFILE: [valueid, flags, instcount, numrefs, // numrefs x valueid, - // n x (valueid, callsitecount, profilecount)] + // n x (valueid, hotness)] case bitc::FS_PERMODULE: case bitc::FS_PERMODULE_PROFILE: { unsigned ValueID = Record[0]; @@ -6296,11 +6298,13 @@ for (unsigned I = CallGraphEdgeStartIndex, E = Record.size(); I != E; ++I) { unsigned CalleeValueId = Record[I]; - unsigned CallsiteCount = Record[++I]; - uint64_t ProfileCount = HasProfile ? Record[++I] : 0; + CalleeInfo::HotnessType Hotness = CalleeInfo::HotnessType::Unknown; + if (IsOldProfileFormat) + I += 2; // Skip 2 old fields (callsite_count, profile_count). + else if (HasProfile) // can interpret hotness with new version. + Hotness = static_cast(Record[++I]); GlobalValue::GUID CalleeGUID = getGUIDFromValueId(CalleeValueId).first; - FS->addCallGraphEdge(CalleeGUID, - CalleeInfo(CallsiteCount, ProfileCount)); + FS->addCallGraphEdge(CalleeGUID, CalleeInfo(Hotness)); } auto GUID = getGUIDFromValueId(ValueID); FS->setOriginalName(GUID.second); @@ -6355,10 +6359,9 @@ break; } // FS_COMBINED: [valueid, modid, flags, instcount, numrefs, - // numrefs x valueid, n x (valueid, callsitecount)] + // numrefs x valueid, n x (valueid)] // FS_COMBINED_PROFILE: [valueid, modid, flags, instcount, numrefs, - // numrefs x valueid, - // n x (valueid, callsitecount, profilecount)] + // numrefs x valueid, n x (valueid, hotness)] case bitc::FS_COMBINED: case bitc::FS_COMBINED_PROFILE: { unsigned ValueID = Record[0]; @@ -6385,11 +6388,13 @@ for (unsigned I = CallGraphEdgeStartIndex, E = Record.size(); I != E; ++I) { unsigned CalleeValueId = Record[I]; - unsigned CallsiteCount = Record[++I]; - uint64_t ProfileCount = HasProfile ? Record[++I] : 0; + CalleeInfo::HotnessType Hotness = CalleeInfo::HotnessType::Unknown; + if (IsOldProfileFormat) + I += 2; // Skip 2 old fields (callsite_count, profile_count). + else if (HasProfile) // Can interpret hotness with new version. + Hotness = static_cast(Record[++I]); GlobalValue::GUID CalleeGUID = getGUIDFromValueId(CalleeValueId).first; - FS->addCallGraphEdge(CalleeGUID, - CalleeInfo(CallsiteCount, ProfileCount)); + FS->addCallGraphEdge(CalleeGUID, CalleeInfo(Hotness)); } GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first; TheIndex->addGlobalValueSummary(GUID, std::move(FS)); Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -3292,10 +3292,8 @@ bool HasProfileData = F.getEntryCount().hasValue(); for (auto &ECI : Calls) { NameVals.push_back(getValueId(ECI.first)); - assert(ECI.second.CallsiteCount > 0 && "Expected at least one callsite"); - NameVals.push_back(ECI.second.CallsiteCount); if (HasProfileData) - NameVals.push_back(ECI.second.ProfileCount); + NameVals.push_back(static_cast(ECI.second.Hotness)); } unsigned FSAbbrev = (HasProfileData ? FSCallsProfileAbbrev : FSCallsAbbrev); @@ -3335,7 +3333,7 @@ // Current version for the summary. // This is bumped whenever we introduce changes in the way some record are // interpreted, like flags for instance. -static const uint64_t INDEX_VERSION = 1; +static const uint64_t INDEX_VERSION = 2; /// Emit the per-module summary section alongside the rest of /// the module's bitcode. @@ -3354,7 +3352,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs - // numrefs x valueid, n x (valueid, callsitecount) + // numrefs x valueid, n x (valueid) Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); unsigned FSCallsAbbrev = Stream.EmitAbbrev(Abbv); @@ -3366,7 +3364,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs - // numrefs x valueid, n x (valueid, callsitecount, profilecount) + // numrefs x valueid, n x (valueid, hotness) Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); unsigned FSCallsProfileAbbrev = Stream.EmitAbbrev(Abbv); @@ -3439,7 +3437,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs - // numrefs x valueid, n x (valueid, callsitecount) + // numrefs x valueid, n x (valueid) Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); unsigned FSCallsAbbrev = Stream.EmitAbbrev(Abbv); @@ -3452,7 +3450,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs - // numrefs x valueid, n x (valueid, callsitecount, profilecount) + // numrefs x valueid, n x (valueid, hotness) Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); unsigned FSCallsProfileAbbrev = Stream.EmitAbbrev(Abbv); @@ -3539,7 +3537,7 @@ bool HasProfileData = false; for (auto &EI : FS->calls()) { - HasProfileData |= EI.second.ProfileCount != 0; + HasProfileData |= EI.second.Hotness != CalleeInfo::HotnessType::Unknown; if (HasProfileData) break; } @@ -3550,10 +3548,8 @@ if (!hasValueId(EI.first.getGUID())) continue; NameVals.push_back(getValueId(EI.first.getGUID())); - assert(EI.second.CallsiteCount > 0 && "Expected at least one callsite"); - NameVals.push_back(EI.second.CallsiteCount); if (HasProfileData) - NameVals.push_back(EI.second.ProfileCount); + NameVals.push_back(static_cast(EI.second.Hotness)); } unsigned FSAbbrev = (HasProfileData ? FSCallsProfileAbbrev : FSCallsAbbrev); Index: lib/LTO/ThinLTOCodeGenerator.cpp =================================================================== --- lib/LTO/ThinLTOCodeGenerator.cpp +++ lib/LTO/ThinLTOCodeGenerator.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/ModuleSummaryAnalysis.h" +#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/BitcodeWriterPass.h" @@ -377,7 +378,8 @@ SmallVector OutputBuffer; { raw_svector_ostream OS(OutputBuffer); - auto Index = buildModuleSummaryIndex(TheModule); + ProfileSummaryInfo PSI(TheModule); + auto Index = buildModuleSummaryIndex(TheModule, nullptr, PSI); WriteBitcodeToFile(&TheModule, OS, true, &Index); } return make_unique(std::move(OutputBuffer)); Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -48,6 +48,10 @@ cl::desc("As we import functions, multiply the " "`import-instr-limit` threshold by this factor " "before processing newly imported functions")); +static cl::opt ImportHotMultiplier( + "import-hot-multiplier", cl::init(3.0), cl::Hidden, cl::value_desc("x"), + cl::ZeroOrMore, cl::desc("Multiply the `import-instr-limit` threshold for " + "hot callsites")); static cl::opt PrintImports("print-imports", cl::init(false), cl::Hidden, cl::desc("Print imported functions")); @@ -268,7 +272,7 @@ /// exported from their source module. static void computeImportForFunction( const FunctionSummary &Summary, const ModuleSummaryIndex &Index, - unsigned Threshold, const GVSummaryMapTy &DefinedGVSummaries, + const unsigned Threshold, const GVSummaryMapTy &DefinedGVSummaries, SmallVectorImpl &Worklist, FunctionImporter::ImportMapTy &ImportList, StringMap *ExportLists = nullptr) { @@ -281,7 +285,12 @@ continue; } - auto *CalleeSummary = selectCallee(GUID, Threshold, Index); + // Fixme: Also lower the threshold for cold callsites. + const auto NewThreshold = + Edge.second.Hotness == CalleeInfo::HotnessType::Hot + ? Threshold * ImportHotMultiplier + : Threshold; + auto *CalleeSummary = selectCallee(GUID, NewThreshold, Index); if (!CalleeSummary) { DEBUG(dbgs() << "ignored! No qualifying callee with summary found.\n"); continue; @@ -297,7 +306,7 @@ } else ResolvedCalleeSummary = cast(CalleeSummary); - assert(ResolvedCalleeSummary->instCount() <= Threshold && + assert(ResolvedCalleeSummary->instCount() <= NewThreshold && "selectCallee() didn't honor the threshold"); auto ExportModulePath = ResolvedCalleeSummary->modulePath(); Index: test/Bitcode/Inputs/thinlto-function-summary-callgraph-profile-summary.ll =================================================================== --- /dev/null +++ test/Bitcode/Inputs/thinlto-function-summary-callgraph-profile-summary.ll @@ -0,0 +1,27 @@ +; ModuleID = 'thinlto-function-summary-callgraph-profile-summary2.ll' +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + + +define void @hot1() #1 { + ret void +} +define void @hot2() #1 { + ret void +} +define void @hot3() #1 { + ret void +} +define void @cold() #1 { + ret void +} +define void @none1() #1 { + ret void +} +define void @none2() #1 { + ret void +} +define void @none3() #1 { + ret void +} + Index: test/Bitcode/summary_version.ll =================================================================== --- test/Bitcode/summary_version.ll +++ test/Bitcode/summary_version.ll @@ -2,7 +2,7 @@ ; RUN: opt -module-summary %s -o - | llvm-bcanalyzer -dump | FileCheck %s ; CHECK: +; CHECK: Index: test/Bitcode/thinlto-alias.ll =================================================================== --- test/Bitcode/thinlto-alias.ll +++ test/Bitcode/thinlto-alias.ll @@ -9,7 +9,7 @@ ; CHECK-NEXT: +; CHECK-NEXT: ; CHECK-NEXT: ; CHECK-NEXT: +; COMBINED-NEXT: ; Followed by the alias and aliasee ; COMBINED-NEXT: +; and hotness type, with value id matching the subsequent value symbol table. +; CHECK-NEXT: ; CHECK-NEXT: ; CHECK-NEXT: +; and hotness type, with value id matching the subsequent value symbol table. +; op6=2 which is hotnessType::None. +; COMBINED-NEXT: ; COMBINED-NEXT: ; COMBINED-NEXT: +; CHECK-NEXT: +; CHECK-LABEL: + +; COMBINED: +; COMBINED_NEXT: + + +; ModuleID = 'thinlto-function-summary-callgraph.ll' +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; This function have high profile count, so entry block is hot. +define void @hot_function(i1 %a, i1 %a2) !prof !20 { +entry: + call void @hot1() + br i1 %a, label %Cold, label %Hot, !prof !41 +Cold: ; 1/1000 goes here + call void @cold() + call void @hot2() + call void @none1() + br label %exit +Hot: ; 999/1000 goes here + call void @hot2() + call void @hot3() + br i1 %a2, label %None1, label %None2, !prof !42 +None1: ; half goes here + call void @none1() + call void @none2() + br label %exit +None2: ; half goes here + call void @none3() + br label %exit +exit: + ret void +} + +declare void @hot1() #1 +declare void @hot2() #1 +declare void @hot3() #1 +declare void @cold() #1 +declare void @none1() #1 +declare void @none2() #1 +declare void @none3() #1 + + +!41 = !{!"branch_weights", i32 1, i32 1000} +!42 = !{!"branch_weights", i32 1, i32 1} + + + +!llvm.module.flags = !{!1} +!20 = !{!"function_entry_count", i64 110} + +!1 = !{i32 1, !"ProfileSummary", !2} +!2 = !{!3, !4, !5, !6, !7, !8, !9, !10} +!3 = !{!"ProfileFormat", !"InstrProf"} +!4 = !{!"TotalCount", i64 10000} +!5 = !{!"MaxCount", i64 10} +!6 = !{!"MaxInternalCount", i64 1} +!7 = !{!"MaxFunctionCount", i64 1000} +!8 = !{!"NumCounts", i64 3} +!9 = !{!"NumFunctions", i64 3} +!10 = !{!"DetailedSummary", !11} +!11 = !{!12, !13, !14} +!12 = !{i32 10000, i64 100, i32 1} +!13 = !{i32 999000, i64 100, i32 1} +!14 = !{i32 999999, i64 1, i32 2} Index: test/Bitcode/thinlto-function-summary-callgraph.ll =================================================================== --- test/Bitcode/thinlto-function-summary-callgraph.ll +++ test/Bitcode/thinlto-function-summary-callgraph.ll @@ -9,7 +9,7 @@ ; CHECK-NEXT: +; CHECK-NEXT: ; CHECK-NEXT: ; CHECK-NEXT: +; COMBINED-NEXT: ; COMBINED-NEXT: ; COMBINED-NEXT: +; CHECK-DAG: ; Function W contains a call to func3 as well as a reference to globalvar: -; CHECK-DAG: +; CHECK-DAG: ; Function X contains call to foo, as well as address reference to foo ; which is in the same instruction as the call: -; CHECK-DAG: +; CHECK-DAG: ; Function Y contains call to func2, and ensures we don't incorrectly add ; a reference to it when reached while earlier analyzing the phi using its ; return value: -; CHECK-DAG: +; CHECK-DAG: ; Function Z contains call to func2, and ensures we don't incorrectly add ; a reference to it when reached while analyzing subsequent use of its return ; value: -; CHECK-DAG: +; CHECK-DAG: ; Variable bar initialization contains address reference to func: ; CHECK-DAG: ; CHECK: