xref: /llvm-project/llvm/unittests/CodeGen/MachineOperandTest.cpp (revision 2db59382db874146e7bc53c490188ca2767078f6)
1 //===- MachineOperandTest.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/MachineOperand.h"
11 #include "llvm/ADT/ilist_node.h"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/LLVMContext.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/IR/ModuleSlotTracker.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include "gtest/gtest.h"
18 
19 using namespace llvm;
20 
21 namespace {
22 
23 TEST(MachineOperandTest, ChangeToTargetIndexTest) {
24   // Creating a MachineOperand to change it to TargetIndex
25   MachineOperand MO = MachineOperand::CreateImm(50);
26 
27   // Checking some precondition on the newly created
28   // MachineOperand.
29   ASSERT_TRUE(MO.isImm());
30   ASSERT_TRUE(MO.getImm() == 50);
31   ASSERT_FALSE(MO.isTargetIndex());
32 
33   // Changing to TargetIndex with some arbitrary values
34   // for index, offset and flags.
35   MO.ChangeToTargetIndex(74, 57, 12);
36 
37   // Checking that the mutation to TargetIndex happened
38   // correctly.
39   ASSERT_TRUE(MO.isTargetIndex());
40   ASSERT_TRUE(MO.getIndex() == 74);
41   ASSERT_TRUE(MO.getOffset() == 57);
42   ASSERT_TRUE(MO.getTargetFlags() == 12);
43 }
44 
45 TEST(MachineOperandTest, PrintRegisterMask) {
46   uint32_t Dummy;
47   MachineOperand MO = MachineOperand::CreateRegMask(&Dummy);
48 
49   // Checking some preconditions on the newly created
50   // MachineOperand.
51   ASSERT_TRUE(MO.isRegMask());
52   ASSERT_TRUE(MO.getRegMask() == &Dummy);
53 
54   // Print a MachineOperand containing a RegMask. Here we check that without a
55   // TRI and IntrinsicInfo we still print a less detailed regmask.
56   std::string str;
57   raw_string_ostream OS(str);
58   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
59   ASSERT_TRUE(OS.str() == "<regmask ...>");
60 }
61 
62 TEST(MachineOperandTest, PrintSubReg) {
63   // Create a MachineOperand with RegNum=1 and SubReg=5.
64   MachineOperand MO = MachineOperand::CreateReg(
65       /*Reg=*/1, /*isDef=*/false, /*isImp=*/false, /*isKill=*/false,
66       /*isDead=*/false, /*isUndef=*/false, /*isEarlyClobber=*/false,
67       /*SubReg=*/5, /*isDebug=*/false, /*isInternalRead=*/false);
68 
69   // Checking some preconditions on the newly created
70   // MachineOperand.
71   ASSERT_TRUE(MO.isReg());
72   ASSERT_TRUE(MO.getReg() == 1);
73   ASSERT_TRUE(MO.getSubReg() == 5);
74 
75   // Print a MachineOperand containing a SubReg. Here we check that without a
76   // TRI and IntrinsicInfo we can still print the subreg index.
77   std::string str;
78   raw_string_ostream OS(str);
79   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
80   ASSERT_TRUE(OS.str() == "%physreg1.subreg5");
81 }
82 
83 TEST(MachineOperandTest, PrintCImm) {
84   LLVMContext Context;
85   APInt Int(128, UINT64_MAX);
86   ++Int;
87   ConstantInt *CImm = ConstantInt::get(Context, Int);
88   // Create a MachineOperand with an Imm=(UINT64_MAX + 1)
89   MachineOperand MO = MachineOperand::CreateCImm(CImm);
90 
91   // Checking some preconditions on the newly created
92   // MachineOperand.
93   ASSERT_TRUE(MO.isCImm());
94   ASSERT_TRUE(MO.getCImm() == CImm);
95   ASSERT_TRUE(MO.getCImm()->getValue() == Int);
96 
97   // Print a MachineOperand containing a SubReg. Here we check that without a
98   // TRI and IntrinsicInfo we can still print the subreg index.
99   std::string str;
100   raw_string_ostream OS(str);
101   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
102   ASSERT_TRUE(OS.str() == "i128 18446744073709551616");
103 }
104 
105 TEST(MachineOperandTest, PrintSubRegIndex) {
106   // Create a MachineOperand with an immediate and print it as a subreg index.
107   MachineOperand MO = MachineOperand::CreateImm(3);
108 
109   // Checking some preconditions on the newly created
110   // MachineOperand.
111   ASSERT_TRUE(MO.isImm());
112   ASSERT_TRUE(MO.getImm() == 3);
113 
114   // Print a MachineOperand containing a SubRegIdx. Here we check that without a
115   // TRI and IntrinsicInfo we can print the operand as a subreg index.
116   std::string str;
117   raw_string_ostream OS(str);
118   ModuleSlotTracker DummyMST(nullptr);
119   MachineOperand::printSubregIdx(OS, MO.getImm(), nullptr);
120   ASSERT_TRUE(OS.str() == "%subreg.3");
121 }
122 
123 TEST(MachineOperandTest, PrintCPI) {
124   // Create a MachineOperand with a constant pool index and print it.
125   MachineOperand MO = MachineOperand::CreateCPI(0, 8);
126 
127   // Checking some preconditions on the newly created
128   // MachineOperand.
129   ASSERT_TRUE(MO.isCPI());
130   ASSERT_TRUE(MO.getIndex() == 0);
131   ASSERT_TRUE(MO.getOffset() == 8);
132 
133   // Print a MachineOperand containing a constant pool index and a positive
134   // offset.
135   std::string str;
136   {
137     raw_string_ostream OS(str);
138     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
139     ASSERT_TRUE(OS.str() == "%const.0 + 8");
140   }
141 
142   str.clear();
143 
144   MO.setOffset(-12);
145 
146   // Print a MachineOperand containing a constant pool index and a negative
147   // offset.
148   {
149     raw_string_ostream OS(str);
150     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
151     ASSERT_TRUE(OS.str() == "%const.0 - 12");
152   }
153 }
154 
155 TEST(MachineOperandTest, PrintTargetIndexName) {
156   // Create a MachineOperand with a target index and print it.
157   MachineOperand MO = MachineOperand::CreateTargetIndex(0, 8);
158 
159   // Checking some preconditions on the newly created
160   // MachineOperand.
161   ASSERT_TRUE(MO.isTargetIndex());
162   ASSERT_TRUE(MO.getIndex() == 0);
163   ASSERT_TRUE(MO.getOffset() == 8);
164 
165   // Print a MachineOperand containing a target index and a positive offset.
166   std::string str;
167   {
168     raw_string_ostream OS(str);
169     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
170     ASSERT_TRUE(OS.str() == "target-index(<unknown>) + 8");
171   }
172 
173   str.clear();
174 
175   MO.setOffset(-12);
176 
177   // Print a MachineOperand containing a target index and a negative offset.
178   {
179     raw_string_ostream OS(str);
180     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
181     ASSERT_TRUE(OS.str() == "target-index(<unknown>) - 12");
182   }
183 }
184 
185 TEST(MachineOperandTest, PrintJumpTableIndex) {
186   // Create a MachineOperand with a jump-table index and print it.
187   MachineOperand MO = MachineOperand::CreateJTI(3);
188 
189   // Checking some preconditions on the newly created
190   // MachineOperand.
191   ASSERT_TRUE(MO.isJTI());
192   ASSERT_TRUE(MO.getIndex() == 3);
193 
194   // Print a MachineOperand containing a jump-table index.
195   std::string str;
196   raw_string_ostream OS(str);
197   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
198   ASSERT_TRUE(OS.str() == "%jump-table.3");
199 }
200 
201 TEST(MachineOperandTest, PrintExternalSymbol) {
202   // Create a MachineOperand with an external symbol and print it.
203   MachineOperand MO = MachineOperand::CreateES("foo");
204 
205   // Checking some preconditions on the newly created
206   // MachineOperand.
207   ASSERT_TRUE(MO.isSymbol());
208   ASSERT_TRUE(MO.getSymbolName() == StringRef("foo"));
209 
210   // Print a MachineOperand containing an external symbol and no offset.
211   std::string str;
212   {
213     raw_string_ostream OS(str);
214     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
215     ASSERT_TRUE(OS.str() == "$foo");
216   }
217 
218   str.clear();
219   MO.setOffset(12);
220 
221   // Print a MachineOperand containing an external symbol and a positive offset.
222   {
223     raw_string_ostream OS(str);
224     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
225     ASSERT_TRUE(OS.str() == "$foo + 12");
226   }
227 
228   str.clear();
229   MO.setOffset(-12);
230 
231   // Print a MachineOperand containing an external symbol and a negative offset.
232   {
233     raw_string_ostream OS(str);
234     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
235     ASSERT_TRUE(OS.str() == "$foo - 12");
236   }
237 }
238 
239 TEST(MachineOperandTest, PrintGlobalAddress) {
240   LLVMContext Ctx;
241   Module M("MachineOperandGVTest", Ctx);
242   M.getOrInsertGlobal("foo", Type::getInt32Ty(Ctx));
243 
244   GlobalValue *GV = M.getNamedValue("foo");
245 
246   // Create a MachineOperand with a global address and a positive offset and
247   // print it.
248   MachineOperand MO = MachineOperand::CreateGA(GV, 12);
249 
250   // Checking some preconditions on the newly created
251   // MachineOperand.
252   ASSERT_TRUE(MO.isGlobal());
253   ASSERT_TRUE(MO.getGlobal() == GV);
254   ASSERT_TRUE(MO.getOffset() == 12);
255 
256   std::string str;
257   // Print a MachineOperand containing a global address and a positive offset.
258   {
259     raw_string_ostream OS(str);
260     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
261     ASSERT_TRUE(OS.str() == "@foo + 12");
262   }
263 
264   str.clear();
265   MO.setOffset(-12);
266 
267   // Print a MachineOperand containing a global address and a negative offset.
268   {
269     raw_string_ostream OS(str);
270     MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
271     ASSERT_TRUE(OS.str() == "@foo - 12");
272   }
273 }
274 
275 TEST(MachineOperandTest, PrintRegisterLiveOut) {
276   // Create a MachineOperand with a register live out list and print it.
277   uint32_t Mask = 0;
278   MachineOperand MO = MachineOperand::CreateRegLiveOut(&Mask);
279 
280   // Checking some preconditions on the newly created
281   // MachineOperand.
282   ASSERT_TRUE(MO.isRegLiveOut());
283   ASSERT_TRUE(MO.getRegLiveOut() == &Mask);
284 
285   std::string str;
286   // Print a MachineOperand containing a register live out list without a TRI.
287   raw_string_ostream OS(str);
288   MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr);
289   ASSERT_TRUE(OS.str() == "liveout(<unknown>)");
290 }
291 
292 TEST(MachineOperandTest, PrintMetadata) {
293   LLVMContext Ctx;
294   Module M("MachineOperandMDNodeTest", Ctx);
295   NamedMDNode *MD = M.getOrInsertNamedMetadata("namedmd");
296   ModuleSlotTracker DummyMST(&M);
297   Metadata *MDS = MDString::get(Ctx, "foo");
298   MDNode *Node = MDNode::get(Ctx, MDS);
299   MD->addOperand(Node);
300 
301   // Create a MachineOperand with a metadata and print it.
302   MachineOperand MO = MachineOperand::CreateMetadata(Node);
303 
304   // Checking some preconditions on the newly created
305   // MachineOperand.
306   ASSERT_TRUE(MO.isMetadata());
307   ASSERT_TRUE(MO.getMetadata() == Node);
308 
309   std::string str;
310   // Print a MachineOperand containing a metadata node.
311   raw_string_ostream OS(str);
312   MO.print(OS, DummyMST, LLT{}, false, false, 0, /*TRI=*/nullptr,
313            /*IntrinsicInfo=*/nullptr);
314   ASSERT_TRUE(OS.str() == "!0");
315 }
316 
317 } // end namespace
318