From 42c63a9f727a2c1b48cee627354b0af54eb24e0b Mon Sep 17 00:00:00 2001 From: gbaraldi Date: Fri, 4 Oct 2024 17:32:27 -0300 Subject: [PATCH 1/2] Improve remarks of the alloc opt pass slightly. The Value printer LLVM uses just prints the kind of instruction so it just shows call. --- src/llvm-alloc-helpers.cpp | 28 ++++++++++++++++++----- src/llvm-alloc-opt.cpp | 46 ++++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/llvm-alloc-helpers.cpp b/src/llvm-alloc-helpers.cpp index 9d2fba832839c..b8421931c559a 100644 --- a/src/llvm-alloc-helpers.cpp +++ b/src/llvm-alloc-helpers.cpp @@ -134,12 +134,16 @@ JL_USED_FUNC void AllocUseInfo::dump(llvm::raw_ostream &OS) OS << " zeroed"; OS << '\n'; OS << "Uses: " << uses.size() << '\n'; - for (auto inst: uses) + for (auto inst: uses) { inst->print(OS); + OS << '\n'; + } if (!preserves.empty()) { OS << "Preserves: " << preserves.size() << '\n'; - for (auto inst: preserves) + for (auto inst: preserves) { inst->print(OS); + OS << '\n'; + } } OS << "MemOps: " << memops.size() << '\n'; for (auto &field: memops) { @@ -263,9 +267,12 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r } LLVM_DEBUG(dbgs() << "Unknown call, marking escape\n"); REMARK([&]() { + std::string str; + llvm::raw_string_ostream rso(str); + inst->print(rso); return OptimizationRemarkMissed(DEBUG_TYPE, "UnknownCall", inst) - << "Unknown call, marking escape (" << ore::NV("Call", inst) << ")"; + << "Unknown call, marking escape (" << ore::NV("Call", StringRef(str)) << ")"; }); required.use_info.escaped = true; return false; @@ -279,9 +286,12 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r if (use->getOperandNo() != StoreInst::getPointerOperandIndex()) { LLVM_DEBUG(dbgs() << "Object address is stored somewhere, marking escape\n"); REMARK([&]() { + std::string str; + llvm::raw_string_ostream rso(str); + inst->print(rso); return OptimizationRemarkMissed(DEBUG_TYPE, "StoreObjAddr", inst) - << "Object address is stored somewhere, marking escape (" << ore::NV("Store", inst) << ")"; + << "Object address is stored somewhere, marking escape (" << ore::NV("Store", StringRef(str)) << ")"; }); required.use_info.escaped = true; return false; @@ -305,9 +315,12 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r if (use->getOperandNo() != isa(inst) ? AtomicCmpXchgInst::getPointerOperandIndex() : AtomicRMWInst::getPointerOperandIndex()) { LLVM_DEBUG(dbgs() << "Object address is cmpxchg/rmw-ed somewhere, marking escape\n"); REMARK([&]() { + std::string str; + llvm::raw_string_ostream rso(str); + inst->print(rso); return OptimizationRemarkMissed(DEBUG_TYPE, "StoreObjAddr", inst) - << "Object address is cmpxchg/rmw-ed somewhere, marking escape (" << ore::NV("Store", inst) << ")"; + << "Object address is cmpxchg/rmw-ed somewhere, marking escape (" << ore::NV("Store", StringRef(str)) << ")"; }); required.use_info.escaped = true; return false; @@ -358,9 +371,12 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r } LLVM_DEBUG(dbgs() << "Unknown instruction, marking escape\n"); REMARK([&]() { + std::string str; + llvm::raw_string_ostream rso(str); + inst->print(rso); return OptimizationRemarkMissed(DEBUG_TYPE, "UnknownInst", inst) - << "Unknown instruction, marking escape (" << ore::NV("Inst", inst) << ")"; + << "Unknown instruction, marking escape (" << ore::NV("Inst", StringRef(str)) << ")"; }); required.use_info.escaped = true; return false; diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index 188955fd50972..85d029892a86b 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -220,12 +220,16 @@ void Optimizer::optimizeAll() while (!worklist.empty()) { auto item = worklist.pop_back_val(); auto orig = item.first; + orig->print(dbgs()); size_t sz = item.second; checkInst(orig); if (use_info.escaped) { REMARK([&]() { + std::string str; + llvm::raw_string_ostream rso(str); + orig->print(rso); return OptimizationRemarkMissed(DEBUG_TYPE, "Escaped", orig) - << "GC allocation escaped " << ore::NV("GC Allocation", orig); + << "GC allocation escaped " << ore::NV("GC Allocation", StringRef(str)); }); if (use_info.hastypeof) optimizeTag(orig); @@ -233,8 +237,11 @@ void Optimizer::optimizeAll() } if (use_info.haserror || use_info.returned) { REMARK([&]() { + std::string str; + llvm::raw_string_ostream rso(str); + orig->print(rso); return OptimizationRemarkMissed(DEBUG_TYPE, "Escaped", orig) - << "GC allocation has error or was returned " << ore::NV("GC Allocation", orig); + << "GC allocation has error or was returned " << ore::NV("GC Allocation", StringRef(str)); }); if (use_info.hastypeof) optimizeTag(orig); @@ -243,8 +250,11 @@ void Optimizer::optimizeAll() if (!use_info.addrescaped && !use_info.hasload && (!use_info.haspreserve || !use_info.refstore)) { REMARK([&]() { + std::string str; + llvm::raw_string_ostream rso(str); + orig->print(rso); return OptimizationRemark(DEBUG_TYPE, "Dead Allocation", orig) - << "GC allocation removed " << ore::NV("GC Allocation", orig); + << "GC allocation removed " << ore::NV("GC Allocation", StringRef(str)); }); // No one took the address, no one reads anything and there's no meaningful // preserve of fields (either no preserve/ccall or no object reference fields) @@ -270,8 +280,11 @@ void Optimizer::optimizeAll() } if (has_refaggr) { REMARK([&]() { + std::string str; + llvm::raw_string_ostream rso(str); + orig->print(rso); return OptimizationRemarkMissed(DEBUG_TYPE, "Escaped", orig) - << "GC allocation has unusual object reference, unable to move to stack " << ore::NV("GC Allocation", orig); + << "GC allocation has unusual object reference, unable to move to stack " << ore::NV("GC Allocation", StringRef(str)); }); if (use_info.hastypeof) optimizeTag(orig); @@ -279,8 +292,11 @@ void Optimizer::optimizeAll() } if (!use_info.hasunknownmem && !use_info.addrescaped) { REMARK([&](){ + std::string str; + llvm::raw_string_ostream rso(str); + orig->print(rso); return OptimizationRemark(DEBUG_TYPE, "Stack Split Allocation", orig) - << "GC allocation split on stack " << ore::NV("GC Allocation", orig); + << "GC allocation split on stack " << ore::NV("GC Allocation", StringRef(str)); }); // No one actually care about the memory layout of this object, split it. splitOnStack(orig); @@ -292,16 +308,22 @@ void Optimizer::optimizeAll() // This later causes the GC rooting pass, to miss-characterize the float as a pointer to a GC value if (has_unboxed && has_ref) { REMARK([&]() { + std::string str; + llvm::raw_string_ostream rso(str); + orig->print(rso); return OptimizationRemarkMissed(DEBUG_TYPE, "Escaped", orig) - << "GC allocation could not be split since it contains both boxed and unboxed values, unable to move to stack " << ore::NV("GC Allocation", orig); + << "GC allocation could not be split since it contains both boxed and unboxed values, unable to move to stack " << ore::NV("GC Allocation", StringRef(str)); }); if (use_info.hastypeof) optimizeTag(orig); continue; } REMARK([&](){ + std::string str; + llvm::raw_string_ostream rso(str); + orig->print(rso); return OptimizationRemark(DEBUG_TYPE, "Stack Move Allocation", orig) - << "GC allocation moved to stack " << ore::NV("GC Allocation", orig); + << "GC allocation moved to stack " << ore::NV("GC Allocation", StringRef(str)); }); // The object has no fields with mix reference access moveToStack(orig, sz, has_ref, use_info.allockind); @@ -380,7 +402,10 @@ void Optimizer::checkInst(CallInst *I) std::string suse_info; llvm::raw_string_ostream osuse_info(suse_info); use_info.dump(osuse_info); - return OptimizationRemarkAnalysis(DEBUG_TYPE, "EscapeAnalysis", I) << "escape analysis for " << ore::NV("GC Allocation", I) << "\n" << ore::NV("UseInfo", osuse_info.str()); + std::string str; + llvm::raw_string_ostream rso(str); + I->print(rso); + return OptimizationRemarkAnalysis(DEBUG_TYPE, "EscapeAnalysis", I) << "escape analysis for " << ore::NV("GC Allocation", StringRef(str)) << "\n" << ore::NV("UseInfo", osuse_info.str()); }); } @@ -905,8 +930,11 @@ void Optimizer::optimizeTag(CallInst *orig_inst) if (pass.typeof_func == callee) { ++RemovedTypeofs; REMARK([&](){ + std::string str; + llvm::raw_string_ostream rso(str); + orig_inst->print(rso); return OptimizationRemark(DEBUG_TYPE, "typeof", call) - << "removed typeof call for GC allocation " << ore::NV("Alloc", orig_inst); + << "removed typeof call for GC allocation " << ore::NV("Alloc", StringRef(str)); }); call->replaceAllUsesWith(tag); // Push to the removed instructions to trigger `finalize` to From ff942d4c92727de95d6fdf94213ab266a705283e Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Mon, 14 Oct 2024 12:22:06 -0300 Subject: [PATCH 2/2] Update llvm-alloc-opt.cpp --- src/llvm-alloc-opt.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index 85d029892a86b..0ec88c9d56356 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -220,7 +220,6 @@ void Optimizer::optimizeAll() while (!worklist.empty()) { auto item = worklist.pop_back_val(); auto orig = item.first; - orig->print(dbgs()); size_t sz = item.second; checkInst(orig); if (use_info.escaped) {