[llvm] cc8a346 - [InlineCost][TargetTransformInfo][AMDGPU] Consider cost of alloca instructions in the caller (1/2)
Juan Manuel MARTINEZ CAAMAÑO via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 29 00:51:48 PDT 2023
Author: Juan Manuel MARTINEZ CAAMAÑO
Date: 2023-06-29T09:49:16+02:00
New Revision: cc8a346e3fa362c2b1319cca9883182fbf36b6db
URL: https://github.com/llvm/llvm-project/commit/cc8a346e3fa362c2b1319cca9883182fbf36b6db
DIFF: https://github.com/llvm/llvm-project/commit/cc8a346e3fa362c2b1319cca9883182fbf36b6db.diff
LOG: [InlineCost][TargetTransformInfo][AMDGPU] Consider cost of alloca instructions in the caller (1/2)
On AMDGPU, alloca instructions have penalty that can
be avoided when SROA is applied after inlining.
This patch introduces the default implementation of
TargetTransformInfo::getCallerAllocaCost.
Reviewed By: mtrofin
Differential Revision: https://reviews.llvm.org/D149740
Added:
Modified:
llvm/include/llvm/Analysis/TargetTransformInfo.h
llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
llvm/include/llvm/CodeGen/BasicTTIImpl.h
llvm/lib/Analysis/InlineCost.cpp
llvm/lib/Analysis/TargetTransformInfo.cpp
llvm/unittests/Analysis/InlineCostTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index d39d069d9eb2ad..0b679039ec4ffa 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -39,6 +39,7 @@ namespace Intrinsic {
typedef unsigned ID;
}
+class AllocaInst;
class AssumptionCache;
class BlockFrequencyInfo;
class DominatorTree;
@@ -340,6 +341,10 @@ class TargetTransformInfo {
/// \returns A value to be added to the inlining threshold.
unsigned adjustInliningThreshold(const CallBase *CB) const;
+ /// \returns The cost of having an Alloca in the caller if not inlined, to be
+ /// added to the threshold
+ unsigned getCallerAllocaCost(const CallBase *CB, const AllocaInst *AI) const;
+
/// \returns Vector bonus in percent.
///
/// Vector bonuses: We want to more aggressively inline vector-dense kernels
@@ -1683,6 +1688,8 @@ class TargetTransformInfo::Concept {
virtual unsigned getInliningThresholdMultiplier() const = 0;
virtual unsigned adjustInliningThreshold(const CallBase *CB) = 0;
virtual int getInlinerVectorBonusPercent() const = 0;
+ virtual unsigned getCallerAllocaCost(const CallBase *CB,
+ const AllocaInst *AI) const = 0;
virtual InstructionCost getMemcpyCost(const Instruction *I) = 0;
virtual uint64_t getMaxMemIntrinsicInlineSizeThreshold() const = 0;
virtual unsigned
@@ -2054,6 +2061,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
int getInlinerVectorBonusPercent() const override {
return Impl.getInlinerVectorBonusPercent();
}
+ unsigned getCallerAllocaCost(const CallBase *CB,
+ const AllocaInst *AI) const override {
+ return Impl.getCallerAllocaCost(CB, AI);
+ }
InstructionCost getMemcpyCost(const Instruction *I) override {
return Impl.getMemcpyCost(I);
}
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index 08707ae05c6fc3..a78d187d61a437 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -70,6 +70,9 @@ class TargetTransformInfoImplBase {
unsigned getInliningThresholdMultiplier() const { return 1; }
unsigned adjustInliningThreshold(const CallBase *CB) const { return 0; }
+ unsigned getCallerAllocaCost(const CallBase *CB, const AllocaInst *AI) const {
+ return 0;
+ };
int getInlinerVectorBonusPercent() const { return 150; }
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index f57697da9aaf90..ca7f6d34b66bd1 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -538,6 +538,9 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
unsigned getInliningThresholdMultiplier() const { return 1; }
unsigned adjustInliningThreshold(const CallBase *CB) { return 0; }
+ unsigned getCallerAllocaCost(const CallBase *CB, const AllocaInst *AI) const {
+ return 0;
+ }
int getInlinerVectorBonusPercent() const { return 150; }
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index d887adc336966d..9ff277f5334ece 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -717,7 +717,9 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
void onInitializeSROAArg(AllocaInst *Arg) override {
assert(Arg != nullptr &&
"Should not initialize SROA costs for null value.");
- SROAArgCosts[Arg] = 0;
+ auto SROAArgCost = TTI.getCallerAllocaCost(&CandidateCall, Arg);
+ SROACostSavings += SROAArgCost;
+ SROAArgCosts[Arg] = SROAArgCost;
}
void onAggregateSROAUse(AllocaInst *SROAArg) override {
@@ -1191,7 +1193,12 @@ class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
InstrCost);
}
- void onInitializeSROAArg(AllocaInst *Arg) override { SROACosts[Arg] = 0; }
+ void onInitializeSROAArg(AllocaInst *Arg) override {
+ auto SROAArgCost = TTI.getCallerAllocaCost(&CandidateCall, Arg);
+ SROACosts[Arg] = SROAArgCost;
+ SROACostSavingOpportunities += SROAArgCost;
+ }
+
void onAggregateSROAUse(AllocaInst *Arg) override {
SROACosts.find(Arg)->second += InstrCost;
SROACostSavingOpportunities += InstrCost;
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 4500e0615219ca..435baab3f4424c 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -217,6 +217,11 @@ TargetTransformInfo::adjustInliningThreshold(const CallBase *CB) const {
return TTIImpl->adjustInliningThreshold(CB);
}
+unsigned TargetTransformInfo::getCallerAllocaCost(const CallBase *CB,
+ const AllocaInst *AI) const {
+ return TTIImpl->getCallerAllocaCost(CB, AI);
+}
+
int TargetTransformInfo::getInlinerVectorBonusPercent() const {
return TTIImpl->getInlinerVectorBonusPercent();
}
diff --git a/llvm/unittests/Analysis/InlineCostTest.cpp b/llvm/unittests/Analysis/InlineCostTest.cpp
index ec5f1e022a4638..881c31f05d7e5f 100644
--- a/llvm/unittests/Analysis/InlineCostTest.cpp
+++ b/llvm/unittests/Analysis/InlineCostTest.cpp
@@ -8,8 +8,10 @@
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/InlineModelFeatureMaps.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
@@ -18,10 +20,40 @@
namespace {
+using namespace llvm;
+
+CallBase *getCallInFunction(Function *F) {
+ for (auto &I : instructions(F)) {
+ if (auto *CB = dyn_cast<llvm::CallBase>(&I))
+ return CB;
+ }
+ return nullptr;
+}
+
+std::optional<InlineCostFeatures> getInliningCostFeaturesForCall(CallBase &CB) {
+ ModuleAnalysisManager MAM;
+ FunctionAnalysisManager FAM;
+ FAM.registerPass([&] { return TargetIRAnalysis(); });
+ FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
+ FAM.registerPass([&] { return AssumptionAnalysis(); });
+ MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
+
+ MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
+ FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
+
+ ModulePassManager MPM;
+ MPM.run(*CB.getModule(), MAM);
+
+ auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
+ return FAM.getResult<AssumptionAnalysis>(F);
+ };
+ auto &TIR = FAM.getResult<TargetIRAnalysis>(*CB.getFunction());
+
+ return getInliningCostFeatures(CB, TIR, GetAssumptionCache);
+}
+
// Tests that we can retrieve the CostFeatures without an error
TEST(InlineCostTest, CostFeatures) {
- using namespace llvm;
-
const auto *const IR = R"IR(
define i32 @f(i32) {
ret i32 4
@@ -42,38 +74,80 @@ define i32 @g(i32) {
ASSERT_TRUE(G);
// find the call to f in g
- CallBase *CB = nullptr;
- for (auto &BB : *G) {
- for (auto &I : BB) {
- if ((CB = dyn_cast<CallBase>(&I)))
- break;
- }
- }
+ CallBase *CB = getCallInFunction(G);
ASSERT_TRUE(CB);
- ModuleAnalysisManager MAM;
- FunctionAnalysisManager FAM;
- FAM.registerPass([&] { return TargetIRAnalysis(); });
- FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
- FAM.registerPass([&] { return AssumptionAnalysis(); });
- MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
+ const auto Features = getInliningCostFeaturesForCall(*CB);
- MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
- FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
+ // Check that the optional is not empty
+ ASSERT_TRUE(Features);
+}
- ModulePassManager MPM;
- MPM.run(*M, MAM);
+// Tests the calculated SROA cost
+TEST(InlineCostTest, SROACost) {
+ using namespace llvm;
- auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
- return FAM.getResult<AssumptionAnalysis>(F);
- };
- auto &TIR = FAM.getResult<TargetIRAnalysis>(*G);
+ const auto *const IR = R"IR(
+define void @f_savings(ptr %var) {
+ %load = load i32, ptr %var
+ %inc = add i32 %load, 1
+ store i32 %inc, ptr %var
+ ret void
+}
+
+define void @g_savings(i32) {
+ %var = alloca i32
+ call void @f_savings(ptr %var)
+ ret void
+}
- const auto Features =
- llvm::getInliningCostFeatures(*CB, TIR, GetAssumptionCache);
+define void @f_losses(ptr %var) {
+ %load = load i32, ptr %var
+ %inc = add i32 %load, 1
+ store i32 %inc, ptr %var
+ call void @prevent_sroa(ptr %var)
+ ret void
+}
- // Check that the optional is not empty
- ASSERT_TRUE(Features);
+define void @g_losses(i32) {
+ %var = alloca i32
+ call void @f_losses(ptr %var)
+ ret void
+}
+
+declare void @prevent_sroa(ptr)
+)IR";
+
+ LLVMContext C;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(IR, Err, C);
+ ASSERT_TRUE(M);
+
+ const int DefaultInstCost = 5;
+ const int DefaultAllocaCost = 0;
+
+ const char *GName[] = {"g_savings", "g_losses", nullptr};
+ const int Savings[] = {2 * DefaultInstCost + DefaultAllocaCost, 0};
+ const int Losses[] = {0, 2 * DefaultInstCost + DefaultAllocaCost};
+
+ for (unsigned i = 0; GName[i]; ++i) {
+ auto *G = M->getFunction(GName[i]);
+ ASSERT_TRUE(G);
+
+ // find the call to f in g
+ CallBase *CB = getCallInFunction(G);
+ ASSERT_TRUE(CB);
+
+ const auto Features = getInliningCostFeaturesForCall(*CB);
+ ASSERT_TRUE(Features);
+
+ // Check the predicted SROA cost
+ auto GetFeature = [&](InlineCostFeatureIndex I) {
+ return (*Features)[static_cast<size_t>(I)];
+ };
+ ASSERT_EQ(GetFeature(InlineCostFeatureIndex::sroa_savings), Savings[i]);
+ ASSERT_EQ(GetFeature(InlineCostFeatureIndex::sroa_losses), Losses[i]);
+ }
}
} // namespace
More information about the llvm-commits
mailing list