1 //===- MachineInstrTest.cpp -----------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
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"
24
25 using namespace llvm;
26
27 namespace {
28 // Add a few Bogus backend classes so we can create MachineInstrs without
29 // depending on a real target.
30 class BogusTargetLowering : public TargetLowering {
31 public:
BogusTargetLowering(TargetMachine & TM)32 BogusTargetLowering(TargetMachine &TM) : TargetLowering(TM) {}
33 };
34
35 class BogusFrameLowering : public TargetFrameLowering {
36 public:
BogusFrameLowering()37 BogusFrameLowering()
38 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 4) {}
39
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const40 void emitPrologue(MachineFunction &MF,
41 MachineBasicBlock &MBB) const override {}
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const42 void emitEpilogue(MachineFunction &MF,
43 MachineBasicBlock &MBB) const override {}
hasFP(const MachineFunction & MF) const44 bool hasFP(const MachineFunction &MF) const override { return false; }
45 };
46
47 class BogusSubtarget : public TargetSubtargetInfo {
48 public:
BogusSubtarget(TargetMachine & TM)49 BogusSubtarget(TargetMachine &TM)
50 : TargetSubtargetInfo(Triple(""), "", "", {}, {}, nullptr, nullptr,
51 nullptr, nullptr, nullptr, nullptr, nullptr),
52 FL(), TL(TM) {}
~BogusSubtarget()53 ~BogusSubtarget() override {}
54
getFrameLowering() const55 const TargetFrameLowering *getFrameLowering() const override { return &FL; }
56
getTargetLowering() const57 const TargetLowering *getTargetLowering() const override { return &TL; }
58
getInstrInfo() const59 const TargetInstrInfo *getInstrInfo() const override { return &TII; }
60
61 private:
62 BogusFrameLowering FL;
63 BogusTargetLowering TL;
64 TargetInstrInfo TII;
65 };
66
67 class BogusTargetMachine : public LLVMTargetMachine {
68 public:
BogusTargetMachine()69 BogusTargetMachine()
70 : LLVMTargetMachine(Target(), "", Triple(""), "", "", TargetOptions(),
71 Reloc::Static, CodeModel::Small, CodeGenOpt::Default),
72 ST(*this) {}
~BogusTargetMachine()73 ~BogusTargetMachine() override {}
74
getSubtargetImpl(const Function &) const75 const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override {
76 return &ST;
77 }
78
79 private:
80 BogusSubtarget ST;
81 };
82
createTargetMachine()83 std::unique_ptr<BogusTargetMachine> createTargetMachine() {
84 return llvm::make_unique<BogusTargetMachine>();
85 }
86
createMachineFunction()87 std::unique_ptr<MachineFunction> createMachineFunction() {
88 LLVMContext Ctx;
89 Module M("Module", Ctx);
90 auto Type = FunctionType::get(Type::getVoidTy(Ctx), false);
91 auto F = Function::Create(Type, GlobalValue::ExternalLinkage, "Test", &M);
92
93 auto TM = createTargetMachine();
94 unsigned FunctionNum = 42;
95 MachineModuleInfo MMI(TM.get());
96 const TargetSubtargetInfo &STI = *TM->getSubtargetImpl(*F);
97
98 return llvm::make_unique<MachineFunction>(*F, *TM, STI, FunctionNum, MMI);
99 }
100
101 // This test makes sure that MachineInstr::isIdenticalTo handles Defs correctly
102 // for various combinations of IgnoreDefs, and also that it is symmetrical.
TEST(IsIdenticalToTest,DifferentDefs)103 TEST(IsIdenticalToTest, DifferentDefs) {
104 auto MF = createMachineFunction();
105
106 unsigned short NumOps = 2;
107 unsigned char NumDefs = 1;
108 MCOperandInfo OpInfo[] = {
109 {0, 0, MCOI::OPERAND_REGISTER, 0},
110 {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
111 MCInstrDesc MCID = {
112 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef,
113 0, nullptr, nullptr, OpInfo, 0, nullptr};
114
115 // Create two MIs with different virtual reg defs and the same uses.
116 unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does.
117 unsigned VirtualDef2 = -43;
118 unsigned VirtualUse = -44;
119
120 auto MI1 = MF->CreateMachineInstr(MCID, DebugLoc());
121 MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
122 MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
123
124 auto MI2 = MF->CreateMachineInstr(MCID, DebugLoc());
125 MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
126 MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
127
128 // Check that they are identical when we ignore virtual register defs, but not
129 // when we check defs.
130 ASSERT_FALSE(MI1->isIdenticalTo(*MI2, MachineInstr::CheckDefs));
131 ASSERT_FALSE(MI2->isIdenticalTo(*MI1, MachineInstr::CheckDefs));
132
133 ASSERT_TRUE(MI1->isIdenticalTo(*MI2, MachineInstr::IgnoreVRegDefs));
134 ASSERT_TRUE(MI2->isIdenticalTo(*MI1, MachineInstr::IgnoreVRegDefs));
135
136 // Create two MIs with different virtual reg defs, and a def or use of a
137 // sentinel register.
138 unsigned SentinelReg = 0;
139
140 auto MI3 = MF->CreateMachineInstr(MCID, DebugLoc());
141 MI3->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
142 MI3->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
143
144 auto MI4 = MF->CreateMachineInstr(MCID, DebugLoc());
145 MI4->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
146 MI4->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
147
148 // Check that they are never identical.
149 ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::CheckDefs));
150 ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::CheckDefs));
151
152 ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::IgnoreVRegDefs));
153 ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::IgnoreVRegDefs));
154 }
155
156 // Check that MachineInstrExpressionTrait::isEqual is symmetric and in sync with
157 // MachineInstrExpressionTrait::getHashValue
checkHashAndIsEqualMatch(MachineInstr * MI1,MachineInstr * MI2)158 void checkHashAndIsEqualMatch(MachineInstr *MI1, MachineInstr *MI2) {
159 bool IsEqual1 = MachineInstrExpressionTrait::isEqual(MI1, MI2);
160 bool IsEqual2 = MachineInstrExpressionTrait::isEqual(MI2, MI1);
161
162 ASSERT_EQ(IsEqual1, IsEqual2);
163
164 auto Hash1 = MachineInstrExpressionTrait::getHashValue(MI1);
165 auto Hash2 = MachineInstrExpressionTrait::getHashValue(MI2);
166
167 ASSERT_EQ(IsEqual1, Hash1 == Hash2);
168 }
169
170 // This test makes sure that MachineInstrExpressionTraits::isEqual is in sync
171 // with MachineInstrExpressionTraits::getHashValue.
TEST(MachineInstrExpressionTraitTest,IsEqualAgreesWithGetHashValue)172 TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) {
173 auto MF = createMachineFunction();
174
175 unsigned short NumOps = 2;
176 unsigned char NumDefs = 1;
177 MCOperandInfo OpInfo[] = {
178 {0, 0, MCOI::OPERAND_REGISTER, 0},
179 {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
180 MCInstrDesc MCID = {
181 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef,
182 0, nullptr, nullptr, OpInfo, 0, nullptr};
183
184 // Define a series of instructions with different kinds of operands and make
185 // sure that the hash function is consistent with isEqual for various
186 // combinations of them.
187 unsigned VirtualDef1 = -42;
188 unsigned VirtualDef2 = -43;
189 unsigned VirtualReg = -44;
190 unsigned SentinelReg = 0;
191 unsigned PhysicalReg = 45;
192
193 auto VD1VU = MF->CreateMachineInstr(MCID, DebugLoc());
194 VD1VU->addOperand(*MF,
195 MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
196 VD1VU->addOperand(*MF,
197 MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
198
199 auto VD2VU = MF->CreateMachineInstr(MCID, DebugLoc());
200 VD2VU->addOperand(*MF,
201 MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
202 VD2VU->addOperand(*MF,
203 MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
204
205 auto VD1SU = MF->CreateMachineInstr(MCID, DebugLoc());
206 VD1SU->addOperand(*MF,
207 MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
208 VD1SU->addOperand(*MF,
209 MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
210
211 auto VD1SD = MF->CreateMachineInstr(MCID, DebugLoc());
212 VD1SD->addOperand(*MF,
213 MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
214 VD1SD->addOperand(*MF,
215 MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
216
217 auto VD2PU = MF->CreateMachineInstr(MCID, DebugLoc());
218 VD2PU->addOperand(*MF,
219 MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
220 VD2PU->addOperand(*MF,
221 MachineOperand::CreateReg(PhysicalReg, /*isDef*/ false));
222
223 auto VD2PD = MF->CreateMachineInstr(MCID, DebugLoc());
224 VD2PD->addOperand(*MF,
225 MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
226 VD2PD->addOperand(*MF,
227 MachineOperand::CreateReg(PhysicalReg, /*isDef*/ true));
228
229 checkHashAndIsEqualMatch(VD1VU, VD2VU);
230 checkHashAndIsEqualMatch(VD1VU, VD1SU);
231 checkHashAndIsEqualMatch(VD1VU, VD1SD);
232 checkHashAndIsEqualMatch(VD1VU, VD2PU);
233 checkHashAndIsEqualMatch(VD1VU, VD2PD);
234
235 checkHashAndIsEqualMatch(VD2VU, VD1SU);
236 checkHashAndIsEqualMatch(VD2VU, VD1SD);
237 checkHashAndIsEqualMatch(VD2VU, VD2PU);
238 checkHashAndIsEqualMatch(VD2VU, VD2PD);
239
240 checkHashAndIsEqualMatch(VD1SU, VD1SD);
241 checkHashAndIsEqualMatch(VD1SU, VD2PU);
242 checkHashAndIsEqualMatch(VD1SU, VD2PD);
243
244 checkHashAndIsEqualMatch(VD1SD, VD2PU);
245 checkHashAndIsEqualMatch(VD1SD, VD2PD);
246
247 checkHashAndIsEqualMatch(VD2PU, VD2PD);
248 }
249
TEST(MachineInstrPrintingTest,DebugLocPrinting)250 TEST(MachineInstrPrintingTest, DebugLocPrinting) {
251 auto MF = createMachineFunction();
252
253 MCOperandInfo OpInfo{0, 0, MCOI::OPERAND_REGISTER, 0};
254 MCInstrDesc MCID = {0, 1, 1, 0, 0, 0,
255 0, nullptr, nullptr, &OpInfo, 0, nullptr};
256
257 LLVMContext Ctx;
258 DIFile *DIF = DIFile::getDistinct(Ctx, "filename", "");
259 DISubprogram *DIS = DISubprogram::getDistinct(
260 Ctx, nullptr, "", "", DIF, 0, nullptr, false, false, 0, nullptr, 0, 0, 0,
261 DINode::FlagZero, false, nullptr);
262 DILocation *DIL = DILocation::get(Ctx, 1, 5, DIS);
263 DebugLoc DL(DIL);
264 MachineInstr *MI = MF->CreateMachineInstr(MCID, DL);
265 MI->addOperand(*MF, MachineOperand::CreateReg(0, /*isDef*/ true));
266
267 std::string str;
268 raw_string_ostream OS(str);
269 MI->print(OS);
270 ASSERT_TRUE(
271 StringRef(OS.str()).startswith("$noreg = UNKNOWN debug-location "));
272 ASSERT_TRUE(
273 StringRef(OS.str()).endswith("filename:1:5"));
274 }
275
276 } // end namespace
277