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 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/CodeGen/MachineBasicBlock.h"
10 #include "llvm/CodeGen/MachineInstr.h"
11 #include "llvm/CodeGen/MachineFunction.h"
12 #include "llvm/CodeGen/MachineMemOperand.h"
13 #include "llvm/CodeGen/MachineModuleInfo.h"
14 #include "llvm/CodeGen/TargetFrameLowering.h"
15 #include "llvm/CodeGen/TargetInstrInfo.h"
16 #include "llvm/CodeGen/TargetLowering.h"
17 #include "llvm/CodeGen/TargetSubtargetInfo.h"
18 #include "llvm/IR/DebugInfoMetadata.h"
19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/IR/ModuleSlotTracker.h"
21 #include "llvm/MC/MCAsmInfo.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/Support/TargetRegistry.h"
24 #include "llvm/Support/TargetSelect.h"
25 #include "llvm/Target/TargetMachine.h"
26 #include "llvm/Target/TargetOptions.h"
27 #include "gtest/gtest.h"
28 
29 using namespace llvm;
30 
31 namespace {
32 // Include helper functions to ease the manipulation of MachineFunctions.
33 #include "MFCommon.inc"
34 
35 std::unique_ptr<MCContext> createMCContext(MCAsmInfo *AsmInfo) {
36   return std::make_unique<MCContext>(
37       AsmInfo, nullptr, nullptr, nullptr, nullptr, false);
38 }
39 
40 // This test makes sure that MachineInstr::isIdenticalTo handles Defs correctly
41 // for various combinations of IgnoreDefs, and also that it is symmetrical.
42 TEST(IsIdenticalToTest, DifferentDefs) {
43   LLVMContext Ctx;
44   Module Mod("Module", Ctx);
45   auto MF = createMachineFunction(Ctx, Mod);
46 
47   unsigned short NumOps = 2;
48   unsigned char NumDefs = 1;
49   MCOperandInfo OpInfo[] = {
50       {0, 0, MCOI::OPERAND_REGISTER, 0},
51       {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
52   MCInstrDesc MCID = {
53       0, NumOps,  NumDefs, 0,      0, 1ULL << MCID::HasOptionalDef,
54       0, nullptr, nullptr, OpInfo, 0, nullptr};
55 
56   // Create two MIs with different virtual reg defs and the same uses.
57   unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does.
58   unsigned VirtualDef2 = -43;
59   unsigned VirtualUse = -44;
60 
61   auto MI1 = MF->CreateMachineInstr(MCID, DebugLoc());
62   MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
63   MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
64 
65   auto MI2 = MF->CreateMachineInstr(MCID, DebugLoc());
66   MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
67   MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
68 
69   // Check that they are identical when we ignore virtual register defs, but not
70   // when we check defs.
71   ASSERT_FALSE(MI1->isIdenticalTo(*MI2, MachineInstr::CheckDefs));
72   ASSERT_FALSE(MI2->isIdenticalTo(*MI1, MachineInstr::CheckDefs));
73 
74   ASSERT_TRUE(MI1->isIdenticalTo(*MI2, MachineInstr::IgnoreVRegDefs));
75   ASSERT_TRUE(MI2->isIdenticalTo(*MI1, MachineInstr::IgnoreVRegDefs));
76 
77   // Create two MIs with different virtual reg defs, and a def or use of a
78   // sentinel register.
79   unsigned SentinelReg = 0;
80 
81   auto MI3 = MF->CreateMachineInstr(MCID, DebugLoc());
82   MI3->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
83   MI3->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
84 
85   auto MI4 = MF->CreateMachineInstr(MCID, DebugLoc());
86   MI4->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
87   MI4->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
88 
89   // Check that they are never identical.
90   ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::CheckDefs));
91   ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::CheckDefs));
92 
93   ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::IgnoreVRegDefs));
94   ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::IgnoreVRegDefs));
95 }
96 
97 // Check that MachineInstrExpressionTrait::isEqual is symmetric and in sync with
98 // MachineInstrExpressionTrait::getHashValue
99 void checkHashAndIsEqualMatch(MachineInstr *MI1, MachineInstr *MI2) {
100   bool IsEqual1 = MachineInstrExpressionTrait::isEqual(MI1, MI2);
101   bool IsEqual2 = MachineInstrExpressionTrait::isEqual(MI2, MI1);
102 
103   ASSERT_EQ(IsEqual1, IsEqual2);
104 
105   auto Hash1 = MachineInstrExpressionTrait::getHashValue(MI1);
106   auto Hash2 = MachineInstrExpressionTrait::getHashValue(MI2);
107 
108   ASSERT_EQ(IsEqual1, Hash1 == Hash2);
109 }
110 
111 // This test makes sure that MachineInstrExpressionTraits::isEqual is in sync
112 // with MachineInstrExpressionTraits::getHashValue.
113 TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) {
114   LLVMContext Ctx;
115   Module Mod("Module", Ctx);
116   auto MF = createMachineFunction(Ctx, Mod);
117 
118   unsigned short NumOps = 2;
119   unsigned char NumDefs = 1;
120   MCOperandInfo OpInfo[] = {
121       {0, 0, MCOI::OPERAND_REGISTER, 0},
122       {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
123   MCInstrDesc MCID = {
124       0, NumOps,  NumDefs, 0,      0, 1ULL << MCID::HasOptionalDef,
125       0, nullptr, nullptr, OpInfo, 0, nullptr};
126 
127   // Define a series of instructions with different kinds of operands and make
128   // sure that the hash function is consistent with isEqual for various
129   // combinations of them.
130   unsigned VirtualDef1 = -42;
131   unsigned VirtualDef2 = -43;
132   unsigned VirtualReg = -44;
133   unsigned SentinelReg = 0;
134   unsigned PhysicalReg = 45;
135 
136   auto VD1VU = MF->CreateMachineInstr(MCID, DebugLoc());
137   VD1VU->addOperand(*MF,
138                     MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
139   VD1VU->addOperand(*MF,
140                     MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
141 
142   auto VD2VU = MF->CreateMachineInstr(MCID, DebugLoc());
143   VD2VU->addOperand(*MF,
144                     MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
145   VD2VU->addOperand(*MF,
146                     MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
147 
148   auto VD1SU = MF->CreateMachineInstr(MCID, DebugLoc());
149   VD1SU->addOperand(*MF,
150                     MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
151   VD1SU->addOperand(*MF,
152                     MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
153 
154   auto VD1SD = MF->CreateMachineInstr(MCID, DebugLoc());
155   VD1SD->addOperand(*MF,
156                     MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
157   VD1SD->addOperand(*MF,
158                     MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
159 
160   auto VD2PU = MF->CreateMachineInstr(MCID, DebugLoc());
161   VD2PU->addOperand(*MF,
162                     MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
163   VD2PU->addOperand(*MF,
164                     MachineOperand::CreateReg(PhysicalReg, /*isDef*/ false));
165 
166   auto VD2PD = MF->CreateMachineInstr(MCID, DebugLoc());
167   VD2PD->addOperand(*MF,
168                     MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
169   VD2PD->addOperand(*MF,
170                     MachineOperand::CreateReg(PhysicalReg, /*isDef*/ true));
171 
172   checkHashAndIsEqualMatch(VD1VU, VD2VU);
173   checkHashAndIsEqualMatch(VD1VU, VD1SU);
174   checkHashAndIsEqualMatch(VD1VU, VD1SD);
175   checkHashAndIsEqualMatch(VD1VU, VD2PU);
176   checkHashAndIsEqualMatch(VD1VU, VD2PD);
177 
178   checkHashAndIsEqualMatch(VD2VU, VD1SU);
179   checkHashAndIsEqualMatch(VD2VU, VD1SD);
180   checkHashAndIsEqualMatch(VD2VU, VD2PU);
181   checkHashAndIsEqualMatch(VD2VU, VD2PD);
182 
183   checkHashAndIsEqualMatch(VD1SU, VD1SD);
184   checkHashAndIsEqualMatch(VD1SU, VD2PU);
185   checkHashAndIsEqualMatch(VD1SU, VD2PD);
186 
187   checkHashAndIsEqualMatch(VD1SD, VD2PU);
188   checkHashAndIsEqualMatch(VD1SD, VD2PD);
189 
190   checkHashAndIsEqualMatch(VD2PU, VD2PD);
191 }
192 
193 TEST(MachineInstrPrintingTest, DebugLocPrinting) {
194   LLVMContext Ctx;
195   Module Mod("Module", Ctx);
196   auto MF = createMachineFunction(Ctx, Mod);
197 
198   MCOperandInfo OpInfo{0, 0, MCOI::OPERAND_REGISTER, 0};
199   MCInstrDesc MCID = {0, 1,       1,       0,       0, 0,
200                       0, nullptr, nullptr, &OpInfo, 0, nullptr};
201 
202   DIFile *DIF = DIFile::getDistinct(Ctx, "filename", "");
203   DISubprogram *DIS = DISubprogram::getDistinct(
204       Ctx, nullptr, "", "", DIF, 0, nullptr, 0, nullptr, 0, 0, DINode::FlagZero,
205       DISubprogram::SPFlagZero, nullptr);
206   DILocation *DIL = DILocation::get(Ctx, 1, 5, DIS);
207   DebugLoc DL(DIL);
208   MachineInstr *MI = MF->CreateMachineInstr(MCID, DL);
209   MI->addOperand(*MF, MachineOperand::CreateReg(0, /*isDef*/ true));
210 
211   std::string str;
212   raw_string_ostream OS(str);
213   MI->print(OS, /*IsStandalone*/true, /*SkipOpers*/false, /*SkipDebugLoc*/false,
214             /*AddNewLine*/false);
215   ASSERT_TRUE(
216       StringRef(OS.str()).startswith("$noreg = UNKNOWN debug-location "));
217   ASSERT_TRUE(
218       StringRef(OS.str()).endswith("filename:1:5"));
219 }
220 
221 TEST(MachineInstrSpan, DistanceBegin) {
222   LLVMContext Ctx;
223   Module Mod("Module", Ctx);
224   auto MF = createMachineFunction(Ctx, Mod);
225   auto MBB = MF->CreateMachineBasicBlock();
226 
227   MCInstrDesc MCID = {0, 0,       0,       0,       0, 0,
228                       0, nullptr, nullptr, nullptr, 0, nullptr};
229 
230   auto MII = MBB->begin();
231   MachineInstrSpan MIS(MII, MBB);
232   ASSERT_TRUE(MIS.empty());
233 
234   auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
235   MBB->insert(MII, MI);
236   ASSERT_TRUE(std::distance(MIS.begin(), MII) == 1);
237 }
238 
239 TEST(MachineInstrSpan, DistanceEnd) {
240   LLVMContext Ctx;
241   Module Mod("Module", Ctx);
242   auto MF = createMachineFunction(Ctx, Mod);
243   auto MBB = MF->CreateMachineBasicBlock();
244 
245   MCInstrDesc MCID = {0, 0,       0,       0,       0, 0,
246                       0, nullptr, nullptr, nullptr, 0, nullptr};
247 
248   auto MII = MBB->end();
249   MachineInstrSpan MIS(MII, MBB);
250   ASSERT_TRUE(MIS.empty());
251 
252   auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
253   MBB->insert(MII, MI);
254   ASSERT_TRUE(std::distance(MIS.begin(), MII) == 1);
255 }
256 
257 TEST(MachineInstrExtraInfo, AddExtraInfo) {
258   LLVMContext Ctx;
259   Module Mod("Module", Ctx);
260   auto MF = createMachineFunction(Ctx, Mod);
261   MCInstrDesc MCID = {0, 0,       0,       0,       0, 0,
262                       0, nullptr, nullptr, nullptr, 0, nullptr};
263 
264   auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
265   auto MAI = MCAsmInfo();
266   auto MC = createMCContext(&MAI);
267   auto MMO = MF->getMachineMemOperand(MachinePointerInfo(),
268                                       MachineMemOperand::MOLoad, 8, 8);
269   SmallVector<MachineMemOperand *, 2> MMOs;
270   MMOs.push_back(MMO);
271   MCSymbol *Sym1 = MC->createTempSymbol("pre_label", false);
272   MCSymbol *Sym2 = MC->createTempSymbol("post_label", false);
273   MDNode *MDN = MDNode::getDistinct(Ctx, None);
274 
275   ASSERT_TRUE(MI->memoperands_empty());
276   ASSERT_FALSE(MI->getPreInstrSymbol());
277   ASSERT_FALSE(MI->getPostInstrSymbol());
278   ASSERT_FALSE(MI->getHeapAllocMarker());
279 
280   MI->setMemRefs(*MF, MMOs);
281   ASSERT_TRUE(MI->memoperands().size() == 1);
282   ASSERT_FALSE(MI->getPreInstrSymbol());
283   ASSERT_FALSE(MI->getPostInstrSymbol());
284   ASSERT_FALSE(MI->getHeapAllocMarker());
285 
286   MI->setPreInstrSymbol(*MF, Sym1);
287   ASSERT_TRUE(MI->memoperands().size() == 1);
288   ASSERT_TRUE(MI->getPreInstrSymbol() == Sym1);
289   ASSERT_FALSE(MI->getPostInstrSymbol());
290   ASSERT_FALSE(MI->getHeapAllocMarker());
291 
292   MI->setPostInstrSymbol(*MF, Sym2);
293   ASSERT_TRUE(MI->memoperands().size() == 1);
294   ASSERT_TRUE(MI->getPreInstrSymbol() == Sym1);
295   ASSERT_TRUE(MI->getPostInstrSymbol() == Sym2);
296   ASSERT_FALSE(MI->getHeapAllocMarker());
297 
298   MI->setHeapAllocMarker(*MF, MDN);
299   ASSERT_TRUE(MI->memoperands().size() == 1);
300   ASSERT_TRUE(MI->getPreInstrSymbol() == Sym1);
301   ASSERT_TRUE(MI->getPostInstrSymbol() == Sym2);
302   ASSERT_TRUE(MI->getHeapAllocMarker() == MDN);
303 }
304 
305 TEST(MachineInstrExtraInfo, ChangeExtraInfo) {
306   LLVMContext Ctx;
307   Module Mod("Module", Ctx);
308   auto MF = createMachineFunction(Ctx, Mod);
309   MCInstrDesc MCID = {0, 0,       0,       0,       0, 0,
310                       0, nullptr, nullptr, nullptr, 0, nullptr};
311 
312   auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
313   auto MAI = MCAsmInfo();
314   auto MC = createMCContext(&MAI);
315   auto MMO = MF->getMachineMemOperand(MachinePointerInfo(),
316                                       MachineMemOperand::MOLoad, 8, 8);
317   SmallVector<MachineMemOperand *, 2> MMOs;
318   MMOs.push_back(MMO);
319   MCSymbol *Sym1 = MC->createTempSymbol("pre_label", false);
320   MCSymbol *Sym2 = MC->createTempSymbol("post_label", false);
321   MDNode *MDN = MDNode::getDistinct(Ctx, None);
322 
323   MI->setMemRefs(*MF, MMOs);
324   MI->setPreInstrSymbol(*MF, Sym1);
325   MI->setPostInstrSymbol(*MF, Sym2);
326   MI->setHeapAllocMarker(*MF, MDN);
327 
328   MMOs.push_back(MMO);
329 
330   MI->setMemRefs(*MF, MMOs);
331   ASSERT_TRUE(MI->memoperands().size() == 2);
332   ASSERT_TRUE(MI->getPreInstrSymbol() == Sym1);
333   ASSERT_TRUE(MI->getPostInstrSymbol() == Sym2);
334   ASSERT_TRUE(MI->getHeapAllocMarker() == MDN);
335 
336   MI->setPostInstrSymbol(*MF, Sym1);
337   ASSERT_TRUE(MI->memoperands().size() == 2);
338   ASSERT_TRUE(MI->getPreInstrSymbol() == Sym1);
339   ASSERT_TRUE(MI->getPostInstrSymbol() == Sym1);
340   ASSERT_TRUE(MI->getHeapAllocMarker() == MDN);
341 }
342 
343 TEST(MachineInstrExtraInfo, RemoveExtraInfo) {
344   LLVMContext Ctx;
345   Module Mod("Module", Ctx);
346   auto MF = createMachineFunction(Ctx, Mod);
347   MCInstrDesc MCID = {0, 0,       0,       0,       0, 0,
348                       0, nullptr, nullptr, nullptr, 0, nullptr};
349 
350   auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
351   auto MAI = MCAsmInfo();
352   auto MC = createMCContext(&MAI);
353   auto MMO = MF->getMachineMemOperand(MachinePointerInfo(),
354                                       MachineMemOperand::MOLoad, 8, 8);
355   SmallVector<MachineMemOperand *, 2> MMOs;
356   MMOs.push_back(MMO);
357   MMOs.push_back(MMO);
358   MCSymbol *Sym1 = MC->createTempSymbol("pre_label", false);
359   MCSymbol *Sym2 = MC->createTempSymbol("post_label", false);
360   MDNode *MDN = MDNode::getDistinct(Ctx, None);
361 
362   MI->setMemRefs(*MF, MMOs);
363   MI->setPreInstrSymbol(*MF, Sym1);
364   MI->setPostInstrSymbol(*MF, Sym2);
365   MI->setHeapAllocMarker(*MF, MDN);
366 
367   MI->setPostInstrSymbol(*MF, nullptr);
368   ASSERT_TRUE(MI->memoperands().size() == 2);
369   ASSERT_TRUE(MI->getPreInstrSymbol() == Sym1);
370   ASSERT_FALSE(MI->getPostInstrSymbol());
371   ASSERT_TRUE(MI->getHeapAllocMarker() == MDN);
372 
373   MI->setHeapAllocMarker(*MF, nullptr);
374   ASSERT_TRUE(MI->memoperands().size() == 2);
375   ASSERT_TRUE(MI->getPreInstrSymbol() == Sym1);
376   ASSERT_FALSE(MI->getPostInstrSymbol());
377   ASSERT_FALSE(MI->getHeapAllocMarker());
378 
379   MI->setPreInstrSymbol(*MF, nullptr);
380   ASSERT_TRUE(MI->memoperands().size() == 2);
381   ASSERT_FALSE(MI->getPreInstrSymbol());
382   ASSERT_FALSE(MI->getPostInstrSymbol());
383   ASSERT_FALSE(MI->getHeapAllocMarker());
384 
385   MI->setMemRefs(*MF, {});
386   ASSERT_TRUE(MI->memoperands_empty());
387   ASSERT_FALSE(MI->getPreInstrSymbol());
388   ASSERT_FALSE(MI->getPostInstrSymbol());
389   ASSERT_FALSE(MI->getHeapAllocMarker());
390 }
391 
392 static_assert(is_trivially_copyable<MCOperand>::value, "trivially copyable");
393 
394 } // end namespace
395