MachineOperandTest.cpp 13 KB

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