1 //===- MachineInstrTest.cpp -----------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "../lib/CodeGen/RegAllocScore.h"
10 #include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
11 #include "llvm/CodeGen/MachineBasicBlock.h"
12 #include "llvm/CodeGen/MachineFunction.h"
13 #include "llvm/CodeGen/MachineInstr.h"
14 #include "llvm/CodeGen/MachineMemOperand.h"
15 #include "llvm/CodeGen/MachineModuleInfo.h"
16 #include "llvm/CodeGen/TargetFrameLowering.h"
17 #include "llvm/CodeGen/TargetInstrInfo.h"
18 #include "llvm/CodeGen/TargetLowering.h"
19 #include "llvm/CodeGen/TargetSubtargetInfo.h"
20 #include "llvm/IR/DebugInfoMetadata.h"
21 #include "llvm/IR/IRBuilder.h"
22 #include "llvm/IR/Module.h"
23 #include "llvm/IR/ModuleSlotTracker.h"
24 #include "llvm/MC/MCAsmInfo.h"
25 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/MC/TargetRegistry.h"
27 #include "llvm/Support/TargetSelect.h"
28 #include "llvm/Target/TargetOptions.h"
29 #include "llvm/TargetParser/Triple.h"
30 #include "gtest/gtest.h"
33 extern cl::opt
<double> CopyWeight
;
34 extern cl::opt
<double> LoadWeight
;
35 extern cl::opt
<double> StoreWeight
;
36 extern cl::opt
<double> CheapRematWeight
;
37 extern cl::opt
<double> ExpensiveRematWeight
;
40 // Include helper functions to ease the manipulation of MachineFunctions.
41 #include "MFCommon.inc"
43 // MachineFunction::CreateMachineInstr doesn't copy the MCInstrDesc, it
44 // takes its address. So we want a bunch of pre-allocated mock MCInstrDescs.
45 #define MOCK_INSTR(MACRO) \
46 MACRO(Copy, TargetOpcode::COPY, 0) \
47 MACRO(Load, 0, 1ULL << MCID::MayLoad) \
48 MACRO(Store, 0, 1ULL << MCID::MayStore) \
49 MACRO(LoadStore, 0, (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) \
50 MACRO(CheapRemat, 0, 1ULL << MCID::CheapAsAMove) \
51 MACRO(ExpensiveRemat, 0, 0) \
52 MACRO(Dbg, TargetOpcode::DBG_LABEL, \
53 (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) \
54 MACRO(InlAsm, TargetOpcode::INLINEASM, \
55 (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) \
56 MACRO(Kill, TargetOpcode::KILL, \
57 (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore))
60 #define MOCK_INSTR_ID(ID, IGNORE, IGNORE2) ID,
61 MOCK_INSTR(MOCK_INSTR_ID
)
66 const std::array
<MCInstrDesc
, MockInstrId::TotalMockInstrs
> MockInstrDescs
{{
67 #define MOCK_SPEC(IGNORE, OPCODE, FLAGS) \
68 {OPCODE, 0, 0, 0, 0, 0, 0, 0, 0, FLAGS, 0},
73 MachineInstr
*createMockCopy(MachineFunction
&MF
) {
74 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Copy
], DebugLoc());
77 MachineInstr
*createMockLoad(MachineFunction
&MF
) {
78 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Load
], DebugLoc());
81 MachineInstr
*createMockStore(MachineFunction
&MF
) {
82 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Store
], DebugLoc());
85 MachineInstr
*createMockLoadStore(MachineFunction
&MF
) {
86 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::LoadStore
],
90 MachineInstr
*createMockCheapRemat(MachineFunction
&MF
) {
91 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::CheapRemat
],
95 MachineInstr
*createMockExpensiveRemat(MachineFunction
&MF
) {
96 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::ExpensiveRemat
],
100 MachineInstr
*createMockDebug(MachineFunction
&MF
) {
101 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Dbg
], DebugLoc());
104 MachineInstr
*createMockKill(MachineFunction
&MF
) {
105 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Kill
], DebugLoc());
108 MachineInstr
*createMockInlineAsm(MachineFunction
&MF
) {
109 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::InlAsm
], DebugLoc());
112 TEST(RegAllocScoreTest
, SkipDebugKillInlineAsm
) {
114 Module
Mod("Module", Ctx
);
115 auto MF
= createMachineFunction(Ctx
, Mod
);
117 auto *MBB
= MF
->CreateMachineBasicBlock();
118 MF
->insert(MF
->end(), MBB
);
119 auto MBBFreqMock
= [&](const MachineBasicBlock
&_MBB
) -> double {
120 assert(&_MBB
== MBB
);
123 auto Next
= MBB
->end();
124 Next
= MBB
->insertAfter(Next
, createMockInlineAsm(*MF
));
125 Next
= MBB
->insertAfter(Next
, createMockDebug(*MF
));
126 Next
= MBB
->insertAfter(Next
, createMockKill(*MF
));
127 const auto Score
= llvm::calculateRegAllocScore(
128 *MF
, MBBFreqMock
, [](const MachineInstr
&) { return false; });
129 ASSERT_EQ(MF
->size(), 1U);
130 ASSERT_EQ(Score
, RegAllocScore());
133 TEST(RegAllocScoreTest
, Counts
) {
135 Module
Mod("Module", Ctx
);
136 auto MF
= createMachineFunction(Ctx
, Mod
);
138 auto *MBB1
= MF
->CreateMachineBasicBlock();
139 auto *MBB2
= MF
->CreateMachineBasicBlock();
140 MF
->insert(MF
->end(), MBB1
);
141 MF
->insert(MF
->end(), MBB2
);
142 const double Freq1
= 0.5;
143 const double Freq2
= 10.0;
144 auto MBBFreqMock
= [&](const MachineBasicBlock
&MBB
) -> double {
149 llvm_unreachable("We only created 2 basic blocks");
151 auto Next
= MBB1
->end();
152 Next
= MBB1
->insertAfter(Next
, createMockCopy(*MF
));
153 Next
= MBB1
->insertAfter(Next
, createMockLoad(*MF
));
154 Next
= MBB1
->insertAfter(Next
, createMockLoad(*MF
));
155 Next
= MBB1
->insertAfter(Next
, createMockStore(*MF
));
156 auto *CheapRemat
= createMockCheapRemat(*MF
);
157 MBB1
->insertAfter(Next
, CheapRemat
);
159 Next
= MBB2
->insertAfter(Next
, createMockLoad(*MF
));
160 Next
= MBB2
->insertAfter(Next
, createMockStore(*MF
));
161 Next
= MBB2
->insertAfter(Next
, createMockLoadStore(*MF
));
162 auto *ExpensiveRemat
= createMockExpensiveRemat(*MF
);
163 MBB2
->insertAfter(Next
, ExpensiveRemat
);
164 auto IsRemat
= [&](const MachineInstr
&MI
) {
165 return &MI
== CheapRemat
|| &MI
== ExpensiveRemat
;
167 ASSERT_EQ(MF
->size(), 2U);
168 const auto TotalScore
=
169 llvm::calculateRegAllocScore(*MF
, MBBFreqMock
, IsRemat
);
170 ASSERT_DOUBLE_EQ(Freq1
, TotalScore
.copyCounts());
171 ASSERT_DOUBLE_EQ(2.0 * Freq1
+ Freq2
, TotalScore
.loadCounts());
172 ASSERT_DOUBLE_EQ(Freq1
+ Freq2
, TotalScore
.storeCounts());
173 ASSERT_DOUBLE_EQ(Freq2
, TotalScore
.loadStoreCounts());
174 ASSERT_DOUBLE_EQ(Freq1
, TotalScore
.cheapRematCounts());
175 ASSERT_DOUBLE_EQ(Freq2
, TotalScore
.expensiveRematCounts());
177 TotalScore
.getScore(),
178 TotalScore
.copyCounts() * CopyWeight
+
179 TotalScore
.loadCounts() * LoadWeight
+
180 TotalScore
.storeCounts() * StoreWeight
+
181 TotalScore
.loadStoreCounts() * (LoadWeight
+ StoreWeight
) +
182 TotalScore
.cheapRematCounts() * CheapRematWeight
+
183 TotalScore
.expensiveRematCounts() * ExpensiveRematWeight