xref: /llvm-project/llvm/unittests/CodeGen/MachineOperandTest.cpp (revision bb3f5e1fed7c6ba733b7f273e93f5d3930976185)
1 //===- MachineOperandTest.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/MachineOperand.h"
10 #include "llvm/ADT/ilist_node.h"
11 #include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
12 #include "llvm/CodeGen/MachineFunction.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/CodeGenTypes/LowLevelType.h"
18 #include "llvm/IR/Constants.h"
19 #include "llvm/IR/InstrTypes.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/IR/ModuleSlotTracker.h"
23 #include "llvm/MC/MCAsmInfo.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/MC/TargetRegistry.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include "gtest/gtest.h"
28 
29 using namespace llvm;
30 
31 namespace {
32 
33 // Include helper functions to ease the manipulation of MachineFunctions.
34 #include "MFCommon.inc"
35 
36 TEST(MachineOperandTest, ChangeToTargetIndexTest) {
37   // Creating a MachineOperand to change it to TargetIndex
38   MachineOperand MO = MachineOperand::CreateImm(50);
39 
40   // Checking some precondition on the newly created
41   // MachineOperand.
42   ASSERT_TRUE(MO.isImm());
43   ASSERT_TRUE(MO.getImm() == 50);
44   ASSERT_FALSE(MO.isTargetIndex());
45 
46   // Changing to TargetIndex with some arbitrary values
47   // for index, offset and flags.
48   MO.ChangeToTargetIndex(74, 57, 12);
49 
50   // Checking that the mutation to TargetIndex happened
51   // correctly.
52   ASSERT_TRUE(MO.isTargetIndex());
53   ASSERT_TRUE(MO.getIndex() == 74);
54   ASSERT_TRUE(MO.getOffset() == 57);
55   ASSERT_TRUE(MO.getTargetFlags() == 12);
56 }
57 
58 TEST(MachineOperandTest, PrintRegisterMask) {
59   LLVMContext Ctx;
60   Module Mod("Module", Ctx);
61   auto MF = createMachineFunction(Ctx, Mod);
62 
63   uint32_t *Dummy = MF->allocateRegMask();
64   MachineOperand MO = MachineOperand::CreateRegMask(Dummy);
65 
66   // Checking some preconditions on the newly created
67   // MachineOperand.
68   ASSERT_TRUE(MO.isRegMask());
69   ASSERT_TRUE(MO.getRegMask() == Dummy);
70 
71   // Print a MachineOperand containing a RegMask. Here we check that without a
72   // TRI and IntrinsicInfo we still print a less detailed regmask.
73   std::string str;
74   raw_string_ostream OS(str);
75   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
76   ASSERT_TRUE(str == "<regmask ...>");
77 }
78 
79 TEST(MachineOperandTest, PrintSubReg) {
80   // Create a MachineOperand with RegNum=1 and SubReg=5.
81   MachineOperand MO = MachineOperand::CreateReg(
82       /*Reg=*/1, /*isDef=*/false, /*isImp=*/false, /*isKill=*/false,
83       /*isDead=*/false, /*isUndef=*/false, /*isEarlyClobber=*/false,
84       /*SubReg=*/5, /*isDebug=*/false, /*isInternalRead=*/false);
85 
86   // Checking some preconditions on the newly created
87   // MachineOperand.
88   ASSERT_TRUE(MO.isReg());
89   ASSERT_TRUE(MO.getReg() == 1);
90   ASSERT_TRUE(MO.getSubReg() == 5);
91 
92   // Print a MachineOperand containing a SubReg. Here we check that without a
93   // TRI and IntrinsicInfo we can still print the subreg index.
94   std::string str;
95   raw_string_ostream OS(str);
96   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
97   ASSERT_TRUE(str == "$physreg1.subreg5");
98 }
99 
100 TEST(MachineOperandTest, PrintCImm) {
101   LLVMContext Context;
102   APInt Int(128, UINT64_MAX);
103   ++Int;
104   ConstantInt *CImm = ConstantInt::get(Context, Int);
105   // Create a MachineOperand with an Imm=(UINT64_MAX + 1)
106   MachineOperand MO = MachineOperand::CreateCImm(CImm);
107 
108   // Checking some preconditions on the newly created
109   // MachineOperand.
110   ASSERT_TRUE(MO.isCImm());
111   ASSERT_TRUE(MO.getCImm() == CImm);
112   ASSERT_TRUE(MO.getCImm()->getValue() == Int);
113 
114   // Print a MachineOperand containing a SubReg. Here we check that without a
115   // TRI and IntrinsicInfo we can still print the subreg index.
116   std::string str;
117   raw_string_ostream OS(str);
118   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
119   ASSERT_TRUE(str == "i128 18446744073709551616");
120 }
121 
122 TEST(MachineOperandTest, PrintSubRegIndex) {
123   // Create a MachineOperand with an immediate and print it as a subreg index.
124   MachineOperand MO = MachineOperand::CreateImm(3);
125 
126   // Checking some preconditions on the newly created
127   // MachineOperand.
128   ASSERT_TRUE(MO.isImm());
129   ASSERT_TRUE(MO.getImm() == 3);
130 
131   // Print a MachineOperand containing a SubRegIdx. Here we check that without a
132   // TRI and IntrinsicInfo we can print the operand as a subreg index.
133   std::string str;
134   raw_string_ostream OS(str);
135   MachineOperand::printSubRegIdx(OS, MO.getImm(), nullptr);
136   ASSERT_TRUE(str == "%subreg.3");
137 }
138 
139 TEST(MachineOperandTest, PrintCPI) {
140   // Create a MachineOperand with a constant pool index and print it.
141   MachineOperand MO = MachineOperand::CreateCPI(0, 8);
142 
143   // Checking some preconditions on the newly created
144   // MachineOperand.
145   ASSERT_TRUE(MO.isCPI());
146   ASSERT_TRUE(MO.getIndex() == 0);
147   ASSERT_TRUE(MO.getOffset() == 8);
148 
149   // Print a MachineOperand containing a constant pool index and a positive
150   // offset.
151   std::string str;
152   {
153     raw_string_ostream OS(str);
154     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
155     ASSERT_TRUE(str == "%const.0 + 8");
156   }
157 
158   str.clear();
159 
160   MO.setOffset(-12);
161 
162   // Print a MachineOperand containing a constant pool index and a negative
163   // offset.
164   {
165     raw_string_ostream OS(str);
166     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
167     ASSERT_TRUE(str == "%const.0 - 12");
168   }
169 }
170 
171 TEST(MachineOperandTest, PrintTargetIndexName) {
172   // Create a MachineOperand with a target index and print it.
173   MachineOperand MO = MachineOperand::CreateTargetIndex(0, 8);
174 
175   // Checking some preconditions on the newly created
176   // MachineOperand.
177   ASSERT_TRUE(MO.isTargetIndex());
178   ASSERT_TRUE(MO.getIndex() == 0);
179   ASSERT_TRUE(MO.getOffset() == 8);
180 
181   // Print a MachineOperand containing a target index and a positive offset.
182   std::string str;
183   {
184     raw_string_ostream OS(str);
185     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
186     ASSERT_TRUE(str == "target-index(<unknown>) + 8");
187   }
188 
189   str.clear();
190 
191   MO.setOffset(-12);
192 
193   // Print a MachineOperand containing a target index and a negative offset.
194   {
195     raw_string_ostream OS(str);
196     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
197     ASSERT_TRUE(str == "target-index(<unknown>) - 12");
198   }
199 }
200 
201 TEST(MachineOperandTest, PrintJumpTableIndex) {
202   // Create a MachineOperand with a jump-table index and print it.
203   MachineOperand MO = MachineOperand::CreateJTI(3);
204 
205   // Checking some preconditions on the newly created
206   // MachineOperand.
207   ASSERT_TRUE(MO.isJTI());
208   ASSERT_TRUE(MO.getIndex() == 3);
209 
210   // Print a MachineOperand containing a jump-table index.
211   std::string str;
212   raw_string_ostream OS(str);
213   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
214   ASSERT_TRUE(str == "%jump-table.3");
215 }
216 
217 TEST(MachineOperandTest, PrintExternalSymbol) {
218   // Create a MachineOperand with an external symbol and print it.
219   MachineOperand MO = MachineOperand::CreateES("foo");
220 
221   // Checking some preconditions on the newly created
222   // MachineOperand.
223   ASSERT_TRUE(MO.isSymbol());
224   ASSERT_TRUE(MO.getSymbolName() == StringRef("foo"));
225 
226   // Print a MachineOperand containing an external symbol and no offset.
227   std::string str;
228   {
229     raw_string_ostream OS(str);
230     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
231     ASSERT_TRUE(str == "&foo");
232   }
233 
234   str.clear();
235   MO.setOffset(12);
236 
237   // Print a MachineOperand containing an external symbol and a positive offset.
238   {
239     raw_string_ostream OS(str);
240     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
241     ASSERT_TRUE(str == "&foo + 12");
242   }
243 
244   str.clear();
245   MO.setOffset(-12);
246 
247   // Print a MachineOperand containing an external symbol and a negative offset.
248   {
249     raw_string_ostream OS(str);
250     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
251     ASSERT_TRUE(str == "&foo - 12");
252   }
253 }
254 
255 TEST(MachineOperandTest, PrintGlobalAddress) {
256   LLVMContext Ctx;
257   Module M("MachineOperandGVTest", Ctx);
258   M.getOrInsertGlobal("foo", Type::getInt32Ty(Ctx));
259 
260   GlobalValue *GV = M.getNamedValue("foo");
261 
262   // Create a MachineOperand with a global address and a positive offset and
263   // print it.
264   MachineOperand MO = MachineOperand::CreateGA(GV, 12);
265 
266   // Checking some preconditions on the newly created
267   // MachineOperand.
268   ASSERT_TRUE(MO.isGlobal());
269   ASSERT_TRUE(MO.getGlobal() == GV);
270   ASSERT_TRUE(MO.getOffset() == 12);
271 
272   std::string str;
273   // Print a MachineOperand containing a global address and a positive offset.
274   {
275     raw_string_ostream OS(str);
276     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
277     ASSERT_TRUE(str == "@foo + 12");
278   }
279 
280   str.clear();
281   MO.setOffset(-12);
282 
283   // Print a MachineOperand containing a global address and a negative offset.
284   {
285     raw_string_ostream OS(str);
286     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
287     ASSERT_TRUE(str == "@foo - 12");
288   }
289 }
290 
291 TEST(MachineOperandTest, PrintRegisterLiveOut) {
292   // Create a MachineOperand with a register live out list and print it.
293   uint32_t Mask = 0;
294   MachineOperand MO = MachineOperand::CreateRegLiveOut(&Mask);
295 
296   // Checking some preconditions on the newly created
297   // MachineOperand.
298   ASSERT_TRUE(MO.isRegLiveOut());
299   ASSERT_TRUE(MO.getRegLiveOut() == &Mask);
300 
301   std::string str;
302   // Print a MachineOperand containing a register live out list without a TRI.
303   raw_string_ostream OS(str);
304   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
305   ASSERT_TRUE(str == "liveout(<unknown>)");
306 }
307 
308 TEST(MachineOperandTest, PrintMetadata) {
309   LLVMContext Ctx;
310   Module M("MachineOperandMDNodeTest", Ctx);
311   NamedMDNode *MD = M.getOrInsertNamedMetadata("namedmd");
312   ModuleSlotTracker MST(&M);
313   Metadata *MDS = MDString::get(Ctx, "foo");
314   MDNode *Node = MDNode::get(Ctx, MDS);
315   MD->addOperand(Node);
316 
317   // Create a MachineOperand with a metadata and print it.
318   MachineOperand MO = MachineOperand::CreateMetadata(Node);
319 
320   // Checking some preconditions on the newly created
321   // MachineOperand.
322   ASSERT_TRUE(MO.isMetadata());
323   ASSERT_TRUE(MO.getMetadata() == Node);
324 
325   std::string str;
326   // Print a MachineOperand containing a metadata node.
327   raw_string_ostream OS(str);
328   MO.print(OS, MST, LLT{}, /*OpIdx*/~0U, /*PrintDef=*/false, /*IsStandalone=*/false,
329            /*ShouldPrintRegisterTies=*/false, 0, /*TRI=*/nullptr,
330            /*IntrinsicInfo=*/nullptr);
331   ASSERT_TRUE(str == "!0");
332 }
333 
334 TEST(MachineOperandTest, PrintMCSymbol) {
335   MCAsmInfo MAI;
336   Triple T = Triple("unknown-unknown-unknown");
337   MCContext Ctx(T, &MAI, /*MRI=*/nullptr, /*MSTI=*/nullptr);
338   MCSymbol *Sym = Ctx.getOrCreateSymbol("foo");
339 
340   // Create a MachineOperand with a metadata and print it.
341   MachineOperand MO = MachineOperand::CreateMCSymbol(Sym);
342 
343   // Checking some preconditions on the newly created
344   // MachineOperand.
345   ASSERT_TRUE(MO.isMCSymbol());
346   ASSERT_TRUE(MO.getMCSymbol() == Sym);
347 
348   std::string str;
349   // Print a MachineOperand containing a metadata node.
350   raw_string_ostream OS(str);
351   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
352   ASSERT_TRUE(str == "<mcsymbol foo>");
353 }
354 
355 TEST(MachineOperandTest, PrintCFI) {
356   // Create a MachineOperand with a CFI index but no function and print it.
357   MachineOperand MO = MachineOperand::CreateCFIIndex(8);
358 
359   // Checking some preconditions on the newly created
360   // MachineOperand.
361   ASSERT_TRUE(MO.isCFIIndex());
362   ASSERT_TRUE(MO.getCFIIndex() == 8);
363 
364   std::string str;
365   // Print a MachineOperand containing a CFI Index node but no machine function
366   // attached to it.
367   raw_string_ostream OS(str);
368   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
369   ASSERT_TRUE(str == "<cfi directive>");
370 }
371 
372 TEST(MachineOperandTest, PrintIntrinsicID) {
373   // Create a MachineOperand with a generic intrinsic ID.
374   MachineOperand MO = MachineOperand::CreateIntrinsicID(Intrinsic::bswap);
375 
376   // Checking some preconditions on the newly created
377   // MachineOperand.
378   ASSERT_TRUE(MO.isIntrinsicID());
379   ASSERT_TRUE(MO.getIntrinsicID() == Intrinsic::bswap);
380 
381   std::string str;
382   {
383     // Print a MachineOperand containing a generic intrinsic ID.
384     raw_string_ostream OS(str);
385     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
386     ASSERT_TRUE(str == "intrinsic(@llvm.bswap)");
387   }
388 
389   str.clear();
390   // Set a target-specific intrinsic.
391   MO = MachineOperand::CreateIntrinsicID((Intrinsic::ID)-1);
392   {
393     // Print a MachineOperand containing a target-specific intrinsic ID but not
394     // IntrinsicInfo.
395     raw_string_ostream OS(str);
396     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
397     ASSERT_TRUE(str == "intrinsic(4294967295)");
398   }
399 }
400 
401 TEST(MachineOperandTest, PrintPredicate) {
402   // Create a MachineOperand with a generic intrinsic ID.
403   MachineOperand MO = MachineOperand::CreatePredicate(CmpInst::ICMP_EQ);
404 
405   // Checking some preconditions on the newly created
406   // MachineOperand.
407   ASSERT_TRUE(MO.isPredicate());
408   ASSERT_TRUE(MO.getPredicate() == CmpInst::ICMP_EQ);
409 
410   std::string str;
411   // Print a MachineOperand containing a int predicate ICMP_EQ.
412   raw_string_ostream OS(str);
413   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
414   ASSERT_TRUE(str == "intpred(eq)");
415 }
416 
417 TEST(MachineOperandTest, HashValue) {
418   char SymName1[] = "test";
419   char SymName2[] = "test";
420   MachineOperand MO1 = MachineOperand::CreateES(SymName1);
421   MachineOperand MO2 = MachineOperand::CreateES(SymName2);
422   ASSERT_NE(SymName1, SymName2);
423   ASSERT_EQ(hash_value(MO1), hash_value(MO2));
424   ASSERT_TRUE(MO1.isIdenticalTo(MO2));
425 }
426 
427 } // end namespace
428