Sync https://gitee.com/openeuler/llvm-project/pulls/89 and build.sh in https://gitee.com/openeuler/llvm-project/pulls/92
1749 lines
67 KiB
Diff
1749 lines
67 KiB
Diff
From 35db41f1fc006aa06fb012ec942d17c93bf0f8d5 Mon Sep 17 00:00:00 2001
|
|
From: Amir Ashouri <amirh.ashouri@huawei.com>
|
|
Date: Thu, 22 Aug 2024 23:58:33 -0400
|
|
Subject: [PATCH] [ACPO] Introduce MLInliner using ACPO infrastructure
|
|
|
|
This change adds ML model to the inliner for performance optimization.
|
|
---
|
|
.../llvm/Analysis/ACPOCollectFeatures.h | 3 +
|
|
llvm/include/llvm/Analysis/ACPOFIModel.h | 144 +++++++++
|
|
llvm/include/llvm/Analysis/ACPOMLInterface.h | 4 +-
|
|
llvm/include/llvm/Analysis/ACPOModel.h | 2 +
|
|
llvm/include/llvm/Analysis/ACPOModelRunner.h | 2 +
|
|
llvm/include/llvm/Analysis/AOTModelRunner.h | 2 +
|
|
llvm/include/llvm/Analysis/CallHeight.h | 2 +
|
|
llvm/include/llvm/Analysis/DumpCallsite.h | 2 +
|
|
llvm/include/llvm/Analysis/DumpFeature.h | 2 +
|
|
llvm/include/llvm/Analysis/FIModelRunner.h | 277 ++++++++++++++++++
|
|
llvm/include/llvm/Analysis/InlineAdvisor.h | 30 ++
|
|
.../llvm/Analysis/InlineModelFeatureMaps.h | 30 ++
|
|
llvm/include/llvm/Analysis/MLInlineAdvisor.h | 5 +-
|
|
llvm/include/llvm/InitializePasses.h | 6 +
|
|
llvm/include/llvm/Transforms/IPO.h | 4 +
|
|
llvm/include/llvm/Transforms/IPO/Inliner.h | 9 +
|
|
llvm/lib/Analysis/ACPOCollectFeatures.cpp | 2 +
|
|
llvm/lib/Analysis/ACPOFIModel.cpp | 243 +++++++++++++++
|
|
llvm/lib/Analysis/ACPOMLInterface.cpp | 2 +
|
|
llvm/lib/Analysis/ACPOModel.cpp | 2 +
|
|
llvm/lib/Analysis/CallHeight.cpp | 3 +
|
|
llvm/lib/Analysis/DumpCallsite.cpp | 2 +
|
|
llvm/lib/Analysis/DumpFeature.cpp | 3 +
|
|
llvm/lib/Analysis/InlineAdvisor.cpp | 115 ++++++++
|
|
llvm/lib/Analysis/MLInlineAdvisor.cpp | 5 +
|
|
llvm/lib/IR/AsmWriter.cpp | 35 ++-
|
|
llvm/lib/Transforms/IPO/Inliner.cpp | 219 +++++++++++++-
|
|
llvm/tools/opt/opt.cpp | 3 +
|
|
28 files changed, 1151 insertions(+), 7 deletions(-)
|
|
create mode 100644 llvm/include/llvm/Analysis/ACPOFIModel.h
|
|
create mode 100644 llvm/include/llvm/Analysis/FIModelRunner.h
|
|
create mode 100644 llvm/lib/Analysis/ACPOFIModel.cpp
|
|
|
|
diff --git a/llvm/include/llvm/Analysis/ACPOCollectFeatures.h b/llvm/include/llvm/Analysis/ACPOCollectFeatures.h
|
|
index ec62b559542d..8b266b3bc756 100644
|
|
--- a/llvm/include/llvm/Analysis/ACPOCollectFeatures.h
|
|
+++ b/llvm/include/llvm/Analysis/ACPOCollectFeatures.h
|
|
@@ -10,6 +10,8 @@
|
|
// collected on a given ACPOModel class from all available features.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
+
|
|
+#if defined(ENABLE_ACPO)
|
|
#ifndef LLVM_ANALYSIS_ACPOCOLLECTFEATURES_H
|
|
#define LLVM_ANALYSIS_ACPOCOLLECTFEATURES_H
|
|
#include "llvm/Analysis/InlineAdvisor.h"
|
|
@@ -294,3 +296,4 @@ operator++(ACPOCollectFeatures::FeatureIndex &, int);
|
|
|
|
} // namespace llvm
|
|
#endif // LLVM_ANALYSIS_ACPOCOLLECTFEATURES_H
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/ACPOFIModel.h b/llvm/include/llvm/Analysis/ACPOFIModel.h
|
|
new file mode 100644
|
|
index 000000000000..8753dd3d7c63
|
|
--- /dev/null
|
|
+++ b/llvm/include/llvm/Analysis/ACPOFIModel.h
|
|
@@ -0,0 +1,144 @@
|
|
+//===- ACPOFIModel.h - AI-Enabled Continuous Program Optimization ---------===//
|
|
+//
|
|
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
+// See https://llvm.org/LICENSE.txt for license information.
|
|
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
+//
|
|
+//===----------------------------------------------------------------------===//
|
|
+
|
|
+#if defined(ENABLE_ACPO)
|
|
+#ifndef LLVM_ANALYSIS_ACPOFIMODEL_H
|
|
+#define LLVM_ANALYSIS_ACPOFIMODEL_H
|
|
+
|
|
+#include "llvm/Analysis/ACPOModel.h"
|
|
+#include "llvm/Analysis/DumpFeature.h"
|
|
+#include "llvm/Analysis/FunctionPropertiesAnalysis.h"
|
|
+#include "llvm/Analysis/InlineAdvisor.h"
|
|
+#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h"
|
|
+#include "llvm/Analysis/LoopInfo.h"
|
|
+#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
+#include "llvm/Analysis/TargetTransformInfo.h"
|
|
+
|
|
+#include <map>
|
|
+
|
|
+namespace llvm {
|
|
+
|
|
+//class ACPOmodel;
|
|
+
|
|
+class ACPOFIModel : public ACPOModel {
|
|
+public:
|
|
+ ACPOFIModel(CallBase *CB, InlineAdvisor *IA, OptimizationRemarkEmitter *ORE,
|
|
+ bool OnlyMandatory, bool UseML = true);
|
|
+
|
|
+ ~ACPOFIModel();
|
|
+
|
|
+ void setMLCustomFeatures(
|
|
+ std::vector<std::pair<std::string, std::string>> FeatureValues);
|
|
+
|
|
+ void sendCustomFeatures() override;
|
|
+
|
|
+ InlineAdvisor *getNotACPOAdvisor();
|
|
+
|
|
+ // Recorder's to micmic the behavior for default InlineAdvice.
|
|
+ // If the model is turned off or was decided to fall back to
|
|
+ // default inline advisor then we need to make sure the advice returned
|
|
+ // is properly recorded. Or else there would be an error.
|
|
+ void recordUnattemptedInlining();
|
|
+
|
|
+ void recordInlining();
|
|
+
|
|
+ void recordUnsuccessfulInlining(InlineResult &IR);
|
|
+
|
|
+ void recordInliningWithCalleeDeleted();
|
|
+
|
|
+ // Interface for IRToPerf Cache system.
|
|
+ struct FunctionFeaturesCache {
|
|
+ using FunctionSizeMap = DenseMap<const Function *, size_t>;
|
|
+ using FunctionFloatMap = DenseMap<const Function *, float>;
|
|
+
|
|
+ std::array<FunctionSizeMap,
|
|
+ static_cast<size_t>(
|
|
+ ACPOFIExtendedFeatures::NamedFeatureIndex::NumNamedFeatures)>
|
|
+ NamedFeatures;
|
|
+ std::array<FunctionFloatMap,
|
|
+ static_cast<size_t>(
|
|
+ ACPOFIExtendedFeatures::NamedFloatFeatureIndex::
|
|
+ NumNamedFloatFeatures)>
|
|
+ NamedFloatFeatures;
|
|
+
|
|
+ FunctionSizeMap &operator[](ACPOFIExtendedFeatures::NamedFeatureIndex Pos) {
|
|
+ return NamedFeatures[static_cast<size_t>(Pos)];
|
|
+ }
|
|
+ FunctionFloatMap &
|
|
+ operator[](ACPOFIExtendedFeatures::NamedFloatFeatureIndex Pos) {
|
|
+ return NamedFloatFeatures[static_cast<size_t>(Pos)];
|
|
+ }
|
|
+ };
|
|
+
|
|
+ struct FunctionAnalysisMap {
|
|
+ DenseMap<const Function *, const DominatorTree *> DomCache;
|
|
+ DenseMap<const Function *, const LoopInfo *> LICache;
|
|
+ DenseMap<const Function *, const TargetTransformInfo *> TTICache;
|
|
+ };
|
|
+
|
|
+ // Invalidation mechanisms
|
|
+ static void invalidateCache(CallBase *CB);
|
|
+
|
|
+ static void invalidateCache(const Function *F);
|
|
+
|
|
+ static void clearCache();
|
|
+
|
|
+ // Getters/setters for the cache system.
|
|
+ static std::optional<size_t>
|
|
+ getCachedSize(const Function *F,
|
|
+ ACPOFIExtendedFeatures::NamedFeatureIndex idx);
|
|
+
|
|
+ static std::optional<float>
|
|
+ getCachedFloat(const Function *F,
|
|
+ ACPOFIExtendedFeatures::NamedFloatFeatureIndex idx);
|
|
+
|
|
+ static void insertSizeCache(const Function *F,
|
|
+ ACPOFIExtendedFeatures::NamedFeatureIndex idx,
|
|
+ size_t val);
|
|
+
|
|
+ static void
|
|
+ insertFloatCache(const Function *F,
|
|
+ ACPOFIExtendedFeatures::NamedFloatFeatureIndex idx,
|
|
+ float val);
|
|
+
|
|
+ static const DominatorTree *getDomCachedAnalysis(const Function *F);
|
|
+
|
|
+ static const LoopInfo *getLICachedAnalysis(const Function *F);
|
|
+
|
|
+ static const TargetTransformInfo *getTTICachedAnalysis(const Function *F);
|
|
+
|
|
+ static void insertAnalysisCache(const Function *F, const DominatorTree *Tree);
|
|
+
|
|
+ static void insertAnalysisCache(const Function *F, const LoopInfo *LI);
|
|
+
|
|
+ static void insertAnalysisCache(const Function *F,
|
|
+ const TargetTransformInfo *TTI);
|
|
+
|
|
+protected:
|
|
+ // Interface to run the MLInference/default advisor and get advice from the
|
|
+ // model/default advisor
|
|
+ virtual std::unique_ptr<ACPOAdvice> getAdviceML() override;
|
|
+
|
|
+ virtual std::unique_ptr<ACPOAdvice> getAdviceNoML() override;
|
|
+
|
|
+private:
|
|
+ static FunctionFeaturesCache FeatureCache;
|
|
+ static FunctionAnalysisMap FunctionAnalysisCache;
|
|
+ CallBase *CurrentCB = nullptr;
|
|
+ InlineAdvisor *NotACPOAdvisor = nullptr;
|
|
+ bool ShouldInline = false;
|
|
+ bool OnlyMandatory = false;
|
|
+ std::unique_ptr<InlineAdvice> NotACPOAdvice = nullptr;
|
|
+ std::vector<std::pair<std::string, std::string>> CustomFeatureValues;
|
|
+};
|
|
+
|
|
+} // end namespace llvm
|
|
+
|
|
+#endif // LLVM_ANALYSIS_ACPOFIMODEL_H
|
|
+
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/ACPOMLInterface.h b/llvm/include/llvm/Analysis/ACPOMLInterface.h
|
|
index 996f27ee32ba..fbc8a46b3d9a 100644
|
|
--- a/llvm/include/llvm/Analysis/ACPOMLInterface.h
|
|
+++ b/llvm/include/llvm/Analysis/ACPOMLInterface.h
|
|
@@ -4,10 +4,9 @@
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
-// Copyright (C) 2021-2022. Huawei Technologies Co., Ltd. All rights reserved.
|
|
-//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#ifndef LLVM_ANALYSIS_ACPOML_INTERFACE_H
|
|
#define LLVM_ANALYSIS_ACPOML_INTERFACE_H
|
|
|
|
@@ -480,3 +479,4 @@ std::shared_ptr<ACPOMLInterface> createPersistentCompiledMLIF();
|
|
} // namespace llvm
|
|
|
|
#endif // LLVM_ANALYSIS_ACPOML_INTERFACE_H
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/ACPOModel.h b/llvm/include/llvm/Analysis/ACPOModel.h
|
|
index 34dbc0fdb8bf..d61ac00efaaf 100644
|
|
--- a/llvm/include/llvm/Analysis/ACPOModel.h
|
|
+++ b/llvm/include/llvm/Analysis/ACPOModel.h
|
|
@@ -6,6 +6,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#ifndef LLVM_ANALYSIS_ACPOMODEL_H
|
|
#define LLVM_ANALYSIS_ACPOMODEL_H
|
|
|
|
@@ -120,3 +121,4 @@ private:
|
|
} // namespace llvm
|
|
|
|
#endif // LLVM_ANALYSIS_ACPOMODEL_H
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/ACPOModelRunner.h b/llvm/include/llvm/Analysis/ACPOModelRunner.h
|
|
index 819e17f71103..044f3af15bbe 100644
|
|
--- a/llvm/include/llvm/Analysis/ACPOModelRunner.h
|
|
+++ b/llvm/include/llvm/Analysis/ACPOModelRunner.h
|
|
@@ -6,6 +6,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#ifndef LLVM_ANALYSIS_ACPOMODEL_H
|
|
#define LLVM_ANALYSIS_ACPOMODEL_H
|
|
|
|
@@ -37,3 +38,4 @@ protected:
|
|
} // namespace llvm
|
|
|
|
#endif // LLVM_ANALYSIS_ACPOMODEL_H
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/AOTModelRunner.h b/llvm/include/llvm/Analysis/AOTModelRunner.h
|
|
index abc6258c4f09..fe19a33a5a08 100644
|
|
--- a/llvm/include/llvm/Analysis/AOTModelRunner.h
|
|
+++ b/llvm/include/llvm/Analysis/AOTModelRunner.h
|
|
@@ -6,6 +6,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#ifndef LLVM_ANALYSIS_AOTMODEL_H
|
|
#define LLVM_ANALYSIS_AOTMODEL_H
|
|
|
|
@@ -201,3 +202,4 @@ private:
|
|
} // namespace llvm
|
|
|
|
#endif // LLVM_ANALYSIS_AOTMODEL_H
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/CallHeight.h b/llvm/include/llvm/Analysis/CallHeight.h
|
|
index c1251081f525..84e94075ea39 100644
|
|
--- a/llvm/include/llvm/Analysis/CallHeight.h
|
|
+++ b/llvm/include/llvm/Analysis/CallHeight.h
|
|
@@ -10,6 +10,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#ifndef LLVM_ANALYSIS_CALLHEIGHT
|
|
#define LLVM_ANALYSIS_CALLHEIGHT
|
|
|
|
@@ -70,3 +71,4 @@ Pass *createCallHeightAnalysisWrapper();
|
|
} // namespace llvm
|
|
|
|
#endif
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/DumpCallsite.h b/llvm/include/llvm/Analysis/DumpCallsite.h
|
|
index 9f80fe1cb985..02238521580b 100644
|
|
--- a/llvm/include/llvm/Analysis/DumpCallsite.h
|
|
+++ b/llvm/include/llvm/Analysis/DumpCallsite.h
|
|
@@ -10,6 +10,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#ifndef LLVM_ANALYSIS_DUMPCALLSITE
|
|
#define LLVM_ANALYSIS_DUMPCALLSITE
|
|
|
|
@@ -25,3 +26,4 @@ public:
|
|
} // namespace llvm
|
|
|
|
#endif
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/DumpFeature.h b/llvm/include/llvm/Analysis/DumpFeature.h
|
|
index 226e06cf5600..67ca36b106cb 100644
|
|
--- a/llvm/include/llvm/Analysis/DumpFeature.h
|
|
+++ b/llvm/include/llvm/Analysis/DumpFeature.h
|
|
@@ -10,6 +10,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#ifndef LLVM_ANALYSIS_DUMPFEATURE
|
|
#define LLVM_ANALYSIS_DUMPFEATURE
|
|
|
|
@@ -192,3 +193,4 @@ operator++(ACPOFIExtendedFeatures::NamedFloatFeatureIndex &n, int);
|
|
} // namespace llvm
|
|
|
|
#endif
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/FIModelRunner.h b/llvm/include/llvm/Analysis/FIModelRunner.h
|
|
new file mode 100644
|
|
index 000000000000..3685220aa074
|
|
--- /dev/null
|
|
+++ b/llvm/include/llvm/Analysis/FIModelRunner.h
|
|
@@ -0,0 +1,277 @@
|
|
+//===- FIModelRunner.h - AI-Enabled Continuous Program Optimization -------===//
|
|
+//
|
|
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
+// See https://llvm.org/LICENSE.txt for license information.
|
|
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
+//
|
|
+//===----------------------------------------------------------------------===//
|
|
+
|
|
+#if defined(ENABLE_ACPO)
|
|
+#ifdef LLVM_HAVE_TF_AOT_FICOMPILEDMODEL
|
|
+
|
|
+#ifndef LLVM_ANALYSIS_FIMODELRUNNER_H
|
|
+#define LLVM_ANALYSIS_FIMODELRUNNER_H
|
|
+
|
|
+#include "llvm/Analysis/AOTModelRunner.h"
|
|
+#include "llvm/Analysis/FICompiledModel.h"
|
|
+
|
|
+namespace llvm {
|
|
+
|
|
+class FIModelRunner : public AOTModelRunner<FICompiledModel> {
|
|
+ std::vector<float> Means = {
|
|
+ 0.40009943697174110699421589742996729910373687744141,
|
|
+ 0.0,
|
|
+ 47.2218788212687599070704891346395015716552734375,
|
|
+ 0.0,
|
|
+ 0.07675459224122871404460966004990041255950927734375,
|
|
+ 5816.8243862454482950852252542972564697265625,
|
|
+ 1333.68016232413765465025790035724639892578125,
|
|
+ 321.9700210967629345759632997214794158935546875,
|
|
+ 0.94076781467098458122677584469784051179885864257812,
|
|
+ 0.0,
|
|
+ 0.0,
|
|
+ 24.57427538666200916850357316434383392333984375,
|
|
+ 0.72785175828753412297089653293369337916374206542969,
|
|
+ 22.362582136282401990001744707114994525909423828125,
|
|
+ 2.3236404681600126842511144786840304732322692871094,
|
|
+ 219.476437468925951179699040949344635009765625,
|
|
+ 123.872156304169635632206336595118045806884765625,
|
|
+ 759.6211988873809559663641266524791717529296875,
|
|
+ 3.5118047810371009198604497214546427130699157714844,
|
|
+ 0.0,
|
|
+ 14.689125089022963877027905255090445280075073242188,
|
|
+ 0.2720138674263292699606608948670327663421630859375,
|
|
+ 97.33707789677367827607668004930019378662109375,
|
|
+ 5.4576519437240493815011177503038197755813598632812,
|
|
+ 222416123463299168.0,
|
|
+ 697004967939498496.0,
|
|
+ 6.2712796684314486839184610289521515369415283203125,
|
|
+ 1.4856427516360068974421437815180979669094085693359,
|
|
+ 0.0041427067953076499376430241738944459939375519752502,
|
|
+ 0.72785175828753412297089653293369337916374206542969,
|
|
+ 552.7808652140716958456323482096195220947265625,
|
|
+ 62.5524652090595196796130039729177951812744140625,
|
|
+ 385.68509386043888298445381224155426025390625,
|
|
+ 92.9494483935554143272383953444659709930419921875,
|
|
+ 24.2728066757145342080548289231956005096435546875,
|
|
+ 0.90531987798814816947867711860453709959983825683594,
|
|
+ 0.0,
|
|
+ 0.0,
|
|
+ 2.9322753597871509256833633116912096738815307617188,
|
|
+ 0.49584111584407208894731411419343203306198120117188,
|
|
+ 7.9963853317029256473347231803927570581436157226562,
|
|
+ 1.4571144465795025091381376114441081881523132324219,
|
|
+ 15.557169540036818844441768305841833353042602539062,
|
|
+ 9.6481678066085265754736610688269138336181640625,
|
|
+ 50.98738225453177363988288561813533306121826171875,
|
|
+ 1.3425469302194332765765238946187309920787811279297,
|
|
+ 0.0,
|
|
+ 839.271140434566405019722878932952880859375,
|
|
+ 0.16440693908813608370422798543586395680904388427734,
|
|
+ 2.8829196844891762374629706755513325333595275878906,
|
|
+ 132.0555906421747067724936641752719879150390625,
|
|
+ 92791372484119440.0,
|
|
+ 166968642875823456.0,
|
|
+ 5.5557876796248262252220229129306972026824951171875,
|
|
+ 1.1750766644405326033506753446999937295913696289062,
|
|
+ 0.0042161570432282073628282859090177225880324840545654,
|
|
+ 0.49584111584407208894731411419343203306198120117188,
|
|
+ 41.15953665944181949498670292086899280548095703125,
|
|
+ 5.14903426051142787400749512016773223876953125,
|
|
+ 2.0527687821658449074391228350577875971794128417969,
|
|
+ 0.52614251736787642776960183255141600966453552246094,
|
|
+ 0.74523979091361081117383946548216044902801513671875,
|
|
+ 222.345100041656024814074044115841388702392578125,
|
|
+ 7.4997648449992606600744693423621356487274169921875,
|
|
+ 0.0,
|
|
+ 78.5584998454695693226312869228422641754150390625,
|
|
+ 0.0,
|
|
+ 10.409640011287439875786731136031448841094970703125,
|
|
+ 8.4653112780338357623577394406311213970184326171875,
|
|
+ 1.3630927585697201198655648113344796001911163330078,
|
|
+ 566.7381985783200661899172700941562652587890625,
|
|
+ 0.0,
|
|
+ 1.2066945269353257508271326514659449458122253417969,
|
|
+ 55.41075531786237462483768467791378498077392578125,
|
|
+ 0.51243634018194272883306439325679093599319458007812,
|
|
+ 1.1147556403606606600931172579294070601463317871094,
|
|
+ -31.471868743197301654390685143880546092987060546875,
|
|
+ 0.0,
|
|
+ 0.030368588666872708276001091576290491502732038497925,
|
|
+ 0.58478345583789081985059965518303215503692626953125,
|
|
+ 0.00034937314395517275094141251834400918596656993031502,
|
|
+ -0.23764092503258577027125397762574721127748489379883,
|
|
+ -62.20223330063559075142620713450014591217041015625,
|
|
+ 5.8952014942420616350204909394960850477218627929688,
|
|
+ 3339.09353794057960840291343629360198974609375,
|
|
+ 0.71960117711874660439974604742019437253475189208984,
|
|
+ -49.2720273048549444183663581497967243194580078125,
|
|
+ 27818.32155766672440222464501857757568359375,
|
|
+ 91.64824843118020680776680819690227508544921875,
|
|
+ 106.3296335613216996307528461329638957977294921875,
|
|
+ 469.83727273948858282892615534365177154541015625,
|
|
+ 0.30689743210739195422576131022651679813861846923828,
|
|
+ 1071.964175815315911677316762506961822509765625,
|
|
+ 1363.988766309679022015188820660114288330078125,
|
|
+ 14.079536139964256236112305487040430307388305664062,
|
|
+ 63165365211952664.0,
|
|
+ 0.38502264206721403816402471420587971806526184082031,
|
|
+ 0.015573979763232508391479491649533883901312947273254,
|
|
+ 0.13859363872129429329227434664062457159161567687988,
|
|
+ 0.0};
|
|
+
|
|
+ std::vector<float> Scales = {
|
|
+ 0.48991823553184549178141082848014775663614273071289,
|
|
+ 1.0,
|
|
+ 19.2517211876445770712962257675826549530029296875,
|
|
+ 1.0,
|
|
+ 0.26620166192402217042456413764739409089088439941406,
|
|
+ 13580.447773648038491955958306789398193359375,
|
|
+ 3192.7079136089387247920967638492584228515625,
|
|
+ 633.0586155859824657454737462103366851806640625,
|
|
+ 0.23605875020885080939336830851971171796321868896484,
|
|
+ 1.0,
|
|
+ 1.0,
|
|
+ 101.565906032925312274528550915420055389404296875,
|
|
+ 0.44506581113952026207414292002795264124870300292969,
|
|
+ 25.4451961539476627649492002092301845550537109375,
|
|
+ 1.8819488669919737233726664271671324968338012695312,
|
|
+ 399.4446922340151786556816659867763519287109375,
|
|
+ 253.61174866766344848656444810330867767333984375,
|
|
+ 1934.51814232197148157865740358829498291015625,
|
|
+ 9.2671206485376131922748754732310771942138671875,
|
|
+ 1.0,
|
|
+ 101.7363052307218964642743230797350406646728515625,
|
|
+ 0.44499699252253444026194983962341211736202239990234,
|
|
+ 241.819662633324895750774885527789592742919921875,
|
|
+ 41.0624051346520815286567085422575473785400390625,
|
|
+ 1810657384453411584.0,
|
|
+ 2590019375355715584.0,
|
|
+ 18.6007475145233769353581010363996028900146484375,
|
|
+ 0.30589376767499054654564361044322140514850616455078,
|
|
+ 0.021661308027730186848147653222440567333251237869263,
|
|
+ 0.44506581113952026207414292002795264124870300292969,
|
|
+ 2210.9835111177717408281750977039337158203125,
|
|
+ 252.28469071093292086516157723963260650634765625,
|
|
+ 1479.28580699818076027440838515758514404296875,
|
|
+ 358.2883493183543350824038498103618621826171875,
|
|
+ 86.4399992258764626740230596624314785003662109375,
|
|
+ 0.29277260204409949473358665272826328873634338378906,
|
|
+ 1.0,
|
|
+ 1.0,
|
|
+ 11.300678128510535103146139590535312891006469726562,
|
|
+ 0.49998270338340455865022704529110342264175415039062,
|
|
+ 9.4889928089799600030573856201954185962677001953125,
|
|
+ 1.0885854822898506366612991769216023385524749755859,
|
|
+ 53.20529981175358358314042561687529087066650390625,
|
|
+ 36.65171139901388386306280153803527355194091796875,
|
|
+ 214.68561782216193023486994206905364990234375,
|
|
+ 2.8728217196022858281878598063485696911811828613281,
|
|
+ 1.0,
|
|
+ 1653.1016242378727838513441383838653564453125,
|
|
+ 0.37064443536603375317639574859640561044216156005859,
|
|
+ 20.0905336391907667348277755081653594970703125,
|
|
+ 288.66579115116110187955200672149658203125,
|
|
+ 967784087203564544.0,
|
|
+ 986920622098821248.0,
|
|
+ 17.499765511468584833210115903057157993316650390625,
|
|
+ 0.57797196338014200645005757905892096459865570068359,
|
|
+ 0.028955889395889600895772630906321865040808916091919,
|
|
+ 0.49998270338340455865022704529110342264175415039062,
|
|
+ 319.19585661999855119574931450188159942626953125,
|
|
+ 38.6813101625874224964718450792133808135986328125,
|
|
+ 39.62777871280881214488545083440840244293212890625,
|
|
+ 5.0871202966110988796799574629403650760650634765625,
|
|
+ 0.69504605038799238680979897253564558923244476318359,
|
|
+ 673.3477042973012203219695948064327239990234375,
|
|
+ 56.94168682747444876213194220326840877532958984375,
|
|
+ 1.0,
|
|
+ 261.01902251155337353338836692273616790771484375,
|
|
+ 1.0,
|
|
+ 85.0611943221388884239786420948803424835205078125,
|
|
+ 53.12927927294536090130350203253328800201416015625,
|
|
+ 21.829518414441992035790462978184223175048828125,
|
|
+ 1898.72146183866834689979441463947296142578125,
|
|
+ 1.0,
|
|
+ 9.7285926829767870316345579340122640132904052734375,
|
|
+ 174.40267892003106453557847999036312103271484375,
|
|
+ 0.98364895900708060327843895720434375107288360595703,
|
|
+ 1.1152676652901183373955973365809768438339233398438,
|
|
+ 18.12268289087599981712628505192697048187255859375,
|
|
+ 1.0,
|
|
+ 0.1715993516574435828747624555035145021975040435791,
|
|
+ 0.49275933843630442821037718204024713486433029174805,
|
|
+ 0.031531692879025040310292382628176710568368434906006,
|
|
+ 23.13033056510358420609918539412319660186767578125,
|
|
+ 210.58233961820729973624111153185367584228515625,
|
|
+ 5.1604155410259560099461850768420845270156860351562,
|
|
+ 2053.87275307550726211047731339931488037109375,
|
|
+ 1.0834136602451556186110792623367160558700561523438,
|
|
+ 3840.080091990574146620929241180419921875,
|
|
+ 13192.047960544839952490292489528656005859375,
|
|
+ 348.088713237990532434196211397647857666015625,
|
|
+ 439.96013885313283253708505071699619293212890625,
|
|
+ 897.3433304220051240918110124766826629638671875,
|
|
+ 0.69288480487588777201324319321429356932640075683594,
|
|
+ 2894.596744865002619917504489421844482421875,
|
|
+ 3788.94162413956064483500085771083831787109375,
|
|
+ 94.549943427633166947998688556253910064697265625,
|
|
+ 649339661894085888.0,
|
|
+ 0.48660066498392295919472871901234611868858337402344,
|
|
+ 0.12382015553845396316212656984134810045361518859863,
|
|
+ 0.50791641118256847242662388453027233481407165527344,
|
|
+ 1.0};
|
|
+
|
|
+public:
|
|
+ FIModelRunner(LLVMContext &Ctx,
|
|
+ std::vector<std::pair<std::string, std::string>> Features,
|
|
+ StringRef DecisionName)
|
|
+ : AOTModelRunner<FICompiledModel>(
|
|
+ Ctx,
|
|
+ {{"input_1", "float32[" + std::to_string(Features.size()) + "]"}},
|
|
+ DecisionName) {}
|
|
+
|
|
+ // Features for this model are only floats so we only need to override the
|
|
+ // float method to handle feature scaling and the input type
|
|
+ bool setCustomFeature(int FeatureIndex, float FeatureValue) override {
|
|
+ // Scale the feature according to the constant mean and scale value
|
|
+ // Feature scaling is done to create a standard normal distribution:
|
|
+ // subtract mean, then divide by standard deviation ("scale")
|
|
+ float ScaledValue =
|
|
+ (FeatureValue - Means[FeatureIndex]) / Scales[FeatureIndex];
|
|
+ // Assuming the Buffer at index 0 is for feature input of shape:
|
|
+ // (Feature.size())
|
|
+ float *Location = getTensor<float>(0) + FeatureIndex;
|
|
+ *Location = ScaledValue;
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ // Outputs for this model are only int so we only need to override this
|
|
+ // method
|
|
+ int getModelResultI(std::string OutputName) override {
|
|
+ if (OutputName == "FI-ShouldInline") {
|
|
+ int Classes[] = {0, 1};
|
|
+ void *ResultUntyped = CompiledModel->result_data(0);
|
|
+ float *Result = reinterpret_cast<float *>(ResultUntyped);
|
|
+ float Max = Result[0];
|
|
+ int MaxClass = 0;
|
|
+ for (size_t I = 0; I < sizeof(Classes) / sizeof(int); ++I) {
|
|
+ if (Result[I] > Max) {
|
|
+ Max = Result[I];
|
|
+ MaxClass = I;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return Classes[MaxClass];
|
|
+ }
|
|
+ assert(false && "ModelRunner received invalid result name");
|
|
+ }
|
|
+};
|
|
+
|
|
+} // namespace llvm
|
|
+
|
|
+#endif // LLVM_ANALYSIS_FIMODELRUNNER_H
|
|
+
|
|
+#endif // LLVM_HAVE_TF_AOT_FICOMPILEDMODEL
|
|
+
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/include/llvm/Analysis/InlineAdvisor.h b/llvm/include/llvm/Analysis/InlineAdvisor.h
|
|
index 53c018d15cd7..adf36a385725 100644
|
|
--- a/llvm/include/llvm/Analysis/InlineAdvisor.h
|
|
+++ b/llvm/include/llvm/Analysis/InlineAdvisor.h
|
|
@@ -200,6 +200,22 @@ public:
|
|
return AnnotatedInlinePassName.c_str();
|
|
}
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+ /// Helper functions used by getFeatures to retrieve certain information
|
|
+ ///{
|
|
+ CallBase *getInlinableCS(Instruction &I);
|
|
+ int64_t getLocalCalls(Function &F);
|
|
+ unsigned getCallLoopLevel(CallBase &CB) const;
|
|
+ uint64_t getCalleeBlockFreq(CallBase &CB) const;
|
|
+ unsigned getCallSiteHeight(CallBase *CB);
|
|
+ ///}
|
|
+
|
|
+ // Allow ACPO infrastructure to replicate Advisor behaviour
|
|
+ virtual bool isForcedToStop() const { return false; }
|
|
+ bool neverInline(CallBase &CB) const;
|
|
+ bool isCSInlinable(CallBase &CB) const;
|
|
+#endif
|
|
+
|
|
protected:
|
|
InlineAdvisor(Module &M, FunctionAnalysisManager &FAM,
|
|
std::optional<InlineContext> IC = std::nullopt);
|
|
@@ -213,6 +229,15 @@ protected:
|
|
const std::string AnnotatedInlinePassName;
|
|
std::unique_ptr<ImportedFunctionsInliningStatistics> ImportedFunctionsStats;
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+ /// Map a function to its callheight
|
|
+ std::map<const Function *, unsigned> FunctionLevels;
|
|
+ // used by getORE() for legacy PM
|
|
+ static std::unique_ptr<OptimizationRemarkEmitter> ORE;
|
|
+
|
|
+ friend class ACPOCollectFeatures;
|
|
+#endif
|
|
+
|
|
enum class MandatoryInliningKind { NotMandatory, Always, Never };
|
|
|
|
static MandatoryInliningKind getMandatoryKind(CallBase &CB,
|
|
@@ -389,6 +414,11 @@ void emitInlinedIntoBasedOnCost(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
|
|
bool ForProfileContext = false,
|
|
const char *PassName = nullptr);
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+/// get call site location as string.
|
|
+std::string getCallSiteLocation(DebugLoc DLoc);
|
|
+#endif
|
|
+
|
|
/// Add location info to ORE message.
|
|
void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc);
|
|
|
|
diff --git a/llvm/include/llvm/Analysis/InlineModelFeatureMaps.h b/llvm/include/llvm/Analysis/InlineModelFeatureMaps.h
|
|
index 77ae60059ce9..e7ece46342fd 100644
|
|
--- a/llvm/include/llvm/Analysis/InlineModelFeatureMaps.h
|
|
+++ b/llvm/include/llvm/Analysis/InlineModelFeatureMaps.h
|
|
@@ -72,6 +72,36 @@ enum class InlineCostFeatureIndex : size_t {
|
|
|
|
NumberOfFeatures
|
|
};
|
|
+
|
|
+#if defined(ENABLE_ACPO)
|
|
+const std::map<InlineCostFeatureIndex, std::string> InlineCostFeatureIndexToName = {
|
|
+ { InlineCostFeatureIndex::sroa_savings, "sroa_savings" },
|
|
+ { InlineCostFeatureIndex::sroa_losses, "sroa_losses" },
|
|
+ { InlineCostFeatureIndex::load_elimination, "load_elimination" },
|
|
+ { InlineCostFeatureIndex::call_penalty, "call_penalty" },
|
|
+ { InlineCostFeatureIndex::call_argument_setup, "call_argument_setup" },
|
|
+ { InlineCostFeatureIndex::load_relative_intrinsic, "load_relative_intrinsic" },
|
|
+ { InlineCostFeatureIndex::lowered_call_arg_setup, "lowered_call_arg_setup" },
|
|
+ { InlineCostFeatureIndex::indirect_call_penalty, "indirect_call_penalty" },
|
|
+ { InlineCostFeatureIndex::jump_table_penalty, "jump_table_penalty" },
|
|
+ { InlineCostFeatureIndex::case_cluster_penalty, "case_cluster_penalty" },
|
|
+ { InlineCostFeatureIndex::switch_penalty, "switch_penalty" },
|
|
+ { InlineCostFeatureIndex::unsimplified_common_instructions, "unsimplified_common_instructions" },
|
|
+ { InlineCostFeatureIndex::num_loops, "num_loops" },
|
|
+ { InlineCostFeatureIndex::dead_blocks, "dead_blocks" },
|
|
+ { InlineCostFeatureIndex::simplified_instructions, "simplified_instructions" },
|
|
+ { InlineCostFeatureIndex::constant_args, "constant_args" },
|
|
+ { InlineCostFeatureIndex::constant_offset_ptr_args, "constant_offset_ptr_args" },
|
|
+ { InlineCostFeatureIndex::callsite_cost, "callsite_cost" },
|
|
+ { InlineCostFeatureIndex::cold_cc_penalty, "cold_cc_penalty" },
|
|
+ { InlineCostFeatureIndex::last_call_to_static_bonus, "last_call_to_static_bonus" },
|
|
+ { InlineCostFeatureIndex::is_multiple_blocks, "is_multiple_blocks" },
|
|
+ { InlineCostFeatureIndex::nested_inlines, "nested_inlines" },
|
|
+ { InlineCostFeatureIndex::nested_inline_cost_estimate, "nested_inline_cost_estimate" },
|
|
+ { InlineCostFeatureIndex::threshold, "threshold" }
|
|
+};
|
|
+#endif
|
|
+
|
|
// clang-format on
|
|
|
|
using InlineCostFeatures =
|
|
diff --git a/llvm/include/llvm/Analysis/MLInlineAdvisor.h b/llvm/include/llvm/Analysis/MLInlineAdvisor.h
|
|
index f58862e53352..e302b0a979a5 100644
|
|
--- a/llvm/include/llvm/Analysis/MLInlineAdvisor.h
|
|
+++ b/llvm/include/llvm/Analysis/MLInlineAdvisor.h
|
|
@@ -41,8 +41,11 @@ public:
|
|
}
|
|
void onSuccessfulInlining(const MLInlineAdvice &Advice,
|
|
bool CalleeWasDeleted);
|
|
-
|
|
+#if defined(ENABLE_ACPO)
|
|
+ bool isForcedToStop() const override { return ForceStop; }
|
|
+#else
|
|
bool isForcedToStop() const { return ForceStop; }
|
|
+#endif
|
|
int64_t getLocalCalls(Function &F);
|
|
const MLModelRunner &getModelRunner() const { return *ModelRunner.get(); }
|
|
FunctionPropertiesInfo &getCachedFPI(Function &) const;
|
|
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
|
|
index 7fdb5db67c16..89160cfd17d1 100644
|
|
--- a/llvm/include/llvm/InitializePasses.h
|
|
+++ b/llvm/include/llvm/InitializePasses.h
|
|
@@ -100,7 +100,9 @@ void initializeDomPrinterWrapperPassPass(PassRegistry &);
|
|
void initializeDomViewerWrapperPassPass(PassRegistry &);
|
|
void initializeDominanceFrontierWrapperPassPass(PassRegistry&);
|
|
void initializeDominatorTreeWrapperPassPass(PassRegistry&);
|
|
+#if defined(ENABLE_ACPO)
|
|
void initializeDumpCallsiteLegacyPass(PassRegistry &);
|
|
+#endif
|
|
void initializeDwarfEHPrepareLegacyPassPass(PassRegistry &);
|
|
void initializeEarlyCSELegacyPassPass(PassRegistry&);
|
|
void initializeEarlyCSEMemSSALegacyPassPass(PassRegistry&);
|
|
@@ -134,7 +136,9 @@ void initializeGlobalsAAWrapperPassPass(PassRegistry&);
|
|
void initializeGuardWideningLegacyPassPass(PassRegistry&);
|
|
void initializeHardwareLoopsLegacyPass(PassRegistry&);
|
|
void initializeMIRProfileLoaderPassPass(PassRegistry &);
|
|
+#if defined(ENABLE_ACPO)
|
|
void initializeInlineAdvisorAnalysisWrapperPass(PassRegistry &);
|
|
+#endif
|
|
void initializeIRSimilarityIdentifierWrapperPassPass(PassRegistry&);
|
|
void initializeIRTranslatorPass(PassRegistry&);
|
|
void initializeIVUsersWrapperPassPass(PassRegistry&);
|
|
@@ -152,11 +156,13 @@ void initializeInterleavedLoadCombinePass(PassRegistry &);
|
|
void initializeIntervalPartitionPass(PassRegistry&);
|
|
void initializeJMCInstrumenterPass(PassRegistry&);
|
|
void initializeKCFIPass(PassRegistry &);
|
|
+#if defined(ENABLE_ACPO)
|
|
void initializeLegacyFAMPass(PassRegistry &);
|
|
void initializeLegacyFunctionPropertiesAnalysisPass(PassRegistry &);
|
|
void initializeLegacyInlinerPassPass(PassRegistry &);
|
|
void initializeLegacyInlineSizeEstimatorAnalysisPass(PassRegistry &);
|
|
void initializeLegacyModuleInlinerWrapperPassPass(PassRegistry &);
|
|
+#endif
|
|
void initializeLCSSAVerificationPassPass(PassRegistry&);
|
|
void initializeLCSSAWrapperPassPass(PassRegistry&);
|
|
void initializeLazyBlockFrequencyInfoPassPass(PassRegistry&);
|
|
diff --git a/llvm/include/llvm/Transforms/IPO.h b/llvm/include/llvm/Transforms/IPO.h
|
|
index 4995b000c454..6905acb261fe 100644
|
|
--- a/llvm/include/llvm/Transforms/IPO.h
|
|
+++ b/llvm/include/llvm/Transforms/IPO.h
|
|
@@ -18,6 +18,10 @@
|
|
#include <functional>
|
|
#include <vector>
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+#include "llvm/Analysis/InlineAdvisor.h"
|
|
+#endif
|
|
+
|
|
namespace llvm {
|
|
|
|
class ModulePass;
|
|
diff --git a/llvm/include/llvm/Transforms/IPO/Inliner.h b/llvm/include/llvm/Transforms/IPO/Inliner.h
|
|
index 401aa2d3a0cc..46a3468c927c 100644
|
|
--- a/llvm/include/llvm/Transforms/IPO/Inliner.h
|
|
+++ b/llvm/include/llvm/Transforms/IPO/Inliner.h
|
|
@@ -16,6 +16,15 @@
|
|
#include "llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h"
|
|
#include "llvm/IR/PassManager.h"
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+#include "llvm/ADT/STLExtras.h"
|
|
+#include "llvm/Analysis/BasicAliasAnalysis.h"
|
|
+#include "llvm/IR/LegacyPassManager.h"
|
|
+#include "llvm/IR/Module.h"
|
|
+#include "llvm/Pass.h"
|
|
+#include <utility>
|
|
+#endif
|
|
+
|
|
namespace llvm {
|
|
|
|
/// The inliner pass for the new pass manager.
|
|
diff --git a/llvm/lib/Analysis/ACPOCollectFeatures.cpp b/llvm/lib/Analysis/ACPOCollectFeatures.cpp
|
|
index f9de26483c76..daa924f2cb3b 100644
|
|
--- a/llvm/lib/Analysis/ACPOCollectFeatures.cpp
|
|
+++ b/llvm/lib/Analysis/ACPOCollectFeatures.cpp
|
|
@@ -10,6 +10,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#include "llvm/Analysis/ACPOCollectFeatures.h"
|
|
#include "llvm/ADT/SCCIterator.h"
|
|
// The ACPOFIModel.h currently contains only the cache system for
|
|
@@ -1256,3 +1257,4 @@ operator++(ACPOCollectFeatures::FeatureIndex &N, int) {
|
|
}
|
|
|
|
} // namespace llvm
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/lib/Analysis/ACPOFIModel.cpp b/llvm/lib/Analysis/ACPOFIModel.cpp
|
|
new file mode 100644
|
|
index 000000000000..d9a647ec1012
|
|
--- /dev/null
|
|
+++ b/llvm/lib/Analysis/ACPOFIModel.cpp
|
|
@@ -0,0 +1,243 @@
|
|
+//===- ACPOFIModel.cpp - AI-Enabled Continuous Program Optimization -------===//
|
|
+//
|
|
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
+// See https://llvm.org/LICENSE.txt for license information.
|
|
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
+//
|
|
+//===----------------------------------------------------------------------===//
|
|
+//
|
|
+// This file implements the interface between ACPO and ML-guided optimizations.
|
|
+// It delegates decision making to inference with a pre-trained model.
|
|
+//
|
|
+//===----------------------------------------------------------------------===//
|
|
+
|
|
+#if defined(ENABLE_ACPO)
|
|
+#include "llvm/Analysis/ACPOFIModel.h"
|
|
+#include "llvm/Support/CommandLine.h"
|
|
+#include "llvm/Support/Process.h"
|
|
+
|
|
+using namespace llvm;
|
|
+
|
|
+#define DEBUG_TYPE "acpo"
|
|
+#define ACPO_ENV_VAR_DIR "ACPO_DIR"
|
|
+
|
|
+cl::opt<bool>
|
|
+ EnableACPOFI("enable-acpo-fi", cl::init(false), cl::Hidden,
|
|
+ cl::desc("Leverage ACPO ML model to decide inlining."));
|
|
+
|
|
+cl::opt<bool>
|
|
+ EnableAOTFI("enable-acpo-fi-aot", cl::init(false), cl::Hidden,
|
|
+ cl::desc("Leverage AOT ML model to decide inlining."));
|
|
+
|
|
+ACPOFIModel::ACPOFIModel(CallBase *CB, InlineAdvisor *IA,
|
|
+ OptimizationRemarkEmitter *ORE, bool OnlyMandatory,
|
|
+ bool UseML)
|
|
+ : ACPOModel(ORE, UseML), CurrentCB(CB), NotACPOAdvisor(IA),
|
|
+ OnlyMandatory(OnlyMandatory) {
|
|
+ Function *Caller = CB->getCaller();
|
|
+ LLVMContext *Context = &(Caller->getContext());
|
|
+ setContextPtr(Context);
|
|
+ if (EnableACPOFI)
|
|
+ // ACPO Python support
|
|
+ setMLIF(createPersistentPythonMLIF());
|
|
+ else if (EnableAOTFI)
|
|
+ // ACPO AOT support
|
|
+ setMLIF(createPersistentCompiledMLIF());
|
|
+}
|
|
+
|
|
+ACPOFIModel::~ACPOFIModel() {}
|
|
+
|
|
+void ACPOFIModel::setMLCustomFeatures(
|
|
+ std::vector<std::pair<std::string, std::string>> FeatureValues) {
|
|
+ CustomFeatureValues = FeatureValues;
|
|
+}
|
|
+
|
|
+void ACPOFIModel::sendCustomFeatures() {
|
|
+ // Get an ACPOMLInterface to communicate with the Python side
|
|
+ std::shared_ptr<ACPOMLInterface> MLIF = getMLIF();
|
|
+ MLIF->initializeFeatures("FI", CustomFeatureValues);
|
|
+}
|
|
+
|
|
+void ACPOFIModel::recordUnattemptedInlining() {
|
|
+ if (NotACPOAdvice)
|
|
+ NotACPOAdvice->recordUnattemptedInlining();
|
|
+}
|
|
+
|
|
+void ACPOFIModel::recordInlining() {
|
|
+ if (NotACPOAdvice)
|
|
+ NotACPOAdvice->recordInlining();
|
|
+}
|
|
+
|
|
+void ACPOFIModel::recordUnsuccessfulInlining(InlineResult &IR) {
|
|
+ if (NotACPOAdvice)
|
|
+ NotACPOAdvice->recordUnsuccessfulInlining(IR);
|
|
+}
|
|
+
|
|
+void ACPOFIModel::recordInliningWithCalleeDeleted() {
|
|
+ if (NotACPOAdvice)
|
|
+ NotACPOAdvice->recordInliningWithCalleeDeleted();
|
|
+}
|
|
+
|
|
+void ACPOFIModel::invalidateCache(CallBase *CB) {
|
|
+ if (CB) {
|
|
+ invalidateCache(CB->getCaller());
|
|
+ }
|
|
+}
|
|
+
|
|
+InlineAdvisor *ACPOFIModel::getNotACPOAdvisor() { return NotACPOAdvisor; }
|
|
+
|
|
+void ACPOFIModel::invalidateCache(const Function *F) {
|
|
+ for (ACPOFIExtendedFeatures::NamedFeatureIndex feature =
|
|
+ ACPOFIExtendedFeatures::NamedFeatureIndex(0);
|
|
+ feature != ACPOFIExtendedFeatures::NamedFeatureIndex::NumNamedFeatures;
|
|
+ ++feature) {
|
|
+ FeatureCache[feature].erase(F);
|
|
+ }
|
|
+ for (ACPOFIExtendedFeatures::NamedFloatFeatureIndex feature =
|
|
+ ACPOFIExtendedFeatures::NamedFloatFeatureIndex(0);
|
|
+ feature !=
|
|
+ ACPOFIExtendedFeatures::NamedFloatFeatureIndex::NumNamedFloatFeatures;
|
|
+ ++feature) {
|
|
+ FeatureCache[feature].erase(F);
|
|
+ }
|
|
+ FunctionAnalysisCache.DomCache.erase(F);
|
|
+ FunctionAnalysisCache.LICache.erase(F);
|
|
+ FunctionAnalysisCache.TTICache.erase(F);
|
|
+}
|
|
+
|
|
+void ACPOFIModel::clearCache() {
|
|
+ for (ACPOFIExtendedFeatures::NamedFeatureIndex feature =
|
|
+ ACPOFIExtendedFeatures::NamedFeatureIndex(0);
|
|
+ feature != ACPOFIExtendedFeatures::NamedFeatureIndex::NumNamedFeatures;
|
|
+ ++feature) {
|
|
+ FeatureCache[feature].clear();
|
|
+ }
|
|
+ for (ACPOFIExtendedFeatures::NamedFloatFeatureIndex feature =
|
|
+ ACPOFIExtendedFeatures::NamedFloatFeatureIndex(0);
|
|
+ feature !=
|
|
+ ACPOFIExtendedFeatures::NamedFloatFeatureIndex::NumNamedFloatFeatures;
|
|
+ ++feature) {
|
|
+ FeatureCache[feature].clear();
|
|
+ }
|
|
+ FunctionAnalysisCache.DomCache.clear();
|
|
+ FunctionAnalysisCache.LICache.clear();
|
|
+ FunctionAnalysisCache.TTICache.clear();
|
|
+}
|
|
+
|
|
+std::optional<size_t>
|
|
+ACPOFIModel::getCachedSize(const Function *F,
|
|
+ ACPOFIExtendedFeatures::NamedFeatureIndex idx) {
|
|
+ auto it = FeatureCache[idx].find(F);
|
|
+ return it != FeatureCache[idx].end() ? std::optional<size_t>(it->second)
|
|
+ : std::nullopt;
|
|
+}
|
|
+
|
|
+std::optional<float> ACPOFIModel::getCachedFloat(
|
|
+ const Function *F, ACPOFIExtendedFeatures::NamedFloatFeatureIndex idx) {
|
|
+ auto it = FeatureCache[idx].find(F);
|
|
+ return it != FeatureCache[idx].end() ? std::optional<float>(it->second)
|
|
+ : std::nullopt;
|
|
+}
|
|
+
|
|
+void ACPOFIModel::insertSizeCache(const Function *F,
|
|
+ ACPOFIExtendedFeatures::NamedFeatureIndex idx,
|
|
+ size_t val) {
|
|
+ FeatureCache[idx].insert(std::make_pair(F, val));
|
|
+}
|
|
+
|
|
+void ACPOFIModel::insertFloatCache(
|
|
+ const Function *F, ACPOFIExtendedFeatures::NamedFloatFeatureIndex idx,
|
|
+ float val) {
|
|
+ FeatureCache[idx].insert(std::make_pair(F, val));
|
|
+}
|
|
+
|
|
+const DominatorTree *ACPOFIModel::getDomCachedAnalysis(const Function *F) {
|
|
+ auto it = FunctionAnalysisCache.DomCache.find(F);
|
|
+ return it != FunctionAnalysisCache.DomCache.end() ? it->second : nullptr;
|
|
+}
|
|
+
|
|
+const LoopInfo *ACPOFIModel::getLICachedAnalysis(const Function *F) {
|
|
+ auto it = FunctionAnalysisCache.LICache.find(F);
|
|
+ return it != FunctionAnalysisCache.LICache.end() ? it->second : nullptr;
|
|
+}
|
|
+
|
|
+const TargetTransformInfo *
|
|
+ACPOFIModel::getTTICachedAnalysis(const Function *F) {
|
|
+ auto it = FunctionAnalysisCache.TTICache.find(F);
|
|
+ return it != FunctionAnalysisCache.TTICache.end() ? it->second : nullptr;
|
|
+}
|
|
+
|
|
+void ACPOFIModel::insertAnalysisCache(const Function *F,
|
|
+ const DominatorTree *Tree) {
|
|
+ FunctionAnalysisCache.DomCache.insert(std::make_pair(F, Tree));
|
|
+}
|
|
+
|
|
+void ACPOFIModel::insertAnalysisCache(const Function *F, const LoopInfo *LI) {
|
|
+ FunctionAnalysisCache.LICache.insert(std::make_pair(F, LI));
|
|
+}
|
|
+
|
|
+void ACPOFIModel::insertAnalysisCache(const Function *F,
|
|
+ const TargetTransformInfo *TTI) {
|
|
+ FunctionAnalysisCache.TTICache.insert(std::make_pair(F, TTI));
|
|
+}
|
|
+
|
|
+std::unique_ptr<ACPOAdvice> ACPOFIModel::getAdviceML() {
|
|
+ std::shared_ptr<ACPOMLInterface> MLIF = getMLIF();
|
|
+ // Generate result.
|
|
+ std::unique_ptr<ACPOAdvice> Advice = std::make_unique<ACPOAdvice>();
|
|
+ // handle mandatory case, forcestop, never inline or not inlinable cases
|
|
+ if (OnlyMandatory)
|
|
+ return getAdviceNoML();
|
|
+ if (NotACPOAdvisor->neverInline(*CurrentCB) ||
|
|
+ !NotACPOAdvisor->isCSInlinable(*CurrentCB)) {
|
|
+ Advice->addField("FI-ShouldInline",
|
|
+ ConstantInt::get(Type::getInt64Ty(*(getContextPtr())),
|
|
+ (int64_t) false));
|
|
+ NotACPOAdvice = nullptr;
|
|
+ return Advice;
|
|
+ }
|
|
+ std::optional<std::string> Env = llvm::sys::Process::GetEnv(ACPO_ENV_VAR_DIR);
|
|
+ if (!Env || *Env == "") {
|
|
+ std::optional<std::string> LLVMDIROpt =
|
|
+ llvm::sys::Process::GetEnv("LLVM_DIR");
|
|
+ if (!LLVMDIROpt) {
|
|
+ outs() << "ACPO_DIR not found. "
|
|
+ << "Did you export ACPO_DIR to $LLVM_DIR/acpo ?\n"
|
|
+ << "Falling back to default advisor. \n";
|
|
+ return getAdviceNoML();
|
|
+ }
|
|
+ }
|
|
+ assert(MLIF != nullptr);
|
|
+ if (!MLIF->loadModel("model-fi.acpo")) {
|
|
+ outs() << "Model not loaded correctly. \n";
|
|
+ return getAdviceNoML();
|
|
+ }
|
|
+ if (!MLIF->initializeFeatures("FI", CustomFeatureValues)) {
|
|
+ outs() << "Features not initialized correctly. \n";
|
|
+ return getAdviceNoML();
|
|
+ }
|
|
+ bool ModelRunOK = MLIF->runModel("FI");
|
|
+ assert(ModelRunOK);
|
|
+ ShouldInline = MLIF->getModelResultI("FI-ShouldInline");
|
|
+ assert(getContextPtr() != nullptr);
|
|
+ Advice->addField("FI-ShouldInline",
|
|
+ ConstantInt::get(Type::getInt64Ty(*(getContextPtr())),
|
|
+ (int64_t)ShouldInline));
|
|
+ return Advice;
|
|
+}
|
|
+
|
|
+std::unique_ptr<ACPOAdvice> ACPOFIModel::getAdviceNoML() {
|
|
+ // Use the advisor used by default inlining
|
|
+ std::unique_ptr<ACPOAdvice> Advice = std::make_unique<ACPOAdvice>();
|
|
+ assert(getContextPtr() != nullptr);
|
|
+ NotACPOAdvice = NotACPOAdvisor->getAdvice(*CurrentCB, OnlyMandatory);
|
|
+ bool ShouldInline = NotACPOAdvice->isInliningRecommended();
|
|
+ Advice->addField("FI-ShouldInline",
|
|
+ ConstantInt::get(Type::getInt64Ty(*(getContextPtr())),
|
|
+ (int64_t)ShouldInline));
|
|
+ return Advice;
|
|
+}
|
|
+
|
|
+ACPOFIModel::FunctionFeaturesCache ACPOFIModel::FeatureCache;
|
|
+ACPOFIModel::FunctionAnalysisMap ACPOFIModel::FunctionAnalysisCache;
|
|
+#endif // ENABLE_ACPO
|
|
diff --git a/llvm/lib/Analysis/ACPOMLInterface.cpp b/llvm/lib/Analysis/ACPOMLInterface.cpp
|
|
index 271dcfe7d851..f48eb46638e3 100644
|
|
--- a/llvm/lib/Analysis/ACPOMLInterface.cpp
|
|
+++ b/llvm/lib/Analysis/ACPOMLInterface.cpp
|
|
@@ -10,6 +10,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#include "llvm/Analysis/ACPOMLInterface.h"
|
|
#include "llvm/Analysis/ACPOModelRunner.h"
|
|
#include "llvm/Analysis/FIModelRunner.h"
|
|
@@ -1403,3 +1404,4 @@ const std::unordered_map<std::string,
|
|
{"FI", createFI},
|
|
#endif
|
|
};
|
|
+#endif
|
|
diff --git a/llvm/lib/Analysis/ACPOModel.cpp b/llvm/lib/Analysis/ACPOModel.cpp
|
|
index 2d0dae733943..fac760f37ef5 100644
|
|
--- a/llvm/lib/Analysis/ACPOModel.cpp
|
|
+++ b/llvm/lib/Analysis/ACPOModel.cpp
|
|
@@ -11,6 +11,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#include "llvm/Analysis/ACPOModel.h"
|
|
#include "llvm/Analysis/LoopInfo.h"
|
|
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
|
@@ -61,3 +62,4 @@ void ACPOModel::addFeature(int64_t ID, Constant *Val) {
|
|
assert(CustomFeatureMap.find(ID) == CustomFeatureMap.end());
|
|
CustomFeatureMap[ID] = Val;
|
|
}
|
|
+#endif
|
|
diff --git a/llvm/lib/Analysis/CallHeight.cpp b/llvm/lib/Analysis/CallHeight.cpp
|
|
index f7b88cbdff05..e42547344796 100644
|
|
--- a/llvm/lib/Analysis/CallHeight.cpp
|
|
+++ b/llvm/lib/Analysis/CallHeight.cpp
|
|
@@ -9,6 +9,8 @@
|
|
// This file implements getting the call height of functions in a module.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
+
|
|
+#if defined(ENABLE_ACPO)
|
|
#include "llvm/Analysis/CallHeight.h"
|
|
#include "llvm/ADT/SCCIterator.h"
|
|
#include "llvm/Analysis/CallGraph.h"
|
|
@@ -87,3 +89,4 @@ INITIALIZE_PASS(CallHeightAnalysisWrapper, DEBUG_TYPE, "Call Height Analysis",
|
|
Pass *llvm::createCallHeightAnalysisWrapper() {
|
|
return new CallHeightAnalysisWrapper();
|
|
}
|
|
+#endif
|
|
diff --git a/llvm/lib/Analysis/DumpCallsite.cpp b/llvm/lib/Analysis/DumpCallsite.cpp
|
|
index d49885a372f2..64ff0d0db8f7 100644
|
|
--- a/llvm/lib/Analysis/DumpCallsite.cpp
|
|
+++ b/llvm/lib/Analysis/DumpCallsite.cpp
|
|
@@ -9,6 +9,7 @@
|
|
// This file implements the ability to dump all callsites in a given function.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
+#if defined(ENABLE_ACPO)
|
|
#include "llvm/Analysis/DumpCallsite.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/InstIterator.h"
|
|
@@ -80,3 +81,4 @@ PreservedAnalyses DumpCallsitePass::run(Function &F,
|
|
Impl.run(F);
|
|
return PreservedAnalyses::all();
|
|
}
|
|
+#endif
|
|
diff --git a/llvm/lib/Analysis/DumpFeature.cpp b/llvm/lib/Analysis/DumpFeature.cpp
|
|
index 81756226c2fd..52acbb2456ad 100644
|
|
--- a/llvm/lib/Analysis/DumpFeature.cpp
|
|
+++ b/llvm/lib/Analysis/DumpFeature.cpp
|
|
@@ -9,6 +9,8 @@
|
|
// This file implements dumping features for functions in an scc.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
+
|
|
+#if defined(ENABLE_ACPO)
|
|
#include "llvm/Analysis/DumpFeature.h"
|
|
#include "llvm/ADT/SCCIterator.h"
|
|
#include "llvm/Analysis/CallHeight.h"
|
|
@@ -573,3 +575,4 @@ operator++(ACPOFIExtendedFeatures::NamedFloatFeatureIndex &n, int) {
|
|
++n;
|
|
return res;
|
|
}
|
|
+#endif
|
|
diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp
|
|
index f6b3c14a0345..4df989ca2b64 100644
|
|
--- a/llvm/lib/Analysis/InlineAdvisor.cpp
|
|
+++ b/llvm/lib/Analysis/InlineAdvisor.cpp
|
|
@@ -27,6 +27,25 @@
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+#include "llvm/ADT/StringRef.h"
|
|
+#include <unordered_set>
|
|
+
|
|
+#include "llvm/ADT/SCCIterator.h"
|
|
+#include "llvm/ADT/StringRef.h"
|
|
+#include "llvm/Analysis/ACPOFIModel.h"
|
|
+#include "llvm/Analysis/DumpFeature.h"
|
|
+#include "llvm/Analysis/FunctionPropertiesAnalysis.h"
|
|
+#include "llvm/Analysis/InlineModelFeatureMaps.h"
|
|
+#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h"
|
|
+#include "llvm/Analysis/LoopInfo.h"
|
|
+#include "llvm/IR/InstIterator.h"
|
|
+#include "llvm/IR/Instructions.h"
|
|
+#include "llvm/InitializePasses.h"
|
|
+#include "llvm/Transforms/IPO/Inliner.h"
|
|
+#include <memory>
|
|
+#endif
|
|
+
|
|
using namespace llvm;
|
|
#define DEBUG_TYPE "inline"
|
|
#ifdef LLVM_HAVE_TF_AOT_INLINERSIZEMODEL
|
|
@@ -537,6 +556,46 @@ void llvm::emitInlinedIntoBasedOnCost(
|
|
PassName);
|
|
}
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+CallBase *InlineAdvisor::getInlinableCS(Instruction &I) {
|
|
+ if (auto *CS = dyn_cast<CallBase>(&I))
|
|
+ if (Function *Callee = CS->getCalledFunction()) {
|
|
+ if (!Callee->isDeclaration()) {
|
|
+ return CS;
|
|
+ }
|
|
+ }
|
|
+ return nullptr;
|
|
+}
|
|
+
|
|
+// TODO: We can make this faster on large programs by applying
|
|
+// this patch from MLGO f46dd19b480496d2ba0a57d12935882e530f2b93.
|
|
+// This patch incrementally computes FunctionPropertiesInfo
|
|
+// instead of recomputing.
|
|
+int64_t InlineAdvisor::getLocalCalls(Function &F) {
|
|
+ return FAM.getResult<FunctionPropertiesAnalysis>(F)
|
|
+ .DirectCallsToDefinedFunctions;
|
|
+}
|
|
+
|
|
+unsigned InlineAdvisor::getCallLoopLevel(CallBase &CB) const {
|
|
+ Function *F = CB.getCaller();
|
|
+ BasicBlock *BB = CB.getParent();
|
|
+ LoopInfo &LI = FAM.getResult<LoopAnalysis>(*F);
|
|
+ return LI.getLoopDepth(BB);
|
|
+}
|
|
+
|
|
+uint64_t InlineAdvisor::getCalleeBlockFreq(CallBase &CB) const {
|
|
+ Function *F = CB.getCaller();
|
|
+ BasicBlock *BB = CB.getParent();
|
|
+ BlockFrequencyInfo &BFI = FAM.getResult<BlockFrequencyAnalysis>(*F);
|
|
+ return BFI.getBlockFreq(BB).getFrequency();
|
|
+}
|
|
+
|
|
+unsigned InlineAdvisor::getCallSiteHeight(CallBase *CB) {
|
|
+ Function *Caller = CB->getCaller();
|
|
+ return FunctionLevels[Caller];
|
|
+}
|
|
+#endif
|
|
+
|
|
InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM,
|
|
std::optional<InlineContext> IC)
|
|
: M(M), FAM(FAM), IC(IC),
|
|
@@ -548,6 +607,35 @@ InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM,
|
|
std::make_unique<ImportedFunctionsInliningStatistics>();
|
|
ImportedFunctionsStats->setModuleInfo(M);
|
|
}
|
|
+#if defined(ENABLE_ACPO)
|
|
+ std::unique_ptr<CallGraph> CG(std::make_unique<CallGraph>(M));
|
|
+ for (auto I = scc_begin(CG.get()); !I.isAtEnd(); ++I) {
|
|
+ const std::vector<CallGraphNode *> &CGNodes = *I;
|
|
+ unsigned Level = 0;
|
|
+ for (auto *CGNode : CGNodes) {
|
|
+ Function *F = CGNode->getFunction();
|
|
+ if (!F || F->isDeclaration())
|
|
+ continue;
|
|
+ for (auto &I : instructions(F)) {
|
|
+ if (auto *CS = getInlinableCS(I)) {
|
|
+ auto *Called = CS->getCalledFunction();
|
|
+ auto Pos = FunctionLevels.find(Called);
|
|
+ // In bottom up traversal, an inlinable callee is either in the
|
|
+ // same SCC, or to a function in a visited SCC. So not finding its
|
|
+ // level means we haven't visited it yet, meaning it's in this SCC.
|
|
+ if (Pos == FunctionLevels.end())
|
|
+ continue;
|
|
+ Level = std::max(Level, Pos->second + 1);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ for (auto *CGNode : CGNodes) {
|
|
+ Function *F = CGNode->getFunction();
|
|
+ if (F && !F->isDeclaration())
|
|
+ FunctionLevels[F] = Level;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
}
|
|
|
|
InlineAdvisor::~InlineAdvisor() {
|
|
@@ -639,6 +727,33 @@ std::unique_ptr<InlineAdvice> InlineAdvisor::getAdvice(CallBase &CB,
|
|
return getMandatoryAdvice(CB, Advice);
|
|
}
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+bool InlineAdvisor::neverInline(CallBase &CB) const {
|
|
+ auto &Caller = *CB.getCaller();
|
|
+ auto &Callee = *CB.getCalledFunction();
|
|
+ auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller);
|
|
+ auto MandatoryKind = InlineAdvisor::getMandatoryKind(CB, FAM, ORE);
|
|
+ // If this is a "never inline" case, there won't be any changes to internal
|
|
+ // state we need to track, so we can just return the base InlineAdvice,
|
|
+ // which will do nothing interesting. Same thing if this is a recursive
|
|
+ // case.
|
|
+ return MandatoryKind == InlineAdvisor::MandatoryInliningKind::Never ||
|
|
+ &Caller == &Callee;
|
|
+}
|
|
+
|
|
+bool InlineAdvisor::isCSInlinable(CallBase &CB) const {
|
|
+ auto &Callee = *CB.getCalledFunction();
|
|
+
|
|
+ auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
|
|
+ return FAM.getResult<AssumptionAnalysis>(F);
|
|
+ };
|
|
+ auto &TIR = FAM.getResult<TargetIRAnalysis>(Callee);
|
|
+ auto IsCallSiteInlinable =
|
|
+ llvm::getInliningCostEstimate(CB, TIR, GetAssumptionCache);
|
|
+ return !!IsCallSiteInlinable;
|
|
+}
|
|
+#endif
|
|
+
|
|
OptimizationRemarkEmitter &InlineAdvisor::getCallerORE(CallBase &CB) {
|
|
return FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller());
|
|
}
|
|
diff --git a/llvm/lib/Analysis/MLInlineAdvisor.cpp b/llvm/lib/Analysis/MLInlineAdvisor.cpp
|
|
index 0660a9993b6d..c7ea2eb8ffe9 100644
|
|
--- a/llvm/lib/Analysis/MLInlineAdvisor.cpp
|
|
+++ b/llvm/lib/Analysis/MLInlineAdvisor.cpp
|
|
@@ -323,6 +323,11 @@ std::unique_ptr<InlineAdvice> MLInlineAdvisor::getAdviceImpl(CallBase &CB) {
|
|
auto &Caller = *CB.getCaller();
|
|
auto &Callee = *CB.getCalledFunction();
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+ LLVM_DEBUG(dbgs() << "Advice on call: " << Caller.getName() << " to "
|
|
+ << Callee.getName() << "\n");
|
|
+#endif
|
|
+
|
|
auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
|
|
return FAM.getResult<AssumptionAnalysis>(F);
|
|
};
|
|
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
|
|
index a02c603a14a5..370b248c2b85 100644
|
|
--- a/llvm/lib/IR/AsmWriter.cpp
|
|
+++ b/llvm/lib/IR/AsmWriter.cpp
|
|
@@ -86,15 +86,19 @@
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
#include "llvm/ADT/StringSet.h"
|
|
#include "llvm/Analysis/LoopInfo.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
+#endif
|
|
|
|
using namespace llvm;
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
cl::opt<std::string> UnnamedVariablePrefix(
|
|
"unnamed-var-prefix", cl::Hidden,
|
|
cl::desc("Specify the prefix added to unnamed variables"), cl::init(""));
|
|
+#endif
|
|
|
|
// Make virtual table appear in this compilation unit.
|
|
AssemblyAnnotationWriter::~AssemblyAnnotationWriter() = default;
|
|
@@ -2494,12 +2498,17 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
|
|
} else {
|
|
Slot = -1;
|
|
}
|
|
-
|
|
+#if defined(ENABLE_ACPO)
|
|
if (Slot != -1) {
|
|
// By default, UnnamedVariablePrefix is empty so it matches original behaviour
|
|
// unless specified.
|
|
Out << Prefix << UnnamedVariablePrefix << Slot;
|
|
} else
|
|
+#else
|
|
+ if (Slot != -1)
|
|
+ Out << Prefix << Slot;
|
|
+ else
|
|
+#endif
|
|
Out << "<badref>";
|
|
}
|
|
|
|
@@ -2635,7 +2644,11 @@ public:
|
|
SmallVector<BasicBlock *, 8> ExitBlocks);
|
|
#endif
|
|
void printArgument(const Argument *FA, AttributeSet Attrs);
|
|
+#if defined(ENABLE_ACPO)
|
|
void printBasicBlock(const BasicBlock *BB, bool PrintLabelOnly = false);
|
|
+#else
|
|
+ void printBasicBlock(const BasicBlock *BB);
|
|
+#endif
|
|
void printInstructionLine(const Instruction &I);
|
|
void printInstruction(const Instruction &I);
|
|
|
|
@@ -4214,17 +4227,27 @@ void AssemblyWriter::printArgument(const Argument *Arg, AttributeSet Attrs) {
|
|
} else {
|
|
int Slot = Machine.getLocalSlot(Arg);
|
|
assert(Slot != -1 && "expect argument in function here");
|
|
+#if defined(ENABLE_ACPO)
|
|
// By default, UnnamedVariablePrefix is empty so it matches original behaviour
|
|
// unless specified.
|
|
Out << " %" << UnnamedVariablePrefix << Slot;
|
|
+#else
|
|
+ Out << " %" << Slot;
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
+
|
|
/// printBasicBlock - This member is called for each basic block in a method.
|
|
+#if defined(ENABLE_ACPO)
|
|
void AssemblyWriter::printBasicBlock(const BasicBlock *BB,
|
|
bool PrintLabelOnly) {
|
|
assert(BB && BB->getParent() && "block without parent!");
|
|
bool IsEntryBlock = BB == &BB->getParent()->getEntryBlock();
|
|
+#else
|
|
+void AssemblyWriter::printBasicBlock(const BasicBlock *BB) {
|
|
+ bool IsEntryBlock = BB == &BB->getParent()->getEntryBlock();
|
|
+#endif
|
|
if (BB->hasName()) { // Print out the label if it exists...
|
|
Out << "\n";
|
|
PrintLLVMName(Out, BB->getName(), LabelPrefix);
|
|
@@ -4233,17 +4256,23 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB,
|
|
Out << "\n";
|
|
int Slot = Machine.getLocalSlot(BB);
|
|
if (Slot != -1) {
|
|
+#if defined(ENABLE_ACPO)
|
|
// By default, UnnamedVariablePrefix is empty so it matches original behaviour
|
|
// unless specified.
|
|
Out << UnnamedVariablePrefix << Slot << ":";
|
|
+#else
|
|
+ Out << Slot << ":";
|
|
+#endif
|
|
} else
|
|
Out << "<badref>:";
|
|
}
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
if (PrintLabelOnly) {
|
|
Out << "\n";
|
|
return;
|
|
}
|
|
+#endif
|
|
|
|
if (!IsEntryBlock) {
|
|
// Output predecessors for the block.
|
|
@@ -4339,9 +4368,13 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
|
|
if (SlotNum == -1)
|
|
Out << "<badref> = ";
|
|
else {
|
|
+#if defined(ENABLE_ACPO)
|
|
// By default, UnnamedVariablePrefix is empty so it matches original behaviour
|
|
// unless specified.
|
|
Out << '%' << UnnamedVariablePrefix << SlotNum << " = ";
|
|
+#else
|
|
+ Out << '%' << SlotNum << " = ";
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp
|
|
index 802667819c44..3a0a2494c36a 100644
|
|
--- a/llvm/lib/Transforms/IPO/Inliner.cpp
|
|
+++ b/llvm/lib/Transforms/IPO/Inliner.cpp
|
|
@@ -64,10 +64,21 @@
|
|
#include <functional>
|
|
#include <utility>
|
|
#include <vector>
|
|
-#if defined(ENABLE_AUTOTUNER)
|
|
+#if defined(ENABLE_AUTOTUNER) || defined(ENABLE_ACPO)
|
|
#include "llvm/AutoTuner/AutoTuning.h"
|
|
#endif
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+#include "llvm/Analysis/ACPOFIModel.h"
|
|
+#include "llvm/Analysis/ModelDataCollector.h"
|
|
+#include "llvm/IR/IRPrintingPasses.h"
|
|
+#include "llvm/Support/FormattedStream.h"
|
|
+#include "llvm/Support/raw_ostream.h"
|
|
+#include "llvm/Transforms/IPO.h"
|
|
+#include "llvm/Transforms/Utils/CallGraphUpdater.h"
|
|
+#include <optional>
|
|
+#endif
|
|
+
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "inline"
|
|
@@ -149,6 +160,124 @@ static cl::opt<CallSiteFormat::Format> CGSCCInlineReplayFormat(
|
|
"<Line Number>:<Column Number>.<Discriminator> (default)")),
|
|
cl::desc("How cgscc inline replay file is formatted"), cl::Hidden);
|
|
|
|
+#if defined(ENABLE_ACPO)
|
|
+static cl::opt<bool>
|
|
+ ACPOVerboseFI("acpo-verbose-fi", cl::init(false), cl::Hidden,
|
|
+ cl::desc("Print ACPO invocation messages for FI."));
|
|
+
|
|
+static cl::opt<bool> FeatureDump("enable-fi-feature-dump", cl::init(false));
|
|
+
|
|
+// Defined in 'lib/Analysis/ACPOFIModel.cpp'
|
|
+extern cl::opt<bool> EnableACPOFI;
|
|
+extern cl::opt<bool> EnableAOTFI;
|
|
+// In "llvm/lib/Analysis/ModelDataCollector.cpp"
|
|
+extern cl::opt<std::string> ACPOModelFile;
|
|
+
|
|
+namespace {
|
|
+/// Class for collecting inlining model data
|
|
+class ModelDataFICollector : public ModelDataCollector {
|
|
+public:
|
|
+ ModelDataFICollector(formatted_raw_ostream &OS, bool OnlyMandatory,
|
|
+ std::string OutputFileName)
|
|
+ : ModelDataCollector(OS, OutputFileName), OnlyMandatory(OnlyMandatory) {}
|
|
+
|
|
+ void collectFeatures(CallBase *CB, InlineAdvisor *IA,
|
|
+ FunctionAnalysisManager *FAM) {
|
|
+ bool MandatoryOnly = getOnlyMandatory();
|
|
+ resetRegisteredFeatures();
|
|
+ ACPOCollectFeatures::FeaturesInfo CallerFeatures{
|
|
+ {ACPOCollectFeatures::FeatureIndex::BasicBlockCount,
|
|
+ /* ACPOCollectFeatures::Scope::Function, */
|
|
+ /* ACPOCollectFeatures::GroupID::FPIRelated, */
|
|
+ {FAM, nullptr},
|
|
+ {CB->getCaller(), nullptr, nullptr, nullptr, nullptr},
|
|
+ {MandatoryOnly, IA}}};
|
|
+ ACPOCollectFeatures::FeaturesInfo CalleeFeatures{
|
|
+ {ACPOCollectFeatures::FeatureIndex::BasicBlockCount,
|
|
+ /* ACPOCollectFeatures::Scope::Function, */
|
|
+ /* ACPOCollectFeatures::GroupID::FPIRelated, */
|
|
+ {FAM, nullptr},
|
|
+ {CB->getCalledFunction(), nullptr, nullptr, nullptr, nullptr},
|
|
+ {MandatoryOnly, IA}}};
|
|
+ BasicBlock *GlobalBB = CB->getParent();
|
|
+ Function *GlobalF = GlobalBB->getParent();
|
|
+ Module *GlobalM = GlobalF->getParent();
|
|
+ ACPOCollectFeatures::FeatureInfo GlobalFeatureInfo{
|
|
+ ACPOCollectFeatures::FeatureIndex::NumOfFeatures,
|
|
+ {FAM, nullptr},
|
|
+ {GlobalF, CB, GlobalBB, GlobalM, nullptr},
|
|
+ {MandatoryOnly, IA}};
|
|
+ ACPOCollectFeatures::FeatureInfo CallerInfo{
|
|
+ ACPOCollectFeatures::FeatureIndex::NumOfFeatures,
|
|
+ {FAM, nullptr},
|
|
+ {CB->getCaller(), CB, GlobalBB, GlobalM, nullptr},
|
|
+ {MandatoryOnly, IA}};
|
|
+ ACPOCollectFeatures::FeatureInfo CalleeInfo{
|
|
+ ACPOCollectFeatures::FeatureIndex::NumOfFeatures,
|
|
+ {FAM, nullptr},
|
|
+ {CB->getCalledFunction(), CB, GlobalBB, GlobalM, nullptr},
|
|
+ {MandatoryOnly, IA}};
|
|
+
|
|
+ registerFeature({ACPOCollectFeatures::Scope::Function}, CalleeInfo,
|
|
+ "callee");
|
|
+ registerFeature({ACPOCollectFeatures::Scope::Function}, CallerInfo,
|
|
+ "caller");
|
|
+ registerFeature({ACPOCollectFeatures::Scope::CallSite}, GlobalFeatureInfo);
|
|
+ registerFeature({ACPOCollectFeatures::Scope::Module}, GlobalFeatureInfo);
|
|
+ ModelDataCollector::collectFeatures();
|
|
+ }
|
|
+ bool getOnlyMandatory() { return OnlyMandatory; }
|
|
+
|
|
+private:
|
|
+ bool OnlyMandatory = false;
|
|
+};
|
|
+
|
|
+llvm::SmallDenseSet<std::pair<CallGraphNode *, CallGraphSCC *>, 4>
|
|
+ InlinedInternalEdges =
|
|
+ llvm::SmallDenseSet<std::pair<CallGraphNode *, CallGraphSCC *>, 4>();
|
|
+} // end anonymous namespace
|
|
+
|
|
+/// helper function for getting advice with acpo infrastructure
|
|
+bool getACPOAdvice(CallBase *CB, std::unique_ptr<ACPOFIModel> &FI,
|
|
+ ModelDataFICollector *MDC, InlineAdvisor *Advisor,
|
|
+ FunctionAnalysisManager *FAM) {
|
|
+ bool ShouldInline = false;
|
|
+ // ------------------------------------------------------------------------
|
|
+ // Begin ACPO invocation
|
|
+ if ((EnableACPOFI || EnableAOTFI) && !MDC->getOnlyMandatory() &&
|
|
+ !Advisor->neverInline(*CB) && Advisor->isCSInlinable(*CB)) {
|
|
+ if (ACPOVerboseFI) {
|
|
+ errs() << "--- ACPOModel is activated\n";
|
|
+ }
|
|
+ MDC->collectFeatures(CB, Advisor, FAM);
|
|
+ std::vector<std::pair<std::string, std::string>> Features =
|
|
+ MDC->getFeatures();
|
|
+ FI->setMLCustomFeatures(Features);
|
|
+ }
|
|
+ std::unique_ptr<ACPOAdvice> Advice = FI->getAdvice();
|
|
+ Constant *Val = Advice->getField("FI-ShouldInline");
|
|
+ assert(Val != nullptr);
|
|
+ assert(isa<ConstantInt>(Val));
|
|
+ ConstantInt *ACPOInline = dyn_cast<ConstantInt>(Val);
|
|
+ ShouldInline = ACPOInline->getSExtValue();
|
|
+ if ((EnableACPOFI || EnableAOTFI) && ACPOVerboseFI) {
|
|
+ errs() << "ACPOModel's inline prediction: " << ShouldInline << "\n";
|
|
+ }
|
|
+ if (FeatureDump) {
|
|
+ MDC->collectFeatures(CB, Advisor, FAM);
|
|
+ std::vector<std::pair<std::string, std::string>> Features =
|
|
+ MDC->getFeatures();
|
|
+ if (MDC->isEmptyOutputFile()) {
|
|
+ MDC->printRow(true);
|
|
+ }
|
|
+ MDC->printRow();
|
|
+ }
|
|
+ return ShouldInline;
|
|
+ // End ACPO Invocation
|
|
+ // ---------------------------------------------------------------------
|
|
+}
|
|
+#endif
|
|
+
|
|
/// Return true if the specified inline history ID
|
|
/// indicates an inline history that includes the specified function.
|
|
static bool inlineHistoryIncludes(
|
|
@@ -205,6 +334,14 @@ InlinerPass::getAdvisor(const ModuleAnalysisManagerCGSCCProxy::Result &MAM,
|
|
PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
|
CGSCCAnalysisManager &AM, LazyCallGraph &CG,
|
|
CGSCCUpdateResult &UR) {
|
|
+#if defined(ENABLE_ACPO)
|
|
+ if (EnableACPOFI || EnableAOTFI) {
|
|
+ // Need to clear the cache at the beggining of the inliner pass, since during
|
|
+ // optimization we may have transofrmed the code which invalidated the cache.
|
|
+ ACPOFIModel::clearCache();
|
|
+ }
|
|
+#endif
|
|
+
|
|
const auto &MAMProxy =
|
|
AM.getResult<ModuleAnalysisManagerCGSCCProxy>(InitialC, CG);
|
|
bool Changed = false;
|
|
@@ -221,6 +358,10 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
|
Advisor.onPassEntry(&InitialC);
|
|
|
|
auto AdvisorOnExit = make_scope_exit([&] { Advisor.onPassExit(&InitialC); });
|
|
+#if defined(ENABLE_ACPO)
|
|
+ if (EnableACPOFI || EnableAOTFI)
|
|
+ ACPOCollectFeatures::clearFunctionLevel();
|
|
+#endif
|
|
|
|
// We use a single common worklist for calls across the entire SCC. We
|
|
// process these in-order and append new calls introduced during inlining to
|
|
@@ -377,8 +518,51 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
|
continue;
|
|
}
|
|
|
|
- std::unique_ptr<InlineAdvice> Advice =
|
|
- Advisor.getAdvice(*CB, OnlyMandatory);
|
|
+ std::unique_ptr<InlineAdvice> Advice = nullptr;
|
|
+ #if defined(ENABLE_ACPO)
|
|
+ std::unique_ptr<ACPOFIModel> FI = nullptr;
|
|
+ if (EnableACPOFI || EnableAOTFI) {
|
|
+ auto &ORE =
|
|
+ FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB->getCaller());
|
|
+ FI = std::make_unique<ACPOFIModel>(
|
|
+ CB, &Advisor, &ORE, OnlyMandatory, EnableACPOFI || EnableAOTFI);
|
|
+ std::error_code EC;
|
|
+ raw_fd_ostream RawOS(ACPOModelFile.getValue(), EC, sys::fs::CD_OpenAlways,
|
|
+ sys::fs::FA_Write, sys::fs::OF_Append);
|
|
+ if (EC)
|
|
+ errs() << "Could not create/open training data file (Falling back to "
|
|
+ "debug mode): "
|
|
+ << EC.message() << "\n";
|
|
+
|
|
+ formatted_raw_ostream OS(RawOS);
|
|
+ ModelDataFICollector MDC(OS, OnlyMandatory, ACPOModelFile);
|
|
+ if (EnableACPOFI)
|
|
+ LLVM_DEBUG(dbgs() << "ACPO Python ML infra is activated" << "\n");
|
|
+ else if (EnableAOTFI)
|
|
+ LLVM_DEBUG(dbgs() << "ACPO AOT C++ ML infra is activated" << "\n");
|
|
+ bool ShouldInline = getACPOAdvice(CB, FI, &MDC, &Advisor, &FAM);
|
|
+
|
|
+ // Check whether we want to inline this callsite.
|
|
+ if (!ShouldInline) {
|
|
+ FI->recordUnattemptedInlining();
|
|
+ continue;
|
|
+ } else {
|
|
+ ACPOFIModel::invalidateCache(CB);
|
|
+ }
|
|
+ } else {
|
|
+ Advice = Advisor.getAdvice(*CB, OnlyMandatory);
|
|
+
|
|
+ // Check whether we want to inline this callsite.
|
|
+ if (!Advice)
|
|
+ continue;
|
|
+
|
|
+ if (!Advice->isInliningRecommended()) {
|
|
+ Advice->recordUnattemptedInlining();
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+#else
|
|
+ Advice = Advisor.getAdvice(*CB, OnlyMandatory);
|
|
|
|
// Check whether we want to inline this callsite.
|
|
if (!Advice)
|
|
@@ -388,6 +572,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
|
Advice->recordUnattemptedInlining();
|
|
continue;
|
|
}
|
|
+#endif
|
|
|
|
int CBCostMult =
|
|
getStringFnAttrAsInt(
|
|
@@ -396,6 +581,13 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
|
|
|
// Setup the data structure used to plumb customization into the
|
|
// `InlineFunction` routine.
|
|
+#if defined(ENABLE_ACPO)
|
|
+ if ((EnableACPOFI || EnableAOTFI) && ACPOVerboseFI) {
|
|
+ Function &F2 = *CB->getCaller();
|
|
+ LLVM_DEBUG(dbgs() << "check: " << F2.getName() << ", "
|
|
+ << Callee.getName() << "\n");
|
|
+ }
|
|
+#endif
|
|
InlineFunctionInfo IFI(
|
|
GetAssumptionCache, PSI,
|
|
&FAM.getResult<BlockFrequencyAnalysis>(*(CB->getCaller())),
|
|
@@ -405,7 +597,14 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
|
InlineFunction(*CB, IFI, /*MergeAttributes=*/true,
|
|
&FAM.getResult<AAManager>(*CB->getCaller()));
|
|
if (!IR.isSuccess()) {
|
|
+#if defined(ENABLE_ACPO)
|
|
+ if (EnableACPOFI || EnableAOTFI)
|
|
+ FI->recordUnsuccessfulInlining(IR);
|
|
+ else
|
|
+ Advice->recordUnsuccessfulInlining(IR);
|
|
+#else
|
|
Advice->recordUnsuccessfulInlining(IR);
|
|
+#endif
|
|
continue;
|
|
}
|
|
|
|
@@ -494,10 +693,24 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
|
DeadFunctionsInComdats.push_back(&Callee);
|
|
}
|
|
}
|
|
+#if defined(ENABLE_ACPO)
|
|
+ if (EnableACPOFI || EnableAOTFI) {
|
|
+ if (CalleeWasDeleted)
|
|
+ FI->recordInliningWithCalleeDeleted();
|
|
+ else
|
|
+ FI->recordInlining();
|
|
+ } else {
|
|
+ if (CalleeWasDeleted)
|
|
+ Advice->recordInliningWithCalleeDeleted();
|
|
+ else
|
|
+ Advice->recordInlining();
|
|
+ }
|
|
+#else
|
|
if (CalleeWasDeleted)
|
|
Advice->recordInliningWithCalleeDeleted();
|
|
else
|
|
Advice->recordInlining();
|
|
+#endif
|
|
}
|
|
|
|
// Back the call index up by one to put us in a good position to go around
|
|
diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp
|
|
index 1401352647cd..671a33309a1b 100644
|
|
--- a/llvm/tools/opt/opt.cpp
|
|
+++ b/llvm/tools/opt/opt.cpp
|
|
@@ -430,6 +430,9 @@ int main(int argc, char **argv) {
|
|
initializeTransformUtils(Registry);
|
|
initializeInstCombine(Registry);
|
|
initializeTarget(Registry);
|
|
+#if defined(ENABLE_ACPO)
|
|
+ initializeDumpCallsiteLegacyPass(Registry);
|
|
+#endif
|
|
// For codegen passes, only passes that do IR to IR transformation are
|
|
// supported.
|
|
initializeExpandLargeDivRemLegacyPassPass(Registry);
|
|
--
|
|
2.38.1.windows.1
|
|
|