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/MachineInstr.h"
10 #include "llvm/CodeGen/MachineBasicBlock.h"
11 #include "llvm/CodeGen/MachineFunction.h"
12 #include "llvm/CodeGen/MachineInstrBuilder.h"
13 #include "llvm/CodeGen/MachineMemOperand.h"
14 #include "llvm/CodeGen/MachineModuleInfo.h"
15 #include "llvm/CodeGen/TargetFrameLowering.h"
16 #include "llvm/CodeGen/TargetInstrInfo.h"
17 #include "llvm/CodeGen/TargetLowering.h"
18 #include "llvm/CodeGen/TargetSubtargetInfo.h"
19 #include "llvm/IR/DebugInfoMetadata.h"
20 #include "llvm/IR/IRBuilder.h"
21 #include "llvm/IR/ModuleSlotTracker.h"
22 #include "llvm/MC/MCAsmInfo.h"
23 #include "llvm/MC/MCSymbol.h"
24 #include "llvm/MC/TargetRegistry.h"
25 #include "llvm/Support/TargetSelect.h"
26 #include "llvm/Target/TargetMachine.h"
27 #include "llvm/Target/TargetOptions.h"
28 #include "llvm/TargetParser/Triple.h"
29 #include "gmock/gmock.h"
30 #include "gtest/gtest.h"
35 // Include helper functions to ease the manipulation of MachineFunctions.
36 #include "MFCommon.inc"
38 std::unique_ptr
<MCContext
> createMCContext(MCAsmInfo
*AsmInfo
) {
39 Triple
TheTriple(/*ArchStr=*/"", /*VendorStr=*/"", /*OSStr=*/"",
40 /*EnvironmentStr=*/"elf");
41 return std::make_unique
<MCContext
>(TheTriple
, AsmInfo
, nullptr, nullptr,
42 nullptr, nullptr, false);
45 // This test makes sure that MachineInstr::isIdenticalTo handles Defs correctly
46 // for various combinations of IgnoreDefs, and also that it is symmetrical.
47 TEST(IsIdenticalToTest
, DifferentDefs
) {
49 Module
Mod("Module", Ctx
);
50 auto MF
= createMachineFunction(Ctx
, Mod
);
52 unsigned short NumOps
= 2;
53 unsigned char NumDefs
= 1;
56 MCOperandInfo OpInfo
[2];
58 {0, NumOps
, NumDefs
, 0, 0, 0, 0, 0, 0, 1ULL << MCID::HasOptionalDef
, 0},
59 {{0, 0, MCOI::OPERAND_REGISTER
, 0},
60 {0, 1 << MCOI::OptionalDef
, MCOI::OPERAND_REGISTER
, 0}}};
62 // Create two MIs with different virtual reg defs and the same uses.
63 unsigned VirtualDef1
= -42; // The value doesn't matter, but the sign does.
64 unsigned VirtualDef2
= -43;
65 unsigned VirtualUse
= -44;
67 auto MI1
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
68 MI1
->addOperand(*MF
, MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
69 MI1
->addOperand(*MF
, MachineOperand::CreateReg(VirtualUse
, /*isDef*/ false));
71 auto MI2
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
72 MI2
->addOperand(*MF
, MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
73 MI2
->addOperand(*MF
, MachineOperand::CreateReg(VirtualUse
, /*isDef*/ false));
75 // Check that they are identical when we ignore virtual register defs, but not
76 // when we check defs.
77 ASSERT_FALSE(MI1
->isIdenticalTo(*MI2
, MachineInstr::CheckDefs
));
78 ASSERT_FALSE(MI2
->isIdenticalTo(*MI1
, MachineInstr::CheckDefs
));
80 ASSERT_TRUE(MI1
->isIdenticalTo(*MI2
, MachineInstr::IgnoreVRegDefs
));
81 ASSERT_TRUE(MI2
->isIdenticalTo(*MI1
, MachineInstr::IgnoreVRegDefs
));
83 // Create two MIs with different virtual reg defs, and a def or use of a
85 unsigned SentinelReg
= 0;
87 auto MI3
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
88 MI3
->addOperand(*MF
, MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
89 MI3
->addOperand(*MF
, MachineOperand::CreateReg(SentinelReg
, /*isDef*/ true));
91 auto MI4
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
92 MI4
->addOperand(*MF
, MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
93 MI4
->addOperand(*MF
, MachineOperand::CreateReg(SentinelReg
, /*isDef*/ false));
95 // Check that they are never identical.
96 ASSERT_FALSE(MI3
->isIdenticalTo(*MI4
, MachineInstr::CheckDefs
));
97 ASSERT_FALSE(MI4
->isIdenticalTo(*MI3
, MachineInstr::CheckDefs
));
99 ASSERT_FALSE(MI3
->isIdenticalTo(*MI4
, MachineInstr::IgnoreVRegDefs
));
100 ASSERT_FALSE(MI4
->isIdenticalTo(*MI3
, MachineInstr::IgnoreVRegDefs
));
103 // Check that MachineInstrExpressionTrait::isEqual is symmetric and in sync with
104 // MachineInstrExpressionTrait::getHashValue
105 void checkHashAndIsEqualMatch(MachineInstr
*MI1
, MachineInstr
*MI2
) {
106 bool IsEqual1
= MachineInstrExpressionTrait::isEqual(MI1
, MI2
);
107 bool IsEqual2
= MachineInstrExpressionTrait::isEqual(MI2
, MI1
);
109 ASSERT_EQ(IsEqual1
, IsEqual2
);
111 auto Hash1
= MachineInstrExpressionTrait::getHashValue(MI1
);
112 auto Hash2
= MachineInstrExpressionTrait::getHashValue(MI2
);
114 ASSERT_EQ(IsEqual1
, Hash1
== Hash2
);
117 // This test makes sure that MachineInstrExpressionTraits::isEqual is in sync
118 // with MachineInstrExpressionTraits::getHashValue.
119 TEST(MachineInstrExpressionTraitTest
, IsEqualAgreesWithGetHashValue
) {
121 Module
Mod("Module", Ctx
);
122 auto MF
= createMachineFunction(Ctx
, Mod
);
124 unsigned short NumOps
= 2;
125 unsigned char NumDefs
= 1;
128 MCOperandInfo OpInfo
[2];
130 {0, NumOps
, NumDefs
, 0, 0, 0, 0, 0, 0, 1ULL << MCID::HasOptionalDef
, 0},
131 {{0, 0, MCOI::OPERAND_REGISTER
, 0},
132 {0, 1 << MCOI::OptionalDef
, MCOI::OPERAND_REGISTER
, 0}}};
134 // Define a series of instructions with different kinds of operands and make
135 // sure that the hash function is consistent with isEqual for various
136 // combinations of them.
137 unsigned VirtualDef1
= -42;
138 unsigned VirtualDef2
= -43;
139 unsigned VirtualReg
= -44;
140 unsigned SentinelReg
= 0;
141 unsigned PhysicalReg
= 45;
143 auto VD1VU
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
144 VD1VU
->addOperand(*MF
,
145 MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
146 VD1VU
->addOperand(*MF
,
147 MachineOperand::CreateReg(VirtualReg
, /*isDef*/ false));
149 auto VD2VU
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
150 VD2VU
->addOperand(*MF
,
151 MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
152 VD2VU
->addOperand(*MF
,
153 MachineOperand::CreateReg(VirtualReg
, /*isDef*/ false));
155 auto VD1SU
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
156 VD1SU
->addOperand(*MF
,
157 MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
158 VD1SU
->addOperand(*MF
,
159 MachineOperand::CreateReg(SentinelReg
, /*isDef*/ false));
161 auto VD1SD
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
162 VD1SD
->addOperand(*MF
,
163 MachineOperand::CreateReg(VirtualDef1
, /*isDef*/ true));
164 VD1SD
->addOperand(*MF
,
165 MachineOperand::CreateReg(SentinelReg
, /*isDef*/ true));
167 auto VD2PU
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
168 VD2PU
->addOperand(*MF
,
169 MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
170 VD2PU
->addOperand(*MF
,
171 MachineOperand::CreateReg(PhysicalReg
, /*isDef*/ false));
173 auto VD2PD
= MF
->CreateMachineInstr(Table
.MCID
, DebugLoc());
174 VD2PD
->addOperand(*MF
,
175 MachineOperand::CreateReg(VirtualDef2
, /*isDef*/ true));
176 VD2PD
->addOperand(*MF
,
177 MachineOperand::CreateReg(PhysicalReg
, /*isDef*/ true));
179 checkHashAndIsEqualMatch(VD1VU
, VD2VU
);
180 checkHashAndIsEqualMatch(VD1VU
, VD1SU
);
181 checkHashAndIsEqualMatch(VD1VU
, VD1SD
);
182 checkHashAndIsEqualMatch(VD1VU
, VD2PU
);
183 checkHashAndIsEqualMatch(VD1VU
, VD2PD
);
185 checkHashAndIsEqualMatch(VD2VU
, VD1SU
);
186 checkHashAndIsEqualMatch(VD2VU
, VD1SD
);
187 checkHashAndIsEqualMatch(VD2VU
, VD2PU
);
188 checkHashAndIsEqualMatch(VD2VU
, VD2PD
);
190 checkHashAndIsEqualMatch(VD1SU
, VD1SD
);
191 checkHashAndIsEqualMatch(VD1SU
, VD2PU
);
192 checkHashAndIsEqualMatch(VD1SU
, VD2PD
);
194 checkHashAndIsEqualMatch(VD1SD
, VD2PU
);
195 checkHashAndIsEqualMatch(VD1SD
, VD2PD
);
197 checkHashAndIsEqualMatch(VD2PU
, VD2PD
);
200 TEST(MachineInstrPrintingTest
, DebugLocPrinting
) {
202 Module
Mod("Module", Ctx
);
203 auto MF
= createMachineFunction(Ctx
, Mod
);
207 MCOperandInfo OpInfo
;
208 } Table
= {{0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
209 {0, 0, MCOI::OPERAND_REGISTER
, 0}};
211 DIFile
*DIF
= DIFile::getDistinct(Ctx
, "filename", "");
212 DISubprogram
*DIS
= DISubprogram::getDistinct(
213 Ctx
, nullptr, "", "", DIF
, 0, nullptr, 0, nullptr, 0, 0, DINode::FlagZero
,
214 DISubprogram::SPFlagZero
, nullptr);
215 DILocation
*DIL
= DILocation::get(Ctx
, 1, 5, DIS
);
217 MachineInstr
*MI
= MF
->CreateMachineInstr(Table
.MCID
, DL
);
218 MI
->addOperand(*MF
, MachineOperand::CreateReg(0, /*isDef*/ true));
221 raw_string_ostream
OS(str
);
222 MI
->print(OS
, /*IsStandalone*/true, /*SkipOpers*/false, /*SkipDebugLoc*/false,
223 /*AddNewLine*/false);
225 StringRef(OS
.str()).startswith("$noreg = UNKNOWN debug-location "));
227 StringRef(OS
.str()).endswith("filename:1:5"));
230 TEST(MachineInstrSpan
, DistanceBegin
) {
232 Module
Mod("Module", Ctx
);
233 auto MF
= createMachineFunction(Ctx
, Mod
);
234 auto MBB
= MF
->CreateMachineBasicBlock();
236 MCInstrDesc MCID
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
238 auto MII
= MBB
->begin();
239 MachineInstrSpan
MIS(MII
, MBB
);
240 ASSERT_TRUE(MIS
.empty());
242 auto MI
= MF
->CreateMachineInstr(MCID
, DebugLoc());
243 MBB
->insert(MII
, MI
);
244 ASSERT_TRUE(std::distance(MIS
.begin(), MII
) == 1);
247 TEST(MachineInstrSpan
, DistanceEnd
) {
249 Module
Mod("Module", Ctx
);
250 auto MF
= createMachineFunction(Ctx
, Mod
);
251 auto MBB
= MF
->CreateMachineBasicBlock();
253 MCInstrDesc MCID
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
255 auto MII
= MBB
->end();
256 MachineInstrSpan
MIS(MII
, MBB
);
257 ASSERT_TRUE(MIS
.empty());
259 auto MI
= MF
->CreateMachineInstr(MCID
, DebugLoc());
260 MBB
->insert(MII
, MI
);
261 ASSERT_TRUE(std::distance(MIS
.begin(), MII
) == 1);
264 TEST(MachineInstrExtraInfo
, AddExtraInfo
) {
266 Module
Mod("Module", Ctx
);
267 auto MF
= createMachineFunction(Ctx
, Mod
);
268 MCInstrDesc MCID
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
270 auto MI
= MF
->CreateMachineInstr(MCID
, DebugLoc());
271 auto MAI
= MCAsmInfo();
272 auto MC
= createMCContext(&MAI
);
273 auto MMO
= MF
->getMachineMemOperand(MachinePointerInfo(),
274 MachineMemOperand::MOLoad
, 8, Align(8));
275 SmallVector
<MachineMemOperand
*, 2> MMOs
;
277 MCSymbol
*Sym1
= MC
->createTempSymbol("pre_label", false);
278 MCSymbol
*Sym2
= MC
->createTempSymbol("post_label", false);
279 MDNode
*HAM
= MDNode::getDistinct(Ctx
, std::nullopt
);
280 MDNode
*PCS
= MDNode::getDistinct(Ctx
, std::nullopt
);
282 ASSERT_TRUE(MI
->memoperands_empty());
283 ASSERT_FALSE(MI
->getPreInstrSymbol());
284 ASSERT_FALSE(MI
->getPostInstrSymbol());
285 ASSERT_FALSE(MI
->getHeapAllocMarker());
286 ASSERT_FALSE(MI
->getPCSections());
288 MI
->setMemRefs(*MF
, MMOs
);
289 ASSERT_TRUE(MI
->memoperands().size() == 1);
290 ASSERT_FALSE(MI
->getPreInstrSymbol());
291 ASSERT_FALSE(MI
->getPostInstrSymbol());
292 ASSERT_FALSE(MI
->getHeapAllocMarker());
293 ASSERT_FALSE(MI
->getPCSections());
295 MI
->setPreInstrSymbol(*MF
, Sym1
);
296 ASSERT_TRUE(MI
->memoperands().size() == 1);
297 ASSERT_TRUE(MI
->getPreInstrSymbol() == Sym1
);
298 ASSERT_FALSE(MI
->getPostInstrSymbol());
299 ASSERT_FALSE(MI
->getHeapAllocMarker());
300 ASSERT_FALSE(MI
->getPCSections());
302 MI
->setPostInstrSymbol(*MF
, Sym2
);
303 ASSERT_TRUE(MI
->memoperands().size() == 1);
304 ASSERT_TRUE(MI
->getPreInstrSymbol() == Sym1
);
305 ASSERT_TRUE(MI
->getPostInstrSymbol() == Sym2
);
306 ASSERT_FALSE(MI
->getHeapAllocMarker());
307 ASSERT_FALSE(MI
->getPCSections());
309 MI
->setHeapAllocMarker(*MF
, HAM
);
310 ASSERT_TRUE(MI
->memoperands().size() == 1);
311 ASSERT_TRUE(MI
->getPreInstrSymbol() == Sym1
);
312 ASSERT_TRUE(MI
->getPostInstrSymbol() == Sym2
);
313 ASSERT_TRUE(MI
->getHeapAllocMarker() == HAM
);
314 ASSERT_FALSE(MI
->getPCSections());
316 MI
->setPCSections(*MF
, PCS
);
317 ASSERT_TRUE(MI
->memoperands().size() == 1);
318 ASSERT_TRUE(MI
->getPreInstrSymbol() == Sym1
);
319 ASSERT_TRUE(MI
->getPostInstrSymbol() == Sym2
);
320 ASSERT_TRUE(MI
->getHeapAllocMarker() == HAM
);
321 ASSERT_TRUE(MI
->getPCSections() == PCS
);
324 TEST(MachineInstrExtraInfo
, ChangeExtraInfo
) {
326 Module
Mod("Module", Ctx
);
327 auto MF
= createMachineFunction(Ctx
, Mod
);
328 MCInstrDesc MCID
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
330 auto MI
= MF
->CreateMachineInstr(MCID
, DebugLoc());
331 auto MAI
= MCAsmInfo();
332 auto MC
= createMCContext(&MAI
);
333 auto MMO
= MF
->getMachineMemOperand(MachinePointerInfo(),
334 MachineMemOperand::MOLoad
, 8, Align(8));
335 SmallVector
<MachineMemOperand
*, 2> MMOs
;
337 MCSymbol
*Sym1
= MC
->createTempSymbol("pre_label", false);
338 MCSymbol
*Sym2
= MC
->createTempSymbol("post_label", false);
339 MDNode
*HAM
= MDNode::getDistinct(Ctx
, std::nullopt
);
340 MDNode
*PCS
= MDNode::getDistinct(Ctx
, std::nullopt
);
342 MI
->setMemRefs(*MF
, MMOs
);
343 MI
->setPreInstrSymbol(*MF
, Sym1
);
344 MI
->setPostInstrSymbol(*MF
, Sym2
);
345 MI
->setHeapAllocMarker(*MF
, HAM
);
346 MI
->setPCSections(*MF
, PCS
);
350 MI
->setMemRefs(*MF
, MMOs
);
351 ASSERT_TRUE(MI
->memoperands().size() == 2);
352 ASSERT_TRUE(MI
->getPreInstrSymbol() == Sym1
);
353 ASSERT_TRUE(MI
->getPostInstrSymbol() == Sym2
);
354 ASSERT_TRUE(MI
->getHeapAllocMarker() == HAM
);
355 ASSERT_TRUE(MI
->getPCSections() == PCS
);
357 MI
->setPostInstrSymbol(*MF
, Sym1
);
358 ASSERT_TRUE(MI
->memoperands().size() == 2);
359 ASSERT_TRUE(MI
->getPreInstrSymbol() == Sym1
);
360 ASSERT_TRUE(MI
->getPostInstrSymbol() == Sym1
);
361 ASSERT_TRUE(MI
->getHeapAllocMarker() == HAM
);
362 ASSERT_TRUE(MI
->getPCSections() == PCS
);
365 TEST(MachineInstrExtraInfo
, RemoveExtraInfo
) {
367 Module
Mod("Module", Ctx
);
368 auto MF
= createMachineFunction(Ctx
, Mod
);
369 MCInstrDesc MCID
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
371 auto MI
= MF
->CreateMachineInstr(MCID
, DebugLoc());
372 auto MAI
= MCAsmInfo();
373 auto MC
= createMCContext(&MAI
);
374 auto MMO
= MF
->getMachineMemOperand(MachinePointerInfo(),
375 MachineMemOperand::MOLoad
, 8, Align(8));
376 SmallVector
<MachineMemOperand
*, 2> MMOs
;
379 MCSymbol
*Sym1
= MC
->createTempSymbol("pre_label", false);
380 MCSymbol
*Sym2
= MC
->createTempSymbol("post_label", false);
381 MDNode
*HAM
= MDNode::getDistinct(Ctx
, std::nullopt
);
382 MDNode
*PCS
= MDNode::getDistinct(Ctx
, std::nullopt
);
384 MI
->setMemRefs(*MF
, MMOs
);
385 MI
->setPreInstrSymbol(*MF
, Sym1
);
386 MI
->setPostInstrSymbol(*MF
, Sym2
);
387 MI
->setHeapAllocMarker(*MF
, HAM
);
388 MI
->setPCSections(*MF
, PCS
);
390 MI
->setPostInstrSymbol(*MF
, nullptr);
391 ASSERT_TRUE(MI
->memoperands().size() == 2);
392 ASSERT_TRUE(MI
->getPreInstrSymbol() == Sym1
);
393 ASSERT_FALSE(MI
->getPostInstrSymbol());
394 ASSERT_TRUE(MI
->getHeapAllocMarker() == HAM
);
395 ASSERT_TRUE(MI
->getPCSections() == PCS
);
397 MI
->setHeapAllocMarker(*MF
, nullptr);
398 ASSERT_TRUE(MI
->memoperands().size() == 2);
399 ASSERT_TRUE(MI
->getPreInstrSymbol() == Sym1
);
400 ASSERT_FALSE(MI
->getPostInstrSymbol());
401 ASSERT_FALSE(MI
->getHeapAllocMarker());
402 ASSERT_TRUE(MI
->getPCSections() == PCS
);
404 MI
->setPCSections(*MF
, nullptr);
405 ASSERT_TRUE(MI
->memoperands().size() == 2);
406 ASSERT_TRUE(MI
->getPreInstrSymbol() == Sym1
);
407 ASSERT_FALSE(MI
->getPostInstrSymbol());
408 ASSERT_FALSE(MI
->getHeapAllocMarker());
409 ASSERT_FALSE(MI
->getPCSections());
411 MI
->setPreInstrSymbol(*MF
, nullptr);
412 ASSERT_TRUE(MI
->memoperands().size() == 2);
413 ASSERT_FALSE(MI
->getPreInstrSymbol());
414 ASSERT_FALSE(MI
->getPostInstrSymbol());
415 ASSERT_FALSE(MI
->getHeapAllocMarker());
416 ASSERT_FALSE(MI
->getPCSections());
418 MI
->setMemRefs(*MF
, {});
419 ASSERT_TRUE(MI
->memoperands_empty());
420 ASSERT_FALSE(MI
->getPreInstrSymbol());
421 ASSERT_FALSE(MI
->getPostInstrSymbol());
422 ASSERT_FALSE(MI
->getHeapAllocMarker());
423 ASSERT_FALSE(MI
->getPCSections());
426 TEST(MachineInstrDebugValue
, AddDebugValueOperand
) {
428 Module
Mod("Module", Ctx
);
429 auto MF
= createMachineFunction(Ctx
, Mod
);
431 for (const unsigned short Opcode
:
432 {TargetOpcode::DBG_VALUE
, TargetOpcode::DBG_VALUE_LIST
,
433 TargetOpcode::DBG_INSTR_REF
, TargetOpcode::DBG_PHI
,
434 TargetOpcode::DBG_LABEL
}) {
435 const MCInstrDesc MCID
= {
437 0, 0, 0, 0, (1ULL << MCID::Pseudo
) | (1ULL << MCID::Variadic
),
440 auto *MI
= MF
->CreateMachineInstr(MCID
, DebugLoc());
441 MI
->addOperand(*MF
, MachineOperand::CreateReg(0, /*isDef*/ false));
443 MI
->addOperand(*MF
, MachineOperand::CreateImm(0));
444 MI
->getOperand(1).ChangeToRegister(0, false);
446 ASSERT_TRUE(MI
->getOperand(0).isDebug());
447 ASSERT_TRUE(MI
->getOperand(1).isDebug());
451 MATCHER_P(HasMIMetadata
, MIMD
, "") {
452 return arg
->getDebugLoc() == MIMD
.getDL() &&
453 arg
->getPCSections() == MIMD
.getPCSections();
456 TEST(MachineInstrBuilder
, BuildMI
) {
458 MDNode
*PCS
= MDNode::getDistinct(Ctx
, std::nullopt
);
459 MDNode
*DI
= MDNode::getDistinct(Ctx
, std::nullopt
);
461 MIMetadata
MIMD(DL
, PCS
);
462 EXPECT_EQ(MIMD
.getDL(), DL
);
463 EXPECT_EQ(MIMD
.getPCSections(), PCS
);
464 // Check common BuildMI() overloads propagate MIMetadata.
465 Module
Mod("Module", Ctx
);
466 auto MF
= createMachineFunction(Ctx
, Mod
);
467 auto MBB
= MF
->CreateMachineBasicBlock();
468 MCInstrDesc MCID
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
469 EXPECT_THAT(BuildMI(*MF
, MIMD
, MCID
), HasMIMetadata(MIMD
));
470 EXPECT_THAT(BuildMI(*MF
, MIMD
, MCID
), HasMIMetadata(MIMD
));
471 EXPECT_THAT(BuildMI(*MBB
, MBB
->end(), MIMD
, MCID
), HasMIMetadata(MIMD
));
472 EXPECT_THAT(BuildMI(*MBB
, MBB
->end(), MIMD
, MCID
), HasMIMetadata(MIMD
));
473 EXPECT_THAT(BuildMI(*MBB
, MBB
->instr_end(), MIMD
, MCID
), HasMIMetadata(MIMD
));
474 EXPECT_THAT(BuildMI(*MBB
, *MBB
->begin(), MIMD
, MCID
), HasMIMetadata(MIMD
));
475 EXPECT_THAT(BuildMI(*MBB
, &*MBB
->begin(), MIMD
, MCID
), HasMIMetadata(MIMD
));
476 EXPECT_THAT(BuildMI(MBB
, MIMD
, MCID
), HasMIMetadata(MIMD
));
479 static_assert(std::is_trivially_copyable_v
<MCOperand
>, "trivially copyable");
481 TEST(MachineInstrTest
, SpliceOperands
) {
483 Module
Mod("Module", Ctx
);
484 std::unique_ptr
<MachineFunction
> MF
= createMachineFunction(Ctx
, Mod
);
485 MachineBasicBlock
*MBB
= MF
->CreateMachineBasicBlock();
486 MCInstrDesc MCID
= {TargetOpcode::INLINEASM
,
495 (1ULL << MCID::Pseudo
) | (1ULL << MCID::Variadic
),
497 MachineInstr
*MI
= MF
->CreateMachineInstr(MCID
, DebugLoc());
498 MBB
->insert(MBB
->begin(), MI
);
499 MI
->addOperand(MachineOperand::CreateImm(0));
500 MI
->addOperand(MachineOperand::CreateImm(1));
501 MI
->addOperand(MachineOperand::CreateImm(2));
502 MI
->addOperand(MachineOperand::CreateImm(3));
503 MI
->addOperand(MachineOperand::CreateImm(4));
505 MI
->removeOperand(1);
506 EXPECT_EQ(MI
->getOperand(1).getImm(), MachineOperand::CreateImm(2).getImm());
507 EXPECT_EQ(MI
->getNumOperands(), 4U);
509 MachineOperand Ops
[] = {
510 MachineOperand::CreateImm(42), MachineOperand::CreateImm(1024),
511 MachineOperand::CreateImm(2048), MachineOperand::CreateImm(4096),
512 MachineOperand::CreateImm(8192),
514 auto *It
= MI
->operands_begin();
518 EXPECT_EQ(MI
->getNumOperands(), 9U);
519 EXPECT_EQ(MI
->getOperand(0).getImm(), MachineOperand::CreateImm(0).getImm());
520 EXPECT_EQ(MI
->getOperand(1).getImm(), MachineOperand::CreateImm(42).getImm());
521 EXPECT_EQ(MI
->getOperand(2).getImm(),
522 MachineOperand::CreateImm(1024).getImm());
523 EXPECT_EQ(MI
->getOperand(3).getImm(),
524 MachineOperand::CreateImm(2048).getImm());
525 EXPECT_EQ(MI
->getOperand(4).getImm(),
526 MachineOperand::CreateImm(4096).getImm());
527 EXPECT_EQ(MI
->getOperand(5).getImm(),
528 MachineOperand::CreateImm(8192).getImm());
529 EXPECT_EQ(MI
->getOperand(6).getImm(), MachineOperand::CreateImm(2).getImm());
530 EXPECT_EQ(MI
->getOperand(7).getImm(), MachineOperand::CreateImm(3).getImm());
531 EXPECT_EQ(MI
->getOperand(8).getImm(), MachineOperand::CreateImm(4).getImm());
533 // test tied operands
534 MCRegisterClass MRC
{0, 0, 0, 0, 0, 0, 0, 0, /*Allocatable=*/true};
535 TargetRegisterClass RC
{&MRC
, 0, 0, {}, 0, 0, 0, 0, 0, 0, 0};
536 // MachineRegisterInfo will be very upset if these registers aren't
538 assert(RC
.isAllocatable() && "unusable TargetRegisterClass");
539 MachineRegisterInfo
&MRI
= MF
->getRegInfo();
540 Register A
= MRI
.createVirtualRegister(&RC
);
541 Register B
= MRI
.createVirtualRegister(&RC
);
542 MI
->getOperand(0).ChangeToRegister(A
, /*isDef=*/true);
543 MI
->getOperand(1).ChangeToRegister(B
, /*isDef=*/false);
544 MI
->tieOperands(0, 1);
545 EXPECT_TRUE(MI
->getOperand(0).isTied());
546 EXPECT_TRUE(MI
->getOperand(1).isTied());
547 EXPECT_EQ(MI
->findTiedOperandIdx(0), 1U);
548 EXPECT_EQ(MI
->findTiedOperandIdx(1), 0U);
549 MI
->insert(&MI
->getOperand(1), {MachineOperand::CreateImm(7)});
550 EXPECT_TRUE(MI
->getOperand(0).isTied());
551 EXPECT_TRUE(MI
->getOperand(1).isImm());
552 EXPECT_TRUE(MI
->getOperand(2).isTied());
553 EXPECT_EQ(MI
->findTiedOperandIdx(0), 2U);
554 EXPECT_EQ(MI
->findTiedOperandIdx(2), 0U);
555 EXPECT_EQ(MI
->getOperand(0).getReg(), A
);
556 EXPECT_EQ(MI
->getOperand(2).getReg(), B
);
559 EXPECT_EQ(MI
->getNumOperands(), 10U);
560 MI
->insert(MI
->operands_begin(), {});
561 EXPECT_EQ(MI
->getNumOperands(), 10U);