xref: /llvm-project/llvm/unittests/CodeGen/RegAllocScoreTest.cpp (revision bb3f5e1fed7c6ba733b7f273e93f5d3930976185)
1fa99cb64SMircea Trofin //===- MachineInstrTest.cpp -----------------------------------------------===//
2fa99cb64SMircea Trofin //
3fa99cb64SMircea Trofin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fa99cb64SMircea Trofin // See https://llvm.org/LICENSE.txt for license information.
5fa99cb64SMircea Trofin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fa99cb64SMircea Trofin //
7fa99cb64SMircea Trofin //===----------------------------------------------------------------------===//
8fa99cb64SMircea Trofin 
9fa99cb64SMircea Trofin #include "../lib/CodeGen/RegAllocScore.h"
10*bb3f5e1fSMatin Raayai #include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
11fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineBasicBlock.h"
12fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineFunction.h"
13fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineInstr.h"
14fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineMemOperand.h"
15fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineModuleInfo.h"
16fa99cb64SMircea Trofin #include "llvm/CodeGen/TargetFrameLowering.h"
17fa99cb64SMircea Trofin #include "llvm/CodeGen/TargetInstrInfo.h"
18fa99cb64SMircea Trofin #include "llvm/CodeGen/TargetLowering.h"
19fa99cb64SMircea Trofin #include "llvm/CodeGen/TargetSubtargetInfo.h"
20fa99cb64SMircea Trofin #include "llvm/IR/DebugInfoMetadata.h"
21fa99cb64SMircea Trofin #include "llvm/IR/IRBuilder.h"
2274deadf1SNikita Popov #include "llvm/IR/Module.h"
23fa99cb64SMircea Trofin #include "llvm/IR/ModuleSlotTracker.h"
24fa99cb64SMircea Trofin #include "llvm/MC/MCAsmInfo.h"
25fa99cb64SMircea Trofin #include "llvm/MC/MCSymbol.h"
26fa99cb64SMircea Trofin #include "llvm/MC/TargetRegistry.h"
27fa99cb64SMircea Trofin #include "llvm/Support/TargetSelect.h"
28fa99cb64SMircea Trofin #include "llvm/Target/TargetOptions.h"
2962c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h"
30fa99cb64SMircea Trofin #include "gtest/gtest.h"
31fa99cb64SMircea Trofin 
32fa99cb64SMircea Trofin using namespace llvm;
33fa99cb64SMircea Trofin extern cl::opt<double> CopyWeight;
34fa99cb64SMircea Trofin extern cl::opt<double> LoadWeight;
35fa99cb64SMircea Trofin extern cl::opt<double> StoreWeight;
36fa99cb64SMircea Trofin extern cl::opt<double> CheapRematWeight;
37fa99cb64SMircea Trofin extern cl::opt<double> ExpensiveRematWeight;
38fa99cb64SMircea Trofin 
39fa99cb64SMircea Trofin namespace {
40fa99cb64SMircea Trofin // Include helper functions to ease the manipulation of MachineFunctions.
41fa99cb64SMircea Trofin #include "MFCommon.inc"
42fa99cb64SMircea Trofin 
43fa99cb64SMircea Trofin // MachineFunction::CreateMachineInstr doesn't copy the MCInstrDesc, it
44fa99cb64SMircea Trofin // takes its address. So we want a bunch of pre-allocated mock MCInstrDescs.
45fa99cb64SMircea Trofin #define MOCK_INSTR(MACRO)                                                      \
46fa99cb64SMircea Trofin   MACRO(Copy, TargetOpcode::COPY, 0)                                           \
47fa99cb64SMircea Trofin   MACRO(Load, 0, 1ULL << MCID::MayLoad)                                        \
48fa99cb64SMircea Trofin   MACRO(Store, 0, 1ULL << MCID::MayStore)                                      \
49fa99cb64SMircea Trofin   MACRO(LoadStore, 0, (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore))      \
50fa99cb64SMircea Trofin   MACRO(CheapRemat, 0, 1ULL << MCID::CheapAsAMove)                             \
51fa99cb64SMircea Trofin   MACRO(ExpensiveRemat, 0, 0)                                                  \
52fa99cb64SMircea Trofin   MACRO(Dbg, TargetOpcode::DBG_LABEL,                                          \
53fa99cb64SMircea Trofin         (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore))                    \
54fa99cb64SMircea Trofin   MACRO(InlAsm, TargetOpcode::INLINEASM,                                       \
55fa99cb64SMircea Trofin         (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore))                    \
56fa99cb64SMircea Trofin   MACRO(Kill, TargetOpcode::KILL,                                              \
57fa99cb64SMircea Trofin         (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore))
58fa99cb64SMircea Trofin 
59fa99cb64SMircea Trofin enum MockInstrId {
60fa99cb64SMircea Trofin #define MOCK_INSTR_ID(ID, IGNORE, IGNORE2) ID,
61fa99cb64SMircea Trofin   MOCK_INSTR(MOCK_INSTR_ID)
62fa99cb64SMircea Trofin #undef MOCK_INSTR_ID
63fa99cb64SMircea Trofin       TotalMockInstrs
64fa99cb64SMircea Trofin };
65fa99cb64SMircea Trofin 
66fa99cb64SMircea Trofin const std::array<MCInstrDesc, MockInstrId::TotalMockInstrs> MockInstrDescs{{
67fa99cb64SMircea Trofin #define MOCK_SPEC(IGNORE, OPCODE, FLAGS)                                       \
688dcdc37aSJay Foad   {OPCODE, 0, 0, 0, 0, 0, 0, 0, 0, FLAGS, 0},
69fa99cb64SMircea Trofin     MOCK_INSTR(MOCK_SPEC)
70fa99cb64SMircea Trofin #undef MOCK_SPEC
71fa99cb64SMircea Trofin }};
72fa99cb64SMircea Trofin 
73fa99cb64SMircea Trofin MachineInstr *createMockCopy(MachineFunction &MF) {
74fa99cb64SMircea Trofin   return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Copy], DebugLoc());
75fa99cb64SMircea Trofin }
76fa99cb64SMircea Trofin 
77fa99cb64SMircea Trofin MachineInstr *createMockLoad(MachineFunction &MF) {
78fa99cb64SMircea Trofin   return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Load], DebugLoc());
79fa99cb64SMircea Trofin }
80fa99cb64SMircea Trofin 
81fa99cb64SMircea Trofin MachineInstr *createMockStore(MachineFunction &MF) {
82fa99cb64SMircea Trofin   return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Store], DebugLoc());
83fa99cb64SMircea Trofin }
84fa99cb64SMircea Trofin 
85fa99cb64SMircea Trofin MachineInstr *createMockLoadStore(MachineFunction &MF) {
86fa99cb64SMircea Trofin   return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::LoadStore],
87fa99cb64SMircea Trofin                                DebugLoc());
88fa99cb64SMircea Trofin }
89fa99cb64SMircea Trofin 
90fa99cb64SMircea Trofin MachineInstr *createMockCheapRemat(MachineFunction &MF) {
91fa99cb64SMircea Trofin   return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::CheapRemat],
92fa99cb64SMircea Trofin                                DebugLoc());
93fa99cb64SMircea Trofin }
94fa99cb64SMircea Trofin 
95fa99cb64SMircea Trofin MachineInstr *createMockExpensiveRemat(MachineFunction &MF) {
96fa99cb64SMircea Trofin   return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::ExpensiveRemat],
97fa99cb64SMircea Trofin                                DebugLoc());
98fa99cb64SMircea Trofin }
99fa99cb64SMircea Trofin 
100fa99cb64SMircea Trofin MachineInstr *createMockDebug(MachineFunction &MF) {
101fa99cb64SMircea Trofin   return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Dbg], DebugLoc());
102fa99cb64SMircea Trofin }
103fa99cb64SMircea Trofin 
104fa99cb64SMircea Trofin MachineInstr *createMockKill(MachineFunction &MF) {
105fa99cb64SMircea Trofin   return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Kill], DebugLoc());
106fa99cb64SMircea Trofin }
107fa99cb64SMircea Trofin 
108fa99cb64SMircea Trofin MachineInstr *createMockInlineAsm(MachineFunction &MF) {
109fa99cb64SMircea Trofin   return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::InlAsm], DebugLoc());
110fa99cb64SMircea Trofin }
111fa99cb64SMircea Trofin 
112fa99cb64SMircea Trofin TEST(RegAllocScoreTest, SkipDebugKillInlineAsm) {
113fa99cb64SMircea Trofin   LLVMContext Ctx;
114fa99cb64SMircea Trofin   Module Mod("Module", Ctx);
115fa99cb64SMircea Trofin   auto MF = createMachineFunction(Ctx, Mod);
116fa99cb64SMircea Trofin 
117fa99cb64SMircea Trofin   auto *MBB = MF->CreateMachineBasicBlock();
118fa99cb64SMircea Trofin   MF->insert(MF->end(), MBB);
119fa99cb64SMircea Trofin   auto MBBFreqMock = [&](const MachineBasicBlock &_MBB) -> double {
120fa99cb64SMircea Trofin     assert(&_MBB == MBB);
121fa99cb64SMircea Trofin     return 0.5;
122fa99cb64SMircea Trofin   };
123fa99cb64SMircea Trofin   auto Next = MBB->end();
124fa99cb64SMircea Trofin   Next = MBB->insertAfter(Next, createMockInlineAsm(*MF));
125fa99cb64SMircea Trofin   Next = MBB->insertAfter(Next, createMockDebug(*MF));
126fa99cb64SMircea Trofin   Next = MBB->insertAfter(Next, createMockKill(*MF));
127fa99cb64SMircea Trofin   const auto Score = llvm::calculateRegAllocScore(
128fa99cb64SMircea Trofin       *MF, MBBFreqMock, [](const MachineInstr &) { return false; });
129fa99cb64SMircea Trofin   ASSERT_EQ(MF->size(), 1U);
130fa99cb64SMircea Trofin   ASSERT_EQ(Score, RegAllocScore());
131fa99cb64SMircea Trofin }
132fa99cb64SMircea Trofin 
133fa99cb64SMircea Trofin TEST(RegAllocScoreTest, Counts) {
134fa99cb64SMircea Trofin   LLVMContext Ctx;
135fa99cb64SMircea Trofin   Module Mod("Module", Ctx);
136fa99cb64SMircea Trofin   auto MF = createMachineFunction(Ctx, Mod);
137fa99cb64SMircea Trofin 
138fa99cb64SMircea Trofin   auto *MBB1 = MF->CreateMachineBasicBlock();
139fa99cb64SMircea Trofin   auto *MBB2 = MF->CreateMachineBasicBlock();
140fa99cb64SMircea Trofin   MF->insert(MF->end(), MBB1);
141fa99cb64SMircea Trofin   MF->insert(MF->end(), MBB2);
142fa99cb64SMircea Trofin   const double Freq1 = 0.5;
143fa99cb64SMircea Trofin   const double Freq2 = 10.0;
144fa99cb64SMircea Trofin   auto MBBFreqMock = [&](const MachineBasicBlock &MBB) -> double {
145fa99cb64SMircea Trofin     if (&MBB == MBB1)
146fa99cb64SMircea Trofin       return Freq1;
147fa99cb64SMircea Trofin     if (&MBB == MBB2)
148fa99cb64SMircea Trofin       return Freq2;
149fd722c59SSimon Pilgrim     llvm_unreachable("We only created 2 basic blocks");
150fa99cb64SMircea Trofin   };
151fa99cb64SMircea Trofin   auto Next = MBB1->end();
152fa99cb64SMircea Trofin   Next = MBB1->insertAfter(Next, createMockCopy(*MF));
153fa99cb64SMircea Trofin   Next = MBB1->insertAfter(Next, createMockLoad(*MF));
154fa99cb64SMircea Trofin   Next = MBB1->insertAfter(Next, createMockLoad(*MF));
155fa99cb64SMircea Trofin   Next = MBB1->insertAfter(Next, createMockStore(*MF));
156fa99cb64SMircea Trofin   auto *CheapRemat = createMockCheapRemat(*MF);
157fa99cb64SMircea Trofin   MBB1->insertAfter(Next, CheapRemat);
158fa99cb64SMircea Trofin   Next = MBB2->end();
159fa99cb64SMircea Trofin   Next = MBB2->insertAfter(Next, createMockLoad(*MF));
160fa99cb64SMircea Trofin   Next = MBB2->insertAfter(Next, createMockStore(*MF));
161fa99cb64SMircea Trofin   Next = MBB2->insertAfter(Next, createMockLoadStore(*MF));
162fa99cb64SMircea Trofin   auto *ExpensiveRemat = createMockExpensiveRemat(*MF);
163fa99cb64SMircea Trofin   MBB2->insertAfter(Next, ExpensiveRemat);
164fa99cb64SMircea Trofin   auto IsRemat = [&](const MachineInstr &MI) {
165fa99cb64SMircea Trofin     return &MI == CheapRemat || &MI == ExpensiveRemat;
166fa99cb64SMircea Trofin   };
167fa99cb64SMircea Trofin   ASSERT_EQ(MF->size(), 2U);
168fa99cb64SMircea Trofin   const auto TotalScore =
169fa99cb64SMircea Trofin       llvm::calculateRegAllocScore(*MF, MBBFreqMock, IsRemat);
1708cd8ebe1SAiden Grossman   ASSERT_DOUBLE_EQ(Freq1, TotalScore.copyCounts());
1718cd8ebe1SAiden Grossman   ASSERT_DOUBLE_EQ(2.0 * Freq1 + Freq2, TotalScore.loadCounts());
1728cd8ebe1SAiden Grossman   ASSERT_DOUBLE_EQ(Freq1 + Freq2, TotalScore.storeCounts());
1738cd8ebe1SAiden Grossman   ASSERT_DOUBLE_EQ(Freq2, TotalScore.loadStoreCounts());
1748cd8ebe1SAiden Grossman   ASSERT_DOUBLE_EQ(Freq1, TotalScore.cheapRematCounts());
1758cd8ebe1SAiden Grossman   ASSERT_DOUBLE_EQ(Freq2, TotalScore.expensiveRematCounts());
1768cd8ebe1SAiden Grossman   ASSERT_DOUBLE_EQ(
1778cd8ebe1SAiden Grossman       TotalScore.getScore(),
178fa99cb64SMircea Trofin       TotalScore.copyCounts() * CopyWeight +
179fa99cb64SMircea Trofin           TotalScore.loadCounts() * LoadWeight +
180fa99cb64SMircea Trofin           TotalScore.storeCounts() * StoreWeight +
181fa99cb64SMircea Trofin           TotalScore.loadStoreCounts() * (LoadWeight + StoreWeight) +
182fa99cb64SMircea Trofin           TotalScore.cheapRematCounts() * CheapRematWeight +
183fa99cb64SMircea Trofin           TotalScore.expensiveRematCounts() * ExpensiveRematWeight
184fa99cb64SMircea Trofin 
185fa99cb64SMircea Trofin   );
186fa99cb64SMircea Trofin }
187fa99cb64SMircea Trofin } // end namespace
188