MachineInstrTest.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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. #include "llvm/CodeGen/MachineBasicBlock.h"
  9. #include "llvm/CodeGen/MachineInstr.h"
  10. #include "llvm/CodeGen/MachineFunction.h"
  11. #include "llvm/CodeGen/MachineModuleInfo.h"
  12. #include "llvm/CodeGen/TargetFrameLowering.h"
  13. #include "llvm/CodeGen/TargetInstrInfo.h"
  14. #include "llvm/CodeGen/TargetLowering.h"
  15. #include "llvm/CodeGen/TargetSubtargetInfo.h"
  16. #include "llvm/IR/DebugInfoMetadata.h"
  17. #include "llvm/IR/ModuleSlotTracker.h"
  18. #include "llvm/Support/TargetRegistry.h"
  19. #include "llvm/Support/TargetSelect.h"
  20. #include "llvm/Target/TargetMachine.h"
  21. #include "llvm/Target/TargetOptions.h"
  22. #include "gtest/gtest.h"
  23. using namespace llvm;
  24. namespace {
  25. // Add a few Bogus backend classes so we can create MachineInstrs without
  26. // depending on a real target.
  27. class BogusTargetLowering : public TargetLowering {
  28. public:
  29. BogusTargetLowering(TargetMachine &TM) : TargetLowering(TM) {}
  30. };
  31. class BogusFrameLowering : public TargetFrameLowering {
  32. public:
  33. BogusFrameLowering()
  34. : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 4) {}
  35. void emitPrologue(MachineFunction &MF,
  36. MachineBasicBlock &MBB) const override {}
  37. void emitEpilogue(MachineFunction &MF,
  38. MachineBasicBlock &MBB) const override {}
  39. bool hasFP(const MachineFunction &MF) const override { return false; }
  40. };
  41. static TargetRegisterClass *const BogusRegisterClasses[] = {nullptr};
  42. class BogusRegisterInfo : public TargetRegisterInfo {
  43. public:
  44. BogusRegisterInfo()
  45. : TargetRegisterInfo(nullptr, BogusRegisterClasses, BogusRegisterClasses,
  46. nullptr, nullptr, LaneBitmask(~0u), nullptr) {
  47. InitMCRegisterInfo(nullptr, 0, 0, 0, nullptr, 0, nullptr, 0, nullptr,
  48. nullptr, nullptr, nullptr, nullptr, 0, nullptr, nullptr);
  49. }
  50. const MCPhysReg *
  51. getCalleeSavedRegs(const MachineFunction *MF) const override {
  52. return nullptr;
  53. }
  54. ArrayRef<const uint32_t *> getRegMasks() const override { return None; }
  55. ArrayRef<const char *> getRegMaskNames() const override { return None; }
  56. BitVector getReservedRegs(const MachineFunction &MF) const override {
  57. return BitVector();
  58. }
  59. const RegClassWeight &
  60. getRegClassWeight(const TargetRegisterClass *RC) const override {
  61. static RegClassWeight Bogus{1, 16};
  62. return Bogus;
  63. }
  64. unsigned getRegUnitWeight(unsigned RegUnit) const override { return 1; }
  65. unsigned getNumRegPressureSets() const override { return 0; }
  66. const char *getRegPressureSetName(unsigned Idx) const override {
  67. return "bogus";
  68. }
  69. unsigned getRegPressureSetLimit(const MachineFunction &MF,
  70. unsigned Idx) const override {
  71. return 0;
  72. }
  73. const int *
  74. getRegClassPressureSets(const TargetRegisterClass *RC) const override {
  75. static const int Bogus[] = {0, -1};
  76. return &Bogus[0];
  77. }
  78. const int *getRegUnitPressureSets(unsigned RegUnit) const override {
  79. static const int Bogus[] = {0, -1};
  80. return &Bogus[0];
  81. }
  82. Register getFrameRegister(const MachineFunction &MF) const override {
  83. return 0;
  84. }
  85. void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
  86. unsigned FIOperandNum,
  87. RegScavenger *RS = nullptr) const override {}
  88. };
  89. class BogusSubtarget : public TargetSubtargetInfo {
  90. public:
  91. BogusSubtarget(TargetMachine &TM)
  92. : TargetSubtargetInfo(Triple(""), "", "", {}, {}, nullptr, nullptr,
  93. nullptr, nullptr, nullptr, nullptr),
  94. FL(), TL(TM) {}
  95. ~BogusSubtarget() override {}
  96. const TargetFrameLowering *getFrameLowering() const override { return &FL; }
  97. const TargetLowering *getTargetLowering() const override { return &TL; }
  98. const TargetInstrInfo *getInstrInfo() const override { return &TII; }
  99. const TargetRegisterInfo *getRegisterInfo() const override { return &TRI; }
  100. private:
  101. BogusFrameLowering FL;
  102. BogusRegisterInfo TRI;
  103. BogusTargetLowering TL;
  104. TargetInstrInfo TII;
  105. };
  106. class BogusTargetMachine : public LLVMTargetMachine {
  107. public:
  108. BogusTargetMachine()
  109. : LLVMTargetMachine(Target(), "", Triple(""), "", "", TargetOptions(),
  110. Reloc::Static, CodeModel::Small, CodeGenOpt::Default),
  111. ST(*this) {}
  112. ~BogusTargetMachine() override {}
  113. const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override {
  114. return &ST;
  115. }
  116. private:
  117. BogusSubtarget ST;
  118. };
  119. std::unique_ptr<BogusTargetMachine> createTargetMachine() {
  120. return std::make_unique<BogusTargetMachine>();
  121. }
  122. std::unique_ptr<MachineFunction> createMachineFunction() {
  123. LLVMContext Ctx;
  124. Module M("Module", Ctx);
  125. auto Type = FunctionType::get(Type::getVoidTy(Ctx), false);
  126. auto F = Function::Create(Type, GlobalValue::ExternalLinkage, "Test", &M);
  127. auto TM = createTargetMachine();
  128. unsigned FunctionNum = 42;
  129. MachineModuleInfo MMI(TM.get());
  130. const TargetSubtargetInfo &STI = *TM->getSubtargetImpl(*F);
  131. return std::make_unique<MachineFunction>(*F, *TM, STI, FunctionNum, MMI);
  132. }
  133. // This test makes sure that MachineInstr::isIdenticalTo handles Defs correctly
  134. // for various combinations of IgnoreDefs, and also that it is symmetrical.
  135. TEST(IsIdenticalToTest, DifferentDefs) {
  136. auto MF = createMachineFunction();
  137. unsigned short NumOps = 2;
  138. unsigned char NumDefs = 1;
  139. MCOperandInfo OpInfo[] = {
  140. {0, 0, MCOI::OPERAND_REGISTER, 0},
  141. {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
  142. MCInstrDesc MCID = {
  143. 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef,
  144. 0, nullptr, nullptr, OpInfo, 0, nullptr};
  145. // Create two MIs with different virtual reg defs and the same uses.
  146. unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does.
  147. unsigned VirtualDef2 = -43;
  148. unsigned VirtualUse = -44;
  149. auto MI1 = MF->CreateMachineInstr(MCID, DebugLoc());
  150. MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  151. MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
  152. auto MI2 = MF->CreateMachineInstr(MCID, DebugLoc());
  153. MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  154. MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
  155. // Check that they are identical when we ignore virtual register defs, but not
  156. // when we check defs.
  157. ASSERT_FALSE(MI1->isIdenticalTo(*MI2, MachineInstr::CheckDefs));
  158. ASSERT_FALSE(MI2->isIdenticalTo(*MI1, MachineInstr::CheckDefs));
  159. ASSERT_TRUE(MI1->isIdenticalTo(*MI2, MachineInstr::IgnoreVRegDefs));
  160. ASSERT_TRUE(MI2->isIdenticalTo(*MI1, MachineInstr::IgnoreVRegDefs));
  161. // Create two MIs with different virtual reg defs, and a def or use of a
  162. // sentinel register.
  163. unsigned SentinelReg = 0;
  164. auto MI3 = MF->CreateMachineInstr(MCID, DebugLoc());
  165. MI3->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  166. MI3->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
  167. auto MI4 = MF->CreateMachineInstr(MCID, DebugLoc());
  168. MI4->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  169. MI4->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
  170. // Check that they are never identical.
  171. ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::CheckDefs));
  172. ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::CheckDefs));
  173. ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::IgnoreVRegDefs));
  174. ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::IgnoreVRegDefs));
  175. }
  176. // Check that MachineInstrExpressionTrait::isEqual is symmetric and in sync with
  177. // MachineInstrExpressionTrait::getHashValue
  178. void checkHashAndIsEqualMatch(MachineInstr *MI1, MachineInstr *MI2) {
  179. bool IsEqual1 = MachineInstrExpressionTrait::isEqual(MI1, MI2);
  180. bool IsEqual2 = MachineInstrExpressionTrait::isEqual(MI2, MI1);
  181. ASSERT_EQ(IsEqual1, IsEqual2);
  182. auto Hash1 = MachineInstrExpressionTrait::getHashValue(MI1);
  183. auto Hash2 = MachineInstrExpressionTrait::getHashValue(MI2);
  184. ASSERT_EQ(IsEqual1, Hash1 == Hash2);
  185. }
  186. // This test makes sure that MachineInstrExpressionTraits::isEqual is in sync
  187. // with MachineInstrExpressionTraits::getHashValue.
  188. TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) {
  189. auto MF = createMachineFunction();
  190. unsigned short NumOps = 2;
  191. unsigned char NumDefs = 1;
  192. MCOperandInfo OpInfo[] = {
  193. {0, 0, MCOI::OPERAND_REGISTER, 0},
  194. {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
  195. MCInstrDesc MCID = {
  196. 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef,
  197. 0, nullptr, nullptr, OpInfo, 0, nullptr};
  198. // Define a series of instructions with different kinds of operands and make
  199. // sure that the hash function is consistent with isEqual for various
  200. // combinations of them.
  201. unsigned VirtualDef1 = -42;
  202. unsigned VirtualDef2 = -43;
  203. unsigned VirtualReg = -44;
  204. unsigned SentinelReg = 0;
  205. unsigned PhysicalReg = 45;
  206. auto VD1VU = MF->CreateMachineInstr(MCID, DebugLoc());
  207. VD1VU->addOperand(*MF,
  208. MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  209. VD1VU->addOperand(*MF,
  210. MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
  211. auto VD2VU = MF->CreateMachineInstr(MCID, DebugLoc());
  212. VD2VU->addOperand(*MF,
  213. MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  214. VD2VU->addOperand(*MF,
  215. MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
  216. auto VD1SU = MF->CreateMachineInstr(MCID, DebugLoc());
  217. VD1SU->addOperand(*MF,
  218. MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  219. VD1SU->addOperand(*MF,
  220. MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
  221. auto VD1SD = MF->CreateMachineInstr(MCID, DebugLoc());
  222. VD1SD->addOperand(*MF,
  223. MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  224. VD1SD->addOperand(*MF,
  225. MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
  226. auto VD2PU = MF->CreateMachineInstr(MCID, DebugLoc());
  227. VD2PU->addOperand(*MF,
  228. MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  229. VD2PU->addOperand(*MF,
  230. MachineOperand::CreateReg(PhysicalReg, /*isDef*/ false));
  231. auto VD2PD = MF->CreateMachineInstr(MCID, DebugLoc());
  232. VD2PD->addOperand(*MF,
  233. MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  234. VD2PD->addOperand(*MF,
  235. MachineOperand::CreateReg(PhysicalReg, /*isDef*/ true));
  236. checkHashAndIsEqualMatch(VD1VU, VD2VU);
  237. checkHashAndIsEqualMatch(VD1VU, VD1SU);
  238. checkHashAndIsEqualMatch(VD1VU, VD1SD);
  239. checkHashAndIsEqualMatch(VD1VU, VD2PU);
  240. checkHashAndIsEqualMatch(VD1VU, VD2PD);
  241. checkHashAndIsEqualMatch(VD2VU, VD1SU);
  242. checkHashAndIsEqualMatch(VD2VU, VD1SD);
  243. checkHashAndIsEqualMatch(VD2VU, VD2PU);
  244. checkHashAndIsEqualMatch(VD2VU, VD2PD);
  245. checkHashAndIsEqualMatch(VD1SU, VD1SD);
  246. checkHashAndIsEqualMatch(VD1SU, VD2PU);
  247. checkHashAndIsEqualMatch(VD1SU, VD2PD);
  248. checkHashAndIsEqualMatch(VD1SD, VD2PU);
  249. checkHashAndIsEqualMatch(VD1SD, VD2PD);
  250. checkHashAndIsEqualMatch(VD2PU, VD2PD);
  251. }
  252. TEST(MachineInstrPrintingTest, DebugLocPrinting) {
  253. auto MF = createMachineFunction();
  254. MCOperandInfo OpInfo{0, 0, MCOI::OPERAND_REGISTER, 0};
  255. MCInstrDesc MCID = {0, 1, 1, 0, 0, 0,
  256. 0, nullptr, nullptr, &OpInfo, 0, nullptr};
  257. LLVMContext Ctx;
  258. DIFile *DIF = DIFile::getDistinct(Ctx, "filename", "");
  259. DISubprogram *DIS = DISubprogram::getDistinct(
  260. Ctx, nullptr, "", "", DIF, 0, nullptr, 0, nullptr, 0, 0, DINode::FlagZero,
  261. DISubprogram::SPFlagZero, 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. std::string str;
  267. raw_string_ostream OS(str);
  268. MI->print(OS, /*IsStandalone*/true, /*SkipOpers*/false, /*SkipDebugLoc*/false,
  269. /*AddNewLine*/false);
  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. TEST(MachineInstrSpan, DistanceBegin) {
  276. auto MF = createMachineFunction();
  277. auto MBB = MF->CreateMachineBasicBlock();
  278. MCInstrDesc MCID = {0, 0, 0, 0, 0, 0,
  279. 0, nullptr, nullptr, nullptr, 0, nullptr};
  280. auto MII = MBB->begin();
  281. MachineInstrSpan MIS(MII, MBB);
  282. ASSERT_TRUE(MIS.empty());
  283. auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
  284. MBB->insert(MII, MI);
  285. ASSERT_TRUE(std::distance(MIS.begin(), MII) == 1);
  286. }
  287. TEST(MachineInstrSpan, DistanceEnd) {
  288. auto MF = createMachineFunction();
  289. auto MBB = MF->CreateMachineBasicBlock();
  290. MCInstrDesc MCID = {0, 0, 0, 0, 0, 0,
  291. 0, nullptr, nullptr, nullptr, 0, nullptr};
  292. auto MII = MBB->end();
  293. MachineInstrSpan MIS(MII, MBB);
  294. ASSERT_TRUE(MIS.empty());
  295. auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
  296. MBB->insert(MII, MI);
  297. ASSERT_TRUE(std::distance(MIS.begin(), MII) == 1);
  298. }
  299. static_assert(is_trivially_copyable<MCOperand>::value, "trivially copyable");
  300. } // end namespace