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 "llvm/CodeGen/MachineBasicBlock.h"
10 #include "llvm/CodeGen/MachineInstr.h"
11 #include "llvm/CodeGen/MachineFunction.h"
12 #include "llvm/CodeGen/MachineModuleInfo.h"
13 #include "llvm/CodeGen/TargetFrameLowering.h"
14 #include "llvm/CodeGen/TargetInstrInfo.h"
15 #include "llvm/CodeGen/TargetLowering.h"
16 #include "llvm/CodeGen/TargetSubtargetInfo.h"
17 #include "llvm/IR/DebugInfoMetadata.h"
18 #include "llvm/IR/ModuleSlotTracker.h"
19 #include "llvm/Support/TargetRegistry.h"
20 #include "llvm/Support/TargetSelect.h"
21 #include "llvm/Target/TargetMachine.h"
22 #include "llvm/Target/TargetOptions.h"
23 #include "gtest/gtest.h"
28 // Add a few Bogus backend classes so we can create MachineInstrs without
29 // depending on a real target.
30 class BogusTargetLowering
: public TargetLowering
{
32 BogusTargetLowering(TargetMachine
&TM
) : TargetLowering(TM
) {}
35 class BogusFrameLowering
: public TargetFrameLowering
{
38 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown
, Align(4), 4) {}
40 void emitPrologue(MachineFunction
&MF
,
41 MachineBasicBlock
&MBB
) const override
{}
42 void emitEpilogue(MachineFunction
&MF
,
43 MachineBasicBlock
&MBB
) const override
{}
44 bool hasFP(const MachineFunction
&MF
) const override
{ return false; }
47 static TargetRegisterClass
*const BogusRegisterClasses
[] = {nullptr};
49 class BogusRegisterInfo
: public TargetRegisterInfo
{
52 : TargetRegisterInfo(nullptr, BogusRegisterClasses
, BogusRegisterClasses
,
53 nullptr, nullptr, LaneBitmask(~0u), nullptr) {
54 InitMCRegisterInfo(nullptr, 0, 0, 0, nullptr, 0, nullptr, 0, nullptr,
55 nullptr, nullptr, nullptr, nullptr, 0, nullptr, nullptr);
59 getCalleeSavedRegs(const MachineFunction
*MF
) const override
{
62 ArrayRef
<const uint32_t *> getRegMasks() const override
{ return None
; }
63 ArrayRef
<const char *> getRegMaskNames() const override
{ return None
; }
64 BitVector
getReservedRegs(const MachineFunction
&MF
) const override
{
67 const RegClassWeight
&
68 getRegClassWeight(const TargetRegisterClass
*RC
) const override
{
69 static RegClassWeight Bogus
{1, 16};
72 unsigned getRegUnitWeight(unsigned RegUnit
) const override
{ return 1; }
73 unsigned getNumRegPressureSets() const override
{ return 0; }
74 const char *getRegPressureSetName(unsigned Idx
) const override
{
77 unsigned getRegPressureSetLimit(const MachineFunction
&MF
,
78 unsigned Idx
) const override
{
82 getRegClassPressureSets(const TargetRegisterClass
*RC
) const override
{
83 static const int Bogus
[] = {0, -1};
86 const int *getRegUnitPressureSets(unsigned RegUnit
) const override
{
87 static const int Bogus
[] = {0, -1};
91 Register
getFrameRegister(const MachineFunction
&MF
) const override
{
94 void eliminateFrameIndex(MachineBasicBlock::iterator MI
, int SPAdj
,
95 unsigned FIOperandNum
,
96 RegScavenger
*RS
= nullptr) const override
{}
99 class BogusSubtarget
: public TargetSubtargetInfo
{
101 BogusSubtarget(TargetMachine
&TM
)
102 : TargetSubtargetInfo(Triple(""), "", "", {}, {}, nullptr, nullptr,
103 nullptr, nullptr, nullptr, nullptr),
105 ~BogusSubtarget() override
{}
107 const TargetFrameLowering
*getFrameLowering() const override
{ return &FL
; }
109 const TargetLowering
*getTargetLowering() const override
{ return &TL
; }
111 const TargetInstrInfo
*getInstrInfo() const override
{ return &TII
; }
113 const TargetRegisterInfo
*getRegisterInfo() const override
{ return &TRI
; }
116 BogusFrameLowering FL
;
117 BogusRegisterInfo TRI
;
118 BogusTargetLowering TL
;
122 class BogusTargetMachine
: public LLVMTargetMachine
{
125 : LLVMTargetMachine(Target(), "", Triple(""), "", "", TargetOptions(),
126 Reloc::Static
, CodeModel::Small
, CodeGenOpt::Default
),
128 ~BogusTargetMachine() override
{}
130 const TargetSubtargetInfo
*getSubtargetImpl(const Function
&) const override
{
138 std::unique_ptr
<BogusTargetMachine
> createTargetMachine() {
139 return std::make_unique
<BogusTargetMachine
>();
142 std::unique_ptr
<MachineFunction
> createMachineFunction() {
144 Module
M("Module", Ctx
);
145 auto Type
= FunctionType::get(Type::getVoidTy(Ctx
), false);
146 auto F
= Function::Create(Type
, GlobalValue::ExternalLinkage
, "Test", &M
);
148 auto TM
= createTargetMachine();
149 unsigned FunctionNum
= 42;
150 MachineModuleInfo
MMI(TM
.get());
151 const TargetSubtargetInfo
&STI
= *TM
->getSubtargetImpl(*F
);
153 return std::make_unique
<MachineFunction
>(*F
, *TM
, STI
, FunctionNum
, MMI
);
156 // This test makes sure that MachineInstr::isIdenticalTo handles Defs correctly
157 // for various combinations of IgnoreDefs, and also that it is symmetrical.
158 TEST(IsIdenticalToTest
, DifferentDefs
) {
159 auto MF
= createMachineFunction();
161 unsigned short NumOps
= 2;
162 unsigned char NumDefs
= 1;
163 MCOperandInfo OpInfo
[] = {
164 {0, 0, MCOI::OPERAND_REGISTER
, 0},
165 {0, 1 << MCOI::OptionalDef
, MCOI::OPERAND_REGISTER
, 0}};
167 0, NumOps
, NumDefs
, 0, 0, 1ULL << MCID::HasOptionalDef
,
168 0, nullptr, nullptr, OpInfo
, 0, nullptr};
170 // Create two MIs with different virtual reg defs and the same uses.
171 unsigned VirtualDef1
= -42; // The value doesn't matter, but the sign does.
172 unsigned VirtualDef2
= -43;
173 unsigned VirtualUse
= -44;
175 auto MI1
= MF
->CreateMachineInstr(MCID
, DebugLoc());
176 MI1
->addOperand(*MF
, MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
177 MI1
->addOperand(*MF
, MachineOperand::CreateReg(VirtualUse
, /*isDef*/ false));
179 auto MI2
= MF
->CreateMachineInstr(MCID
, DebugLoc());
180 MI2
->addOperand(*MF
, MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
181 MI2
->addOperand(*MF
, MachineOperand::CreateReg(VirtualUse
, /*isDef*/ false));
183 // Check that they are identical when we ignore virtual register defs, but not
184 // when we check defs.
185 ASSERT_FALSE(MI1
->isIdenticalTo(*MI2
, MachineInstr::CheckDefs
));
186 ASSERT_FALSE(MI2
->isIdenticalTo(*MI1
, MachineInstr::CheckDefs
));
188 ASSERT_TRUE(MI1
->isIdenticalTo(*MI2
, MachineInstr::IgnoreVRegDefs
));
189 ASSERT_TRUE(MI2
->isIdenticalTo(*MI1
, MachineInstr::IgnoreVRegDefs
));
191 // Create two MIs with different virtual reg defs, and a def or use of a
192 // sentinel register.
193 unsigned SentinelReg
= 0;
195 auto MI3
= MF
->CreateMachineInstr(MCID
, DebugLoc());
196 MI3
->addOperand(*MF
, MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
197 MI3
->addOperand(*MF
, MachineOperand::CreateReg(SentinelReg
, /*isDef*/ true));
199 auto MI4
= MF
->CreateMachineInstr(MCID
, DebugLoc());
200 MI4
->addOperand(*MF
, MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
201 MI4
->addOperand(*MF
, MachineOperand::CreateReg(SentinelReg
, /*isDef*/ false));
203 // Check that they are never identical.
204 ASSERT_FALSE(MI3
->isIdenticalTo(*MI4
, MachineInstr::CheckDefs
));
205 ASSERT_FALSE(MI4
->isIdenticalTo(*MI3
, MachineInstr::CheckDefs
));
207 ASSERT_FALSE(MI3
->isIdenticalTo(*MI4
, MachineInstr::IgnoreVRegDefs
));
208 ASSERT_FALSE(MI4
->isIdenticalTo(*MI3
, MachineInstr::IgnoreVRegDefs
));
211 // Check that MachineInstrExpressionTrait::isEqual is symmetric and in sync with
212 // MachineInstrExpressionTrait::getHashValue
213 void checkHashAndIsEqualMatch(MachineInstr
*MI1
, MachineInstr
*MI2
) {
214 bool IsEqual1
= MachineInstrExpressionTrait::isEqual(MI1
, MI2
);
215 bool IsEqual2
= MachineInstrExpressionTrait::isEqual(MI2
, MI1
);
217 ASSERT_EQ(IsEqual1
, IsEqual2
);
219 auto Hash1
= MachineInstrExpressionTrait::getHashValue(MI1
);
220 auto Hash2
= MachineInstrExpressionTrait::getHashValue(MI2
);
222 ASSERT_EQ(IsEqual1
, Hash1
== Hash2
);
225 // This test makes sure that MachineInstrExpressionTraits::isEqual is in sync
226 // with MachineInstrExpressionTraits::getHashValue.
227 TEST(MachineInstrExpressionTraitTest
, IsEqualAgreesWithGetHashValue
) {
228 auto MF
= createMachineFunction();
230 unsigned short NumOps
= 2;
231 unsigned char NumDefs
= 1;
232 MCOperandInfo OpInfo
[] = {
233 {0, 0, MCOI::OPERAND_REGISTER
, 0},
234 {0, 1 << MCOI::OptionalDef
, MCOI::OPERAND_REGISTER
, 0}};
236 0, NumOps
, NumDefs
, 0, 0, 1ULL << MCID::HasOptionalDef
,
237 0, nullptr, nullptr, OpInfo
, 0, nullptr};
239 // Define a series of instructions with different kinds of operands and make
240 // sure that the hash function is consistent with isEqual for various
241 // combinations of them.
242 unsigned VirtualDef1
= -42;
243 unsigned VirtualDef2
= -43;
244 unsigned VirtualReg
= -44;
245 unsigned SentinelReg
= 0;
246 unsigned PhysicalReg
= 45;
248 auto VD1VU
= MF
->CreateMachineInstr(MCID
, DebugLoc());
249 VD1VU
->addOperand(*MF
,
250 MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
251 VD1VU
->addOperand(*MF
,
252 MachineOperand::CreateReg(VirtualReg
, /*isDef*/ false));
254 auto VD2VU
= MF
->CreateMachineInstr(MCID
, DebugLoc());
255 VD2VU
->addOperand(*MF
,
256 MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
257 VD2VU
->addOperand(*MF
,
258 MachineOperand::CreateReg(VirtualReg
, /*isDef*/ false));
260 auto VD1SU
= MF
->CreateMachineInstr(MCID
, DebugLoc());
261 VD1SU
->addOperand(*MF
,
262 MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
263 VD1SU
->addOperand(*MF
,
264 MachineOperand::CreateReg(SentinelReg
, /*isDef*/ false));
266 auto VD1SD
= MF
->CreateMachineInstr(MCID
, DebugLoc());
267 VD1SD
->addOperand(*MF
,
268 MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
269 VD1SD
->addOperand(*MF
,
270 MachineOperand::CreateReg(SentinelReg
, /*isDef*/ true));
272 auto VD2PU
= MF
->CreateMachineInstr(MCID
, DebugLoc());
273 VD2PU
->addOperand(*MF
,
274 MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
275 VD2PU
->addOperand(*MF
,
276 MachineOperand::CreateReg(PhysicalReg
, /*isDef*/ false));
278 auto VD2PD
= MF
->CreateMachineInstr(MCID
, DebugLoc());
279 VD2PD
->addOperand(*MF
,
280 MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
281 VD2PD
->addOperand(*MF
,
282 MachineOperand::CreateReg(PhysicalReg
, /*isDef*/ true));
284 checkHashAndIsEqualMatch(VD1VU
, VD2VU
);
285 checkHashAndIsEqualMatch(VD1VU
, VD1SU
);
286 checkHashAndIsEqualMatch(VD1VU
, VD1SD
);
287 checkHashAndIsEqualMatch(VD1VU
, VD2PU
);
288 checkHashAndIsEqualMatch(VD1VU
, VD2PD
);
290 checkHashAndIsEqualMatch(VD2VU
, VD1SU
);
291 checkHashAndIsEqualMatch(VD2VU
, VD1SD
);
292 checkHashAndIsEqualMatch(VD2VU
, VD2PU
);
293 checkHashAndIsEqualMatch(VD2VU
, VD2PD
);
295 checkHashAndIsEqualMatch(VD1SU
, VD1SD
);
296 checkHashAndIsEqualMatch(VD1SU
, VD2PU
);
297 checkHashAndIsEqualMatch(VD1SU
, VD2PD
);
299 checkHashAndIsEqualMatch(VD1SD
, VD2PU
);
300 checkHashAndIsEqualMatch(VD1SD
, VD2PD
);
302 checkHashAndIsEqualMatch(VD2PU
, VD2PD
);
305 TEST(MachineInstrPrintingTest
, DebugLocPrinting
) {
306 auto MF
= createMachineFunction();
308 MCOperandInfo OpInfo
{0, 0, MCOI::OPERAND_REGISTER
, 0};
309 MCInstrDesc MCID
= {0, 1, 1, 0, 0, 0,
310 0, nullptr, nullptr, &OpInfo
, 0, nullptr};
313 DIFile
*DIF
= DIFile::getDistinct(Ctx
, "filename", "");
314 DISubprogram
*DIS
= DISubprogram::getDistinct(
315 Ctx
, nullptr, "", "", DIF
, 0, nullptr, 0, nullptr, 0, 0, DINode::FlagZero
,
316 DISubprogram::SPFlagZero
, nullptr);
317 DILocation
*DIL
= DILocation::get(Ctx
, 1, 5, DIS
);
319 MachineInstr
*MI
= MF
->CreateMachineInstr(MCID
, DL
);
320 MI
->addOperand(*MF
, MachineOperand::CreateReg(0, /*isDef*/ true));
323 raw_string_ostream
OS(str
);
324 MI
->print(OS
, /*IsStandalone*/true, /*SkipOpers*/false, /*SkipDebugLoc*/false,
325 /*AddNewLine*/false);
327 StringRef(OS
.str()).startswith("$noreg = UNKNOWN debug-location "));
329 StringRef(OS
.str()).endswith("filename:1:5"));
332 TEST(MachineInstrSpan
, DistanceBegin
) {
333 auto MF
= createMachineFunction();
334 auto MBB
= MF
->CreateMachineBasicBlock();
336 MCInstrDesc MCID
= {0, 0, 0, 0, 0, 0,
337 0, nullptr, nullptr, nullptr, 0, nullptr};
339 auto MII
= MBB
->begin();
340 MachineInstrSpan
MIS(MII
, MBB
);
341 ASSERT_TRUE(MIS
.empty());
343 auto MI
= MF
->CreateMachineInstr(MCID
, DebugLoc());
344 MBB
->insert(MII
, MI
);
345 ASSERT_TRUE(std::distance(MIS
.begin(), MII
) == 1);
348 TEST(MachineInstrSpan
, DistanceEnd
) {
349 auto MF
= createMachineFunction();
350 auto MBB
= MF
->CreateMachineBasicBlock();
352 MCInstrDesc MCID
= {0, 0, 0, 0, 0, 0,
353 0, nullptr, nullptr, nullptr, 0, nullptr};
355 auto MII
= MBB
->end();
356 MachineInstrSpan
MIS(MII
, MBB
);
357 ASSERT_TRUE(MIS
.empty());
359 auto MI
= MF
->CreateMachineInstr(MCID
, DebugLoc());
360 MBB
->insert(MII
, MI
);
361 ASSERT_TRUE(std::distance(MIS
.begin(), MII
) == 1);
364 static_assert(is_trivially_copyable
<MCOperand
>::value
, "trivially copyable");