MachineInstrTest.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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/MachineInstr.h"
  9. #include "llvm/CodeGen/MachineFunction.h"
  10. #include "llvm/CodeGen/MachineModuleInfo.h"
  11. #include "llvm/CodeGen/TargetFrameLowering.h"
  12. #include "llvm/CodeGen/TargetInstrInfo.h"
  13. #include "llvm/CodeGen/TargetLowering.h"
  14. #include "llvm/CodeGen/TargetSubtargetInfo.h"
  15. #include "llvm/IR/DebugInfoMetadata.h"
  16. #include "llvm/IR/ModuleSlotTracker.h"
  17. #include "llvm/Support/TargetRegistry.h"
  18. #include "llvm/Support/TargetSelect.h"
  19. #include "llvm/Target/TargetMachine.h"
  20. #include "llvm/Target/TargetOptions.h"
  21. #include "gtest/gtest.h"
  22. using namespace llvm;
  23. namespace {
  24. // Add a few Bogus backend classes so we can create MachineInstrs without
  25. // depending on a real target.
  26. class BogusTargetLowering : public TargetLowering {
  27. public:
  28. BogusTargetLowering(TargetMachine &TM) : TargetLowering(TM) {}
  29. };
  30. class BogusFrameLowering : public TargetFrameLowering {
  31. public:
  32. BogusFrameLowering()
  33. : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 4) {}
  34. void emitPrologue(MachineFunction &MF,
  35. MachineBasicBlock &MBB) const override {}
  36. void emitEpilogue(MachineFunction &MF,
  37. MachineBasicBlock &MBB) const override {}
  38. bool hasFP(const MachineFunction &MF) const override { return false; }
  39. };
  40. class BogusSubtarget : public TargetSubtargetInfo {
  41. public:
  42. BogusSubtarget(TargetMachine &TM)
  43. : TargetSubtargetInfo(Triple(""), "", "", {}, {}, nullptr, nullptr,
  44. nullptr, nullptr, nullptr, nullptr),
  45. FL(), TL(TM) {}
  46. ~BogusSubtarget() override {}
  47. const TargetFrameLowering *getFrameLowering() const override { return &FL; }
  48. const TargetLowering *getTargetLowering() const override { return &TL; }
  49. const TargetInstrInfo *getInstrInfo() const override { return &TII; }
  50. private:
  51. BogusFrameLowering FL;
  52. BogusTargetLowering TL;
  53. TargetInstrInfo TII;
  54. };
  55. class BogusTargetMachine : public LLVMTargetMachine {
  56. public:
  57. BogusTargetMachine()
  58. : LLVMTargetMachine(Target(), "", Triple(""), "", "", TargetOptions(),
  59. Reloc::Static, CodeModel::Small, CodeGenOpt::Default),
  60. ST(*this) {}
  61. ~BogusTargetMachine() override {}
  62. const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override {
  63. return &ST;
  64. }
  65. private:
  66. BogusSubtarget ST;
  67. };
  68. std::unique_ptr<BogusTargetMachine> createTargetMachine() {
  69. return llvm::make_unique<BogusTargetMachine>();
  70. }
  71. std::unique_ptr<MachineFunction> createMachineFunction() {
  72. LLVMContext Ctx;
  73. Module M("Module", Ctx);
  74. auto Type = FunctionType::get(Type::getVoidTy(Ctx), false);
  75. auto F = Function::Create(Type, GlobalValue::ExternalLinkage, "Test", &M);
  76. auto TM = createTargetMachine();
  77. unsigned FunctionNum = 42;
  78. MachineModuleInfo MMI(TM.get());
  79. const TargetSubtargetInfo &STI = *TM->getSubtargetImpl(*F);
  80. return llvm::make_unique<MachineFunction>(*F, *TM, STI, FunctionNum, MMI);
  81. }
  82. // This test makes sure that MachineInstr::isIdenticalTo handles Defs correctly
  83. // for various combinations of IgnoreDefs, and also that it is symmetrical.
  84. TEST(IsIdenticalToTest, DifferentDefs) {
  85. auto MF = createMachineFunction();
  86. unsigned short NumOps = 2;
  87. unsigned char NumDefs = 1;
  88. MCOperandInfo OpInfo[] = {
  89. {0, 0, MCOI::OPERAND_REGISTER, 0},
  90. {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
  91. MCInstrDesc MCID = {
  92. 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef,
  93. 0, nullptr, nullptr, OpInfo, 0, nullptr};
  94. // Create two MIs with different virtual reg defs and the same uses.
  95. unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does.
  96. unsigned VirtualDef2 = -43;
  97. unsigned VirtualUse = -44;
  98. auto MI1 = MF->CreateMachineInstr(MCID, DebugLoc());
  99. MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  100. MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
  101. auto MI2 = MF->CreateMachineInstr(MCID, DebugLoc());
  102. MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  103. MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
  104. // Check that they are identical when we ignore virtual register defs, but not
  105. // when we check defs.
  106. ASSERT_FALSE(MI1->isIdenticalTo(*MI2, MachineInstr::CheckDefs));
  107. ASSERT_FALSE(MI2->isIdenticalTo(*MI1, MachineInstr::CheckDefs));
  108. ASSERT_TRUE(MI1->isIdenticalTo(*MI2, MachineInstr::IgnoreVRegDefs));
  109. ASSERT_TRUE(MI2->isIdenticalTo(*MI1, MachineInstr::IgnoreVRegDefs));
  110. // Create two MIs with different virtual reg defs, and a def or use of a
  111. // sentinel register.
  112. unsigned SentinelReg = 0;
  113. auto MI3 = MF->CreateMachineInstr(MCID, DebugLoc());
  114. MI3->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  115. MI3->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
  116. auto MI4 = MF->CreateMachineInstr(MCID, DebugLoc());
  117. MI4->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  118. MI4->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
  119. // Check that they are never identical.
  120. ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::CheckDefs));
  121. ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::CheckDefs));
  122. ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::IgnoreVRegDefs));
  123. ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::IgnoreVRegDefs));
  124. }
  125. // Check that MachineInstrExpressionTrait::isEqual is symmetric and in sync with
  126. // MachineInstrExpressionTrait::getHashValue
  127. void checkHashAndIsEqualMatch(MachineInstr *MI1, MachineInstr *MI2) {
  128. bool IsEqual1 = MachineInstrExpressionTrait::isEqual(MI1, MI2);
  129. bool IsEqual2 = MachineInstrExpressionTrait::isEqual(MI2, MI1);
  130. ASSERT_EQ(IsEqual1, IsEqual2);
  131. auto Hash1 = MachineInstrExpressionTrait::getHashValue(MI1);
  132. auto Hash2 = MachineInstrExpressionTrait::getHashValue(MI2);
  133. ASSERT_EQ(IsEqual1, Hash1 == Hash2);
  134. }
  135. // This test makes sure that MachineInstrExpressionTraits::isEqual is in sync
  136. // with MachineInstrExpressionTraits::getHashValue.
  137. TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) {
  138. auto MF = createMachineFunction();
  139. unsigned short NumOps = 2;
  140. unsigned char NumDefs = 1;
  141. MCOperandInfo OpInfo[] = {
  142. {0, 0, MCOI::OPERAND_REGISTER, 0},
  143. {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
  144. MCInstrDesc MCID = {
  145. 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef,
  146. 0, nullptr, nullptr, OpInfo, 0, nullptr};
  147. // Define a series of instructions with different kinds of operands and make
  148. // sure that the hash function is consistent with isEqual for various
  149. // combinations of them.
  150. unsigned VirtualDef1 = -42;
  151. unsigned VirtualDef2 = -43;
  152. unsigned VirtualReg = -44;
  153. unsigned SentinelReg = 0;
  154. unsigned PhysicalReg = 45;
  155. auto VD1VU = MF->CreateMachineInstr(MCID, DebugLoc());
  156. VD1VU->addOperand(*MF,
  157. MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  158. VD1VU->addOperand(*MF,
  159. MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
  160. auto VD2VU = MF->CreateMachineInstr(MCID, DebugLoc());
  161. VD2VU->addOperand(*MF,
  162. MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  163. VD2VU->addOperand(*MF,
  164. MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
  165. auto VD1SU = MF->CreateMachineInstr(MCID, DebugLoc());
  166. VD1SU->addOperand(*MF,
  167. MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  168. VD1SU->addOperand(*MF,
  169. MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
  170. auto VD1SD = MF->CreateMachineInstr(MCID, DebugLoc());
  171. VD1SD->addOperand(*MF,
  172. MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
  173. VD1SD->addOperand(*MF,
  174. MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
  175. auto VD2PU = MF->CreateMachineInstr(MCID, DebugLoc());
  176. VD2PU->addOperand(*MF,
  177. MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  178. VD2PU->addOperand(*MF,
  179. MachineOperand::CreateReg(PhysicalReg, /*isDef*/ false));
  180. auto VD2PD = MF->CreateMachineInstr(MCID, DebugLoc());
  181. VD2PD->addOperand(*MF,
  182. MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
  183. VD2PD->addOperand(*MF,
  184. MachineOperand::CreateReg(PhysicalReg, /*isDef*/ true));
  185. checkHashAndIsEqualMatch(VD1VU, VD2VU);
  186. checkHashAndIsEqualMatch(VD1VU, VD1SU);
  187. checkHashAndIsEqualMatch(VD1VU, VD1SD);
  188. checkHashAndIsEqualMatch(VD1VU, VD2PU);
  189. checkHashAndIsEqualMatch(VD1VU, VD2PD);
  190. checkHashAndIsEqualMatch(VD2VU, VD1SU);
  191. checkHashAndIsEqualMatch(VD2VU, VD1SD);
  192. checkHashAndIsEqualMatch(VD2VU, VD2PU);
  193. checkHashAndIsEqualMatch(VD2VU, VD2PD);
  194. checkHashAndIsEqualMatch(VD1SU, VD1SD);
  195. checkHashAndIsEqualMatch(VD1SU, VD2PU);
  196. checkHashAndIsEqualMatch(VD1SU, VD2PD);
  197. checkHashAndIsEqualMatch(VD1SD, VD2PU);
  198. checkHashAndIsEqualMatch(VD1SD, VD2PD);
  199. checkHashAndIsEqualMatch(VD2PU, VD2PD);
  200. }
  201. TEST(MachineInstrPrintingTest, DebugLocPrinting) {
  202. auto MF = createMachineFunction();
  203. MCOperandInfo OpInfo{0, 0, MCOI::OPERAND_REGISTER, 0};
  204. MCInstrDesc MCID = {0, 1, 1, 0, 0, 0,
  205. 0, nullptr, nullptr, &OpInfo, 0, nullptr};
  206. LLVMContext Ctx;
  207. DIFile *DIF = DIFile::getDistinct(Ctx, "filename", "");
  208. DISubprogram *DIS = DISubprogram::getDistinct(
  209. Ctx, nullptr, "", "", DIF, 0, nullptr, 0, nullptr, 0, 0, DINode::FlagZero,
  210. DISubprogram::SPFlagZero, nullptr);
  211. DILocation *DIL = DILocation::get(Ctx, 1, 5, DIS);
  212. DebugLoc DL(DIL);
  213. MachineInstr *MI = MF->CreateMachineInstr(MCID, DL);
  214. MI->addOperand(*MF, MachineOperand::CreateReg(0, /*isDef*/ true));
  215. std::string str;
  216. raw_string_ostream OS(str);
  217. MI->print(OS);
  218. ASSERT_TRUE(
  219. StringRef(OS.str()).startswith("$noreg = UNKNOWN debug-location "));
  220. ASSERT_TRUE(
  221. StringRef(OS.str()).endswith("filename:1:5"));
  222. }
  223. static_assert(is_trivially_copyable<MCOperand>::value, "trivially copyable");
  224. } // end namespace