Index: llvm/include/llvm/IR/Instructions.h =================================================================== --- llvm/include/llvm/IR/Instructions.h +++ llvm/include/llvm/IR/Instructions.h @@ -3965,6 +3965,62 @@ return isa(V) && classof(cast(V)); } + // Find the "branch_weights" metadata and indirect-call metadata. + // Return true if either metadat is found. + // Return false if none of the metadtata is found. + // This method sets the reference argument to nullptr if the metadata + // is not found. + static bool getProfMetaData(MDNode *MD, MDNode *&BranchWeightMD, + MDNode *&IndirectCallMD) { + BranchWeightMD = IndirectCallMD = nullptr; + + auto isMDwithName = [](MDNode *MD, const char *Str) { + auto *MDName = dyn_cast(MD->getOperand(0)); + if (!MDName) + return false; + return (MDName->getString().equals(Str)); + }; + + if (isMDwithName(MD, "branch_weights")) { + BranchWeightMD = MD; + return true; + } + if (isMDwithName(MD, "VP")) { + IndirectCallMD = MD; + return true; + } + if (MD->getNumOperands() != 3) + return false; + for (int I = 1; I < 3; I++) { + auto *MDT = cast(MD->getOperand(I)); + if (!MDT) + continue; + if (isMDwithName(MDT, "branch_weights")) + BranchWeightMD = MDT; + else if (isMDwithName(MDT, "VP")) + IndirectCallMD = MDT; + } + return (BranchWeightMD || IndirectCallMD); + } + + // A utility method that return "branch_weights" metadata. Return + // nullptr if the metadata is not found. + static MDNode *getBranchWeightProfData(MDNode *MD) { + MDNode *BranchWeightMD, *IndirectCallMD; + if (!getProfMetaData(MD, BranchWeightMD, IndirectCallMD)) + return nullptr; + return BranchWeightMD; + } + + // A utility method that return indirect-call metadata. Return + // nullptr if the metadata is not found. + static MDNode *getIndirectCallProfData(MDNode *MD) { + MDNode *BranchWeightMD, *IndirectCallMD; + if (!getProfMetaData(MD, BranchWeightMD, IndirectCallMD)) + return nullptr; + return IndirectCallMD; + } + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. Index: llvm/lib/Analysis/BranchProbabilityInfo.cpp =================================================================== --- llvm/lib/Analysis/BranchProbabilityInfo.cpp +++ llvm/lib/Analysis/BranchProbabilityInfo.cpp @@ -403,7 +403,9 @@ SmallVector UnreachableIdxs; SmallVector ReachableIdxs; - extractBranchWeights(*TI, Weights); + if (!extractBranchWeights(*TI, Weights)) + return false; + for (unsigned I = 0, E = Weights.size(); I != E; ++I) { WeightSum += Weights[I]; const LoopBlock SrcLoopBB = getLoopBlock(BB); Index: llvm/lib/IR/Metadata.cpp =================================================================== --- llvm/lib/IR/Metadata.cpp +++ llvm/lib/IR/Metadata.cpp @@ -1502,7 +1502,16 @@ getOpcode() == Instruction::Switch) && "Looking for branch weights on something besides branch"); - return ::extractProfTotalWeight(getMetadata(LLVMContext::MD_prof), TotalVal); + TotalVal = 0; + auto *ProfileData = getMetadata(LLVMContext::MD_prof); + if (!ProfileData) + return false; + if (getOpcode() == Instruction::Invoke) { + ProfileData = InvokeInst::getBranchWeightProfData(ProfileData); + if (!ProfileData) + return false; + } + return ::extractProfTotalWeight(ProfileData, TotalVal); } void GlobalObject::copyMetadata(const GlobalObject *Other, unsigned Offset) { Index: llvm/lib/IR/ProfDataUtils.cpp =================================================================== --- llvm/lib/IR/ProfDataUtils.cpp +++ llvm/lib/IR/ProfDataUtils.cpp @@ -111,17 +111,28 @@ bool extractBranchWeights(const Instruction &I, SmallVectorImpl &Weights) { auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); + if (!ProfileData) + return false; + if (I.getOpcode() == Instruction::Invoke) + ProfileData = InvokeInst::getBranchWeightProfData(ProfileData); return extractBranchWeights(ProfileData, Weights); } bool extractBranchWeights(const Instruction &I, uint64_t &TrueVal, uint64_t &FalseVal) { assert((I.getOpcode() == Instruction::Br || - I.getOpcode() == Instruction::Select) && + I.getOpcode() == Instruction::Select || + I.getOpcode() == Instruction::Invoke) && "Looking for branch weights on something besides branch or select"); SmallVector Weights; auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); + if (!ProfileData) + return false; + + if (I.getOpcode() == Instruction::Invoke) + ProfileData = InvokeInst::getBranchWeightProfData(ProfileData); + if (!extractBranchWeights(ProfileData, Weights)) return false; Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -4475,47 +4475,59 @@ } void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) { - Check(MD->getNumOperands() >= 2, - "!prof annotations should have no less than 2 operands", MD); - - // Check first operand. - Check(MD->getOperand(0) != nullptr, "first operand should not be null", MD); - Check(isa(MD->getOperand(0)), - "expected string with name of the !prof annotation", MD); - MDString *MDS = cast(MD->getOperand(0)); - StringRef ProfName = MDS->getString(); - - // Check consistency of !prof branch_weights metadata. - if (ProfName.equals("branch_weights")) { - if (isa(&I)) { - Check(MD->getNumOperands() == 2 || MD->getNumOperands() == 3, - "Wrong number of InvokeInst branch_weights operands", MD); - } else { - unsigned ExpectedNumOperands = 0; - if (BranchInst *BI = dyn_cast(&I)) - ExpectedNumOperands = BI->getNumSuccessors(); - else if (SwitchInst *SI = dyn_cast(&I)) - ExpectedNumOperands = SI->getNumSuccessors(); - else if (isa(&I)) - ExpectedNumOperands = 1; - else if (IndirectBrInst *IBI = dyn_cast(&I)) - ExpectedNumOperands = IBI->getNumDestinations(); - else if (isa(&I)) - ExpectedNumOperands = 2; - else - CheckFailed("!prof branch_weights are not allowed for this instruction", - MD); - - Check(MD->getNumOperands() == 1 + ExpectedNumOperands, - "Wrong number of operands", MD); - } - for (unsigned i = 1; i < MD->getNumOperands(); ++i) { - auto &MDO = MD->getOperand(i); - Check(MDO, "second operand should not be null", MD); - Check(mdconst::dyn_extract(MDO), - "!prof brunch_weights operand is not a const int"); + auto checkInst = [this](Instruction &I, MDNode *MD) { + Check(MD->getNumOperands() >= 2, + "!prof annotations should have no less than 2 operands", MD); + + // Check first operand. + Check(MD->getOperand(0) != nullptr, "first operand should not be null", MD); + Check(isa(MD->getOperand(0)), + "expected string with name of the !prof annotation", MD); + MDString *MDS = cast(MD->getOperand(0)); + StringRef ProfName = MDS->getString(); + + // Check consistency of !prof branch_weights metadata. + if (ProfName.equals("branch_weights")) { + if (isa(&I)) { + Check(MD->getNumOperands() == 2 || MD->getNumOperands() == 3, + "Wrong number of InvokeInst branch_weights operands", MD); + } else { + unsigned ExpectedNumOperands = 0; + if (BranchInst *BI = dyn_cast(&I)) + ExpectedNumOperands = BI->getNumSuccessors(); + else if (SwitchInst *SI = dyn_cast(&I)) + ExpectedNumOperands = SI->getNumSuccessors(); + else if (isa(&I)) + ExpectedNumOperands = 1; + else if (IndirectBrInst *IBI = dyn_cast(&I)) + ExpectedNumOperands = IBI->getNumDestinations(); + else if (isa(&I)) + ExpectedNumOperands = 2; + else + CheckFailed( + "!prof branch_weights are not allowed for this instruction", MD); + + Check(MD->getNumOperands() == 1 + ExpectedNumOperands, + "Wrong number of operands", MD); + } + for (unsigned i = 1; i < MD->getNumOperands(); ++i) { + auto &MDO = MD->getOperand(i); + Check(MDO, "second operand should not be null", MD); + Check(mdconst::dyn_extract(MDO), + "!prof brunch_weights operand is not a const int"); + } } + }; + + // Check MD for non-invoke instructions or InvokeInst only with branch_weight. + if (!isa(&I) || isa(MD->getOperand(0))) { + checkInst(I, MD); + return; } + + // For an InvokeInst that has both branch_weight and VP profiles. + checkInst(I, cast(MD->getOperand(1))); + checkInst(I, cast(MD->getOperand(2))); } void Verifier::visitCallStackMetadata(MDNode *MD) { Index: llvm/lib/ProfileData/InstrProf.cpp =================================================================== --- llvm/lib/ProfileData/InstrProf.cpp +++ llvm/lib/ProfileData/InstrProf.cpp @@ -25,6 +25,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" @@ -1056,7 +1057,26 @@ if (--MDCount == 0) break; } - Inst.setMetadata(LLVMContext::MD_prof, MDNode::get(Ctx, Vals)); + if (!isa(&Inst)) { + Inst.setMetadata(LLVMContext::MD_prof, MDNode::get(Ctx, Vals)); + return; + } + + // For an invoke instruction, if we have VP counts, we should already have a + // "branch_weights" MD_prof. + MDNode *BranchWeight = Inst.getMetadata(LLVMContext::MD_prof); + assert(BranchWeight != nullptr && + dyn_cast(BranchWeight->getOperand(0)) + ->getString() + .equals("branch_weights") && + "Expect non-null branch_weight metadata"); + SmallVector InvokeVals; + InvokeVals.push_back(nullptr); + InvokeVals.push_back(BranchWeight); + InvokeVals.push_back(MDNode::get(Ctx, Vals)); + MDNode *NewM = MDNode::getDistinct(Ctx, InvokeVals); + NewM->replaceOperandWith(0, NewM); + Inst.setMetadata(LLVMContext::MD_prof, NewM); } bool getValueProfDataFromInst(const Instruction &Inst, @@ -1069,6 +1089,12 @@ if (!MD) return false; + if (isa(&Inst)) { + MD = cast(&Inst)->getIndirectCallProfData(MD); + if (!MD) + return false; + } + unsigned NOps = MD->getNumOperands(); if (NOps < 5) Index: llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp +++ llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp @@ -313,8 +313,13 @@ continue; Changed = true; - // Adjust the MD.prof metadata. First delete the old one. - CB->setMetadata(LLVMContext::MD_prof, nullptr); + // Adjust the MD.prof metadata. First delete the old one. xur + if (isa(CB)) { + MDNode *MD = CB->getMetadata(LLVMContext::MD_prof); + MD = InvokeInst::getBranchWeightProfData(MD); + CB->setMetadata(LLVMContext::MD_prof, MD); + } else + CB->setMetadata(LLVMContext::MD_prof, nullptr); // If all promoted, we don't need the MD.prof metadata. if (TotalCount == 0 || NumPromoted == NumVals) continue; Index: llvm/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/lib/Transforms/Utils/Local.cpp +++ llvm/lib/Transforms/Utils/Local.cpp @@ -2170,17 +2170,25 @@ NewCall->setDebugLoc(II->getDebugLoc()); NewCall->copyMetadata(*II); - // If the invoke had profile metadata, try converting them for CallInst. - uint64_t TotalWeight; - if (NewCall->extractProfTotalWeight(TotalWeight)) { - // Set the total weight if it fits into i32, otherwise reset. - MDBuilder MDB(NewCall->getContext()); - auto NewWeights = uint32_t(TotalWeight) != TotalWeight - ? nullptr - : MDB.createBranchWeights({uint32_t(TotalWeight)}); - NewCall->setMetadata(LLVMContext::MD_prof, NewWeights); + // Move MD_prof data to the new instruction. We can only have one. + // First to keep indirect-call profile metadata. + // Otherwise, if try converting them for total call profile data. + auto *ProfileData = II->getMetadata(LLVMContext::MD_prof); + if (!ProfileData) + return NewCall; + ProfileData = InvokeInst::getIndirectCallProfData(ProfileData); + if (!ProfileData) { + uint64_t TotalWeight; + if (II->extractProfTotalWeight(TotalWeight)) { + // Set the total weight if it fits into i32, otherwise reset. + MDBuilder MDB(NewCall->getContext()); + ProfileData = uint32_t(TotalWeight) != TotalWeight + ? nullptr + : MDB.createBranchWeights({uint32_t(TotalWeight)}); + } } - + // Set the MD_prof metadata. + NewCall->setMetadata(LLVMContext::MD_prof, ProfileData); return NewCall; } Index: llvm/test/Transforms/PGOProfile/Inputs/invoke_icall.proftext =================================================================== --- /dev/null +++ llvm/test/Transforms/PGOProfile/Inputs/invoke_icall.proftext @@ -0,0 +1,30 @@ +# IR level Instrumentation Flag +:ir +_Z3bari +# Func Hash: +784007058953177093 +# Num Counters: +2 +# Counter Values: +10000 +7500 + +_Z3fooi +# Func Hash: +264495437628610820 +# Num Counters: +4 +# Counter Values: +10000 +0 +7500 +0 +# Num Value Kinds: +1 +# ValueKind = IPVK_IndirectCallTarget: +0 +# NumValueSites: +1 +1 +_Z3bari:10000 + Index: llvm/test/Transforms/PGOProfile/invoke_icall.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/PGOProfile/invoke_icall.ll @@ -0,0 +1,187 @@ +; RUN: llvm-profdata merge %S/Inputs/invoke_icall.proftext -o %t.profdata +; RUN: opt < %s -passes=pgo-instr-use -pgo-instrument-entry=false -pgo-test-profile-file=%t.profdata -S | FileCheck %s + +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.std::ios_base::Init" = type { i8 } +%"class.std::basic_ostream" = type { i32 (...)**, %"class.std::basic_ios" } +%"class.std::basic_ios" = type { %"class.std::ios_base", %"class.std::basic_ostream"*, i8, i8, %"class.std::basic_streambuf"*, %"class.std::ctype"*, %"class.std::num_put"*, %"class.std::num_get"* } +%"class.std::ios_base" = type { i32 (...)**, i64, i64, i32, i32, i32, %"struct.std::ios_base::_Callback_list"*, %"struct.std::ios_base::_Words", [8 x %"struct.std::ios_base::_Words"], i32, %"struct.std::ios_base::_Words"*, %"class.std::locale" } +%"struct.std::ios_base::_Callback_list" = type { %"struct.std::ios_base::_Callback_list"*, void (i32, %"class.std::ios_base"*, i32)*, i32, i32 } +%"struct.std::ios_base::_Words" = type { i8*, i64 } +%"class.std::locale" = type { %"class.std::locale::_Impl"* } +%"class.std::locale::_Impl" = type { i32, %"class.std::locale::facet"**, i64, %"class.std::locale::facet"**, i8** } +%"class.std::locale::facet" = type <{ i32 (...)**, i32, [4 x i8] }> +%"class.std::basic_streambuf" = type { i32 (...)**, i8*, i8*, i8*, i8*, i8*, i8*, %"class.std::locale" } +%"class.std::ctype" = type <{ %"class.std::locale::facet.base", [4 x i8], %struct.__locale_struct*, i8, [7 x i8], i32*, i32*, i16*, i8, [256 x i8], [256 x i8], i8, [6 x i8] }> +%"class.std::locale::facet.base" = type <{ i32 (...)**, i32 }> +%struct.__locale_struct = type { [13 x %struct.__locale_data*], i16*, i32*, i32*, [13 x i8*] } +%struct.__locale_data = type opaque +%"class.std::num_put" = type { %"class.std::locale::facet.base", [4 x i8] } +%"class.std::num_get" = type { %"class.std::locale::facet.base", [4 x i8] } + +@_ZStL8__ioinit = internal global %"class.std::ios_base::Init" zeroinitializer, align 1 +@__dso_handle = external hidden global i8 +@_ZTIi = external dso_local constant i8* +@goo = dso_local local_unnamed_addr global i32 (i32)* null, align 8 +@_ZSt4cerr = external dso_local global %"class.std::basic_ostream", align 8 +@.str = private unnamed_addr constant [19 x i8] c"got an exception.\0A\00", align 1 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_test2.cc, i8* null }] + +declare dso_local void @_ZNSt8ios_base4InitC1Ev(%"class.std::ios_base::Init"* nonnull align 1 dereferenceable(1)) unnamed_addr #0 + +declare dso_local void @_ZNSt8ios_base4InitD1Ev(%"class.std::ios_base::Init"* nonnull align 1 dereferenceable(1)) unnamed_addr #1 + +declare dso_local i32 @__cxa_atexit(void (i8*)*, i8*, i8*) local_unnamed_addr #2 + +define dso_local i32 @_Z3bari(i32 %a) #3 !dbg !6 { +entry: + %0 = and i32 %a, 3, !dbg !9 + %tobool.not = icmp eq i32 %0, 0, !dbg !9 + br i1 %tobool.not, label %if.end, label %if.then, !dbg !9 + +if.then: + %exception = call i8* @__cxa_allocate_exception(i64 4) #7, !dbg !10 + %1 = bitcast i8* %exception to i32*, !dbg !10 + store i32 20, i32* %1, align 16, !dbg !10, !tbaa !11 + call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #8, !dbg !10 + unreachable, !dbg !10 + +if.end: + %mul = mul nsw i32 %a, %a, !dbg !15 + ret i32 %mul, !dbg !16 +} + +declare dso_local i8* @__cxa_allocate_exception(i64) local_unnamed_addr + +declare dso_local void @__cxa_throw(i8*, i8*, i8*) local_unnamed_addr + +define dso_local i32 @_Z3fooi(i32 %n) local_unnamed_addr #3 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) !dbg !17 { +entry: + %0 = load i32 (i32)*, i32 (i32)** @goo, align 8, !dbg !18, !tbaa !19 + %call = invoke i32 %0(i32 %n) + to label %cleanup unwind label %lpad, !dbg !18 +; CHECK-LABEL: @_Z3fooi +; CHECK-SAME: !prof ![[BW_ENTRY:[0-9]+]] +; CHECK: %call = invoke +; CHECK: to label +; CHECK-SAME: !prof ![[MD_INVOKE:[0-9]+]] +; CHECK-DAG: ![[BW_ENTRY]] = !{!"function_entry_count", i64 10000} +; CHECK-DAG: ![[BW_INVOKE:[0-9]+]] = !{!"branch_weights", i32 2500, i32 7500} +; CHECK-DAG: ![[MD_INVOKE]] = distinct !{![[MD_INVOKE]], ![[BW_INVOKE]], ![[VP_INVOKE:[0-9]+]]} +; CHECK-DAG: ![[VP_INVOKE]] = !{!"VP", i32 0, i64 10000, i64 3727899762981752933, i64 10000} + +lpad: + %1 = landingpad { i8*, i32 } + cleanup + catch i8* bitcast (i8** @_ZTIi to i8*), !dbg !21 + %2 = extractvalue { i8*, i32 } %1, 1, !dbg !21 + %3 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #7, !dbg !22 + %matches = icmp eq i32 %2, %3, !dbg !22 + br i1 %matches, label %catch, label %ehcleanup, !dbg !22 + +catch: + %4 = extractvalue { i8*, i32 } %1, 0, !dbg !21 + %5 = call i8* @__cxa_begin_catch(i8* %4) #7, !dbg !22 + %call1.i12 = invoke nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l(%"class.std::basic_ostream"* nonnull align 8 dereferenceable(8) @_ZSt4cerr, i8* nonnull getelementptr inbounds ([19 x i8], [19 x i8]* @.str, i64 0, i64 0), i64 18) + to label %invoke.cont2 unwind label %lpad1, !dbg !23 + +invoke.cont2: + call void @__cxa_end_catch() #7, !dbg !27 + br label %cleanup + +lpad1: + %6 = landingpad { i8*, i32 } + cleanup, !dbg !21 + call void @__cxa_end_catch() #7, !dbg !27 + br label %ehcleanup, !dbg !27 + +cleanup: + %retval.0 = phi i32 [ -1, %invoke.cont2 ], [ %call, %entry ], !dbg !28 + ret i32 %retval.0, !dbg !21 + +ehcleanup: + %lpad.val6.merged = phi { i8*, i32 } [ %6, %lpad1 ], [ %1, %lpad ], !dbg !21 + resume { i8*, i32 } %lpad.val6.merged, !dbg !21 +} + +declare dso_local i32 @__gxx_personality_v0(...) + +declare i32 @llvm.eh.typeid.for(i8*) #4 + +declare dso_local i8* @__cxa_begin_catch(i8*) local_unnamed_addr + +declare dso_local void @__cxa_end_catch() local_unnamed_addr + +declare dso_local nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l(%"class.std::basic_ostream"* nonnull align 8 dereferenceable(8), i8*, i64) local_unnamed_addr #0 + +define internal void @_GLOBAL__sub_I_test2.cc() #6 section ".text.startup" !dbg !41 { +entry: + call void @_ZNSt8ios_base4InitC1Ev(%"class.std::ios_base::Init"* nonnull align 1 dereferenceable(1) @_ZStL8__ioinit), !dbg !42 + %0 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%"class.std::ios_base::Init"*)* @_ZNSt8ios_base4InitD1Ev to void (i8*)*), i8* getelementptr inbounds (%"class.std::ios_base::Init", %"class.std::ios_base::Init"* @_ZStL8__ioinit, i64 0, i32 0), i8* nonnull @__dso_handle) #7, !dbg !47 + ret void +} + +attributes #0 = { "frame-pointer"="none" "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 = { nounwind "frame-pointer"="none" "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 = { nofree nounwind } +attributes #3 = { mustprogress noinline uwtable "frame-pointer"="none" "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 #4 = { nofree nosync nounwind readnone } +attributes #5 = { mustprogress norecurse uwtable "frame-pointer"="none" "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 = { uwtable "frame-pointer"="none" "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 #7 = { nounwind } +attributes #8 = { noreturn } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0 (git@github.com:llvm/llvm-project.git 5bbf786ca33ef97de76d4eb5563b68aae61cc508)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test2.cc", directory: "/usr/local/google/home/xur/work/tests/BFI/cases/invoke_with_icall") +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = !{i32 1, !"wchar_size", i32 4} +!4 = !{i32 7, !"uwtable", i32 1} +!5 = !{!"clang version 14.0.0 (git@github.com:llvm/llvm-project.git 5bbf786ca33ef97de76d4eb5563b68aae61cc508)"} +!6 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 6, type: !7, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) +!7 = !DISubroutineType(types: !8) +!8 = !{} +!9 = !DILocation(line: 8, column: 9, scope: !6) +!10 = !DILocation(line: 9, column: 9, scope: !6) +!11 = !{!12, !12, i64 0} +!12 = !{!"int", !13, i64 0} +!13 = !{!"omnipotent char", !14, i64 0} +!14 = !{!"Simple C++ TBAA"} +!15 = !DILocation(line: 10, column: 13, scope: !6) +!16 = !DILocation(line: 10, column: 5, scope: !6) +!17 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 15, type: !7, scopeLine: 16, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) +!18 = !DILocation(line: 20, column: 15, scope: !17) +!19 = !{!20, !20, i64 0} +!20 = !{!"any pointer", !13, i64 0} +!21 = !DILocation(line: 28, column: 1, scope: !17) +!22 = !DILocation(line: 21, column: 5, scope: !17) +!23 = !DILocation(line: 611, column: 2, scope: !24, inlinedAt: !26) +!24 = distinct !DISubprogram(name: "operator<< >", scope: !25, file: !25, line: 606, type: !7, scopeLine: 607, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) +!25 = !DIFile(filename: "lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/ostream", directory: "/usr") +!26 = distinct !DILocation(line: 24, column: 14, scope: !17) +!27 = !DILocation(line: 26, column: 5, scope: !17) +!28 = !DILocation(line: 0, scope: !17) +!29 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 30, type: !7, scopeLine: 31, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) +!30 = !DILocation(line: 33, column: 7, scope: !29) +!31 = !DILocation(line: 34, column: 8, scope: !29) +!32 = !DILocation(line: 0, scope: !29) +!33 = !DILocation(line: 34, column: 21, scope: !29) +!34 = !DILocation(line: 34, column: 3, scope: !29) +!35 = !DILocation(line: 36, column: 3, scope: !29) +!36 = !DILocation(line: 35, column: 12, scope: !29) +!37 = !DILocation(line: 34, column: 31, scope: !29) +!38 = distinct !{!38, !34, !39, !40} +!39 = !DILocation(line: 35, column: 17, scope: !29) +!40 = !{!"llvm.loop.mustprogress"} +!41 = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_test2.cc", scope: !1, file: !1, type: !7, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) +!42 = !DILocation(line: 74, column: 25, scope: !43, inlinedAt: !46) +!43 = !DILexicalBlockFile(scope: !45, file: !44, discriminator: 0) +!44 = !DIFile(filename: "lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/iostream", directory: "/usr") +!45 = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !1, file: !1, type: !7, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) +!46 = distinct !DILocation(line: 0, scope: !41) +!47 = !DILocation(line: 0, scope: !45, inlinedAt: !46)