Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / unittests / CodeGen / MachineInstrTest.cpp
blob0841cd3a7fb04f3a4f9df12a076d93fedca7d520
1 //===- MachineInstrTest.cpp -----------------------------------------------===//
2 //
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
6 //
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"
32 using namespace llvm;
34 namespace {
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) {
48 LLVMContext Ctx;
49 Module Mod("Module", Ctx);
50 auto MF = createMachineFunction(Ctx, Mod);
52 unsigned short NumOps = 2;
53 unsigned char NumDefs = 1;
54 struct {
55 MCInstrDesc MCID;
56 MCOperandInfo OpInfo[2];
57 } Table = {
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
84 // sentinel register.
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) {
120 LLVMContext Ctx;
121 Module Mod("Module", Ctx);
122 auto MF = createMachineFunction(Ctx, Mod);
124 unsigned short NumOps = 2;
125 unsigned char NumDefs = 1;
126 struct {
127 MCInstrDesc MCID;
128 MCOperandInfo OpInfo[2];
129 } Table = {
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) {
201 LLVMContext Ctx;
202 Module Mod("Module", Ctx);
203 auto MF = createMachineFunction(Ctx, Mod);
205 struct {
206 MCInstrDesc MCID;
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);
216 DebugLoc DL(DIL);
217 MachineInstr *MI = MF->CreateMachineInstr(Table.MCID, DL);
218 MI->addOperand(*MF, MachineOperand::CreateReg(0, /*isDef*/ true));
220 std::string str;
221 raw_string_ostream OS(str);
222 MI->print(OS, /*IsStandalone*/true, /*SkipOpers*/false, /*SkipDebugLoc*/false,
223 /*AddNewLine*/false);
224 ASSERT_TRUE(
225 StringRef(OS.str()).startswith("$noreg = UNKNOWN debug-location "));
226 ASSERT_TRUE(
227 StringRef(OS.str()).endswith("filename:1:5"));
230 TEST(MachineInstrSpan, DistanceBegin) {
231 LLVMContext Ctx;
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) {
248 LLVMContext Ctx;
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) {
265 LLVMContext Ctx;
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;
276 MMOs.push_back(MMO);
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) {
325 LLVMContext Ctx;
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;
336 MMOs.push_back(MMO);
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);
348 MMOs.push_back(MMO);
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) {
366 LLVMContext Ctx;
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;
377 MMOs.push_back(MMO);
378 MMOs.push_back(MMO);
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) {
427 LLVMContext Ctx;
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 = {
436 Opcode, 0, 0, 0, 0,
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) {
457 LLVMContext Ctx;
458 MDNode *PCS = MDNode::getDistinct(Ctx, std::nullopt);
459 MDNode *DI = MDNode::getDistinct(Ctx, std::nullopt);
460 DebugLoc DL(DI);
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) {
482 LLVMContext Ctx;
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();
515 ++It;
516 MI->insert(It, Ops);
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
537 // allocatable.
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);
558 // bad inputs
559 EXPECT_EQ(MI->getNumOperands(), 10U);
560 MI->insert(MI->operands_begin(), {});
561 EXPECT_EQ(MI->getNumOperands(), 10U);
564 } // end namespace