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/ADT/Triple.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/ModuleSlotTracker.h"
23 #include "llvm/MC/MCAsmInfo.h"
24 #include "llvm/MC/MCSymbol.h"
25 #include "llvm/MC/TargetRegistry.h"
26 #include "llvm/Support/TargetSelect.h"
27 #include "llvm/Target/TargetMachine.h"
28 #include "llvm/Target/TargetOptions.h"
29 #include "gtest/gtest.h"
32 extern cl::opt
<double> CopyWeight
;
33 extern cl::opt
<double> LoadWeight
;
34 extern cl::opt
<double> StoreWeight
;
35 extern cl::opt
<double> CheapRematWeight
;
36 extern cl::opt
<double> ExpensiveRematWeight
;
39 // Include helper functions to ease the manipulation of MachineFunctions.
40 #include "MFCommon.inc"
42 // MachineFunction::CreateMachineInstr doesn't copy the MCInstrDesc, it
43 // takes its address. So we want a bunch of pre-allocated mock MCInstrDescs.
44 #define MOCK_INSTR(MACRO) \
45 MACRO(Copy, TargetOpcode::COPY, 0) \
46 MACRO(Load, 0, 1ULL << MCID::MayLoad) \
47 MACRO(Store, 0, 1ULL << MCID::MayStore) \
48 MACRO(LoadStore, 0, (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) \
49 MACRO(CheapRemat, 0, 1ULL << MCID::CheapAsAMove) \
50 MACRO(ExpensiveRemat, 0, 0) \
51 MACRO(Dbg, TargetOpcode::DBG_LABEL, \
52 (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) \
53 MACRO(InlAsm, TargetOpcode::INLINEASM, \
54 (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) \
55 MACRO(Kill, TargetOpcode::KILL, \
56 (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore))
59 #define MOCK_INSTR_ID(ID, IGNORE, IGNORE2) ID,
60 MOCK_INSTR(MOCK_INSTR_ID
)
65 const std::array
<MCInstrDesc
, MockInstrId::TotalMockInstrs
> MockInstrDescs
{{
66 #define MOCK_SPEC(IGNORE, OPCODE, FLAGS) \
67 {OPCODE, 0, 0, 0, 0, FLAGS, 0, nullptr, nullptr, nullptr},
72 MachineInstr
*createMockCopy(MachineFunction
&MF
) {
73 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Copy
], DebugLoc());
76 MachineInstr
*createMockLoad(MachineFunction
&MF
) {
77 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Load
], DebugLoc());
80 MachineInstr
*createMockStore(MachineFunction
&MF
) {
81 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Store
], DebugLoc());
84 MachineInstr
*createMockLoadStore(MachineFunction
&MF
) {
85 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::LoadStore
],
89 MachineInstr
*createMockCheapRemat(MachineFunction
&MF
) {
90 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::CheapRemat
],
94 MachineInstr
*createMockExpensiveRemat(MachineFunction
&MF
) {
95 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::ExpensiveRemat
],
99 MachineInstr
*createMockDebug(MachineFunction
&MF
) {
100 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Dbg
], DebugLoc());
103 MachineInstr
*createMockKill(MachineFunction
&MF
) {
104 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::Kill
], DebugLoc());
107 MachineInstr
*createMockInlineAsm(MachineFunction
&MF
) {
108 return MF
.CreateMachineInstr(MockInstrDescs
[MockInstrId::InlAsm
], DebugLoc());
111 TEST(RegAllocScoreTest
, SkipDebugKillInlineAsm
) {
113 Module
Mod("Module", Ctx
);
114 auto MF
= createMachineFunction(Ctx
, Mod
);
116 auto *MBB
= MF
->CreateMachineBasicBlock();
117 MF
->insert(MF
->end(), MBB
);
118 auto MBBFreqMock
= [&](const MachineBasicBlock
&_MBB
) -> double {
119 assert(&_MBB
== MBB
);
122 auto Next
= MBB
->end();
123 Next
= MBB
->insertAfter(Next
, createMockInlineAsm(*MF
));
124 Next
= MBB
->insertAfter(Next
, createMockDebug(*MF
));
125 Next
= MBB
->insertAfter(Next
, createMockKill(*MF
));
126 const auto Score
= llvm::calculateRegAllocScore(
127 *MF
, MBBFreqMock
, [](const MachineInstr
&) { return false; });
128 ASSERT_EQ(MF
->size(), 1U);
129 ASSERT_EQ(Score
, RegAllocScore());
132 TEST(RegAllocScoreTest
, Counts
) {
134 Module
Mod("Module", Ctx
);
135 auto MF
= createMachineFunction(Ctx
, Mod
);
137 auto *MBB1
= MF
->CreateMachineBasicBlock();
138 auto *MBB2
= MF
->CreateMachineBasicBlock();
139 MF
->insert(MF
->end(), MBB1
);
140 MF
->insert(MF
->end(), MBB2
);
141 const double Freq1
= 0.5;
142 const double Freq2
= 10.0;
143 auto MBBFreqMock
= [&](const MachineBasicBlock
&MBB
) -> double {
148 llvm_unreachable("We only created 2 basic blocks");
150 auto Next
= MBB1
->end();
151 Next
= MBB1
->insertAfter(Next
, createMockCopy(*MF
));
152 Next
= MBB1
->insertAfter(Next
, createMockLoad(*MF
));
153 Next
= MBB1
->insertAfter(Next
, createMockLoad(*MF
));
154 Next
= MBB1
->insertAfter(Next
, createMockStore(*MF
));
155 auto *CheapRemat
= createMockCheapRemat(*MF
);
156 MBB1
->insertAfter(Next
, CheapRemat
);
158 Next
= MBB2
->insertAfter(Next
, createMockLoad(*MF
));
159 Next
= MBB2
->insertAfter(Next
, createMockStore(*MF
));
160 Next
= MBB2
->insertAfter(Next
, createMockLoadStore(*MF
));
161 auto *ExpensiveRemat
= createMockExpensiveRemat(*MF
);
162 MBB2
->insertAfter(Next
, ExpensiveRemat
);
163 auto IsRemat
= [&](const MachineInstr
&MI
) {
164 return &MI
== CheapRemat
|| &MI
== ExpensiveRemat
;
166 ASSERT_EQ(MF
->size(), 2U);
167 const auto TotalScore
=
168 llvm::calculateRegAllocScore(*MF
, MBBFreqMock
, IsRemat
);
169 ASSERT_EQ(Freq1
, TotalScore
.copyCounts());
170 ASSERT_EQ(2.0 * Freq1
+ Freq2
, TotalScore
.loadCounts());
171 ASSERT_EQ(Freq1
+ Freq2
, TotalScore
.storeCounts());
172 ASSERT_EQ(Freq2
, TotalScore
.loadStoreCounts());
173 ASSERT_EQ(Freq1
, TotalScore
.cheapRematCounts());
174 ASSERT_EQ(Freq2
, TotalScore
.expensiveRematCounts());
175 ASSERT_EQ(TotalScore
.getScore(),
176 TotalScore
.copyCounts() * CopyWeight
+
177 TotalScore
.loadCounts() * LoadWeight
+
178 TotalScore
.storeCounts() * StoreWeight
+
179 TotalScore
.loadStoreCounts() * (LoadWeight
+ StoreWeight
) +
180 TotalScore
.cheapRematCounts() * CheapRematWeight
+
181 TotalScore
.expensiveRematCounts() * ExpensiveRematWeight