MCInstrDescView.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. //===-- MCInstrDescView.cpp -------------------------------------*- C++ -*-===//
  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 "MCInstrDescView.h"
  9. #include <iterator>
  10. #include <map>
  11. #include <tuple>
  12. #include "llvm/ADT/STLExtras.h"
  13. namespace llvm {
  14. namespace exegesis {
  15. unsigned Variable::getIndex() const { return *Index; }
  16. unsigned Variable::getPrimaryOperandIndex() const {
  17. assert(!TiedOperands.empty());
  18. return TiedOperands[0];
  19. }
  20. bool Variable::hasTiedOperands() const {
  21. assert(TiedOperands.size() <= 2 &&
  22. "No more than two operands can be tied together");
  23. // By definition only Use and Def operands can be tied together.
  24. // TiedOperands[0] is the Def operand (LLVM stores defs first).
  25. // TiedOperands[1] is the Use operand.
  26. return TiedOperands.size() > 1;
  27. }
  28. unsigned Operand::getIndex() const { return *Index; }
  29. bool Operand::isExplicit() const { return Info; }
  30. bool Operand::isImplicit() const { return !Info; }
  31. bool Operand::isImplicitReg() const { return ImplicitReg; }
  32. bool Operand::isDef() const { return IsDef; }
  33. bool Operand::isUse() const { return !IsDef; }
  34. bool Operand::isReg() const { return Tracker; }
  35. bool Operand::isTied() const { return TiedToIndex.hasValue(); }
  36. bool Operand::isVariable() const { return VariableIndex.hasValue(); }
  37. bool Operand::isMemory() const {
  38. return isExplicit() &&
  39. getExplicitOperandInfo().OperandType == MCOI::OPERAND_MEMORY;
  40. }
  41. bool Operand::isImmediate() const {
  42. return isExplicit() &&
  43. getExplicitOperandInfo().OperandType == MCOI::OPERAND_IMMEDIATE;
  44. }
  45. unsigned Operand::getTiedToIndex() const { return *TiedToIndex; }
  46. unsigned Operand::getVariableIndex() const { return *VariableIndex; }
  47. unsigned Operand::getImplicitReg() const {
  48. assert(ImplicitReg);
  49. return *ImplicitReg;
  50. }
  51. const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
  52. assert(Tracker);
  53. return *Tracker;
  54. }
  55. const MCOperandInfo &Operand::getExplicitOperandInfo() const {
  56. assert(Info);
  57. return *Info;
  58. }
  59. const BitVector *BitVectorCache::getUnique(BitVector &&BV) const {
  60. for (const auto &Entry : Cache)
  61. if (*Entry == BV)
  62. return Entry.get();
  63. Cache.push_back(std::make_unique<BitVector>());
  64. auto &Entry = Cache.back();
  65. Entry->swap(BV);
  66. return Entry.get();
  67. }
  68. Instruction::Instruction(const MCInstrDesc *Description, StringRef Name,
  69. SmallVector<Operand, 8> Operands,
  70. SmallVector<Variable, 4> Variables,
  71. const BitVector *ImplDefRegs,
  72. const BitVector *ImplUseRegs,
  73. const BitVector *AllDefRegs,
  74. const BitVector *AllUseRegs)
  75. : Description(*Description), Name(Name), Operands(std::move(Operands)),
  76. Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs),
  77. ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs),
  78. AllUseRegs(*AllUseRegs) {}
  79. std::unique_ptr<Instruction>
  80. Instruction::create(const MCInstrInfo &InstrInfo,
  81. const RegisterAliasingTrackerCache &RATC,
  82. const BitVectorCache &BVC, unsigned Opcode) {
  83. const llvm::MCInstrDesc *const Description = &InstrInfo.get(Opcode);
  84. unsigned OpIndex = 0;
  85. SmallVector<Operand, 8> Operands;
  86. SmallVector<Variable, 4> Variables;
  87. for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
  88. const auto &OpInfo = Description->opInfo_begin()[OpIndex];
  89. Operand Operand;
  90. Operand.Index = OpIndex;
  91. Operand.IsDef = (OpIndex < Description->getNumDefs());
  92. // TODO(gchatelet): Handle isLookupPtrRegClass.
  93. if (OpInfo.RegClass >= 0)
  94. Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
  95. int TiedToIndex = Description->getOperandConstraint(OpIndex, MCOI::TIED_TO);
  96. assert((TiedToIndex == -1 ||
  97. (0 <= TiedToIndex &&
  98. TiedToIndex < std::numeric_limits<uint8_t>::max())) &&
  99. "Unknown Operand Constraint");
  100. if (TiedToIndex >= 0)
  101. Operand.TiedToIndex = TiedToIndex;
  102. Operand.Info = &OpInfo;
  103. Operands.push_back(Operand);
  104. }
  105. for (const MCPhysReg *MCPhysReg = Description->getImplicitDefs();
  106. MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
  107. Operand Operand;
  108. Operand.Index = OpIndex;
  109. Operand.IsDef = true;
  110. Operand.Tracker = &RATC.getRegister(*MCPhysReg);
  111. Operand.ImplicitReg = MCPhysReg;
  112. Operands.push_back(Operand);
  113. }
  114. for (const MCPhysReg *MCPhysReg = Description->getImplicitUses();
  115. MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
  116. Operand Operand;
  117. Operand.Index = OpIndex;
  118. Operand.IsDef = false;
  119. Operand.Tracker = &RATC.getRegister(*MCPhysReg);
  120. Operand.ImplicitReg = MCPhysReg;
  121. Operands.push_back(Operand);
  122. }
  123. Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
  124. // Assigning Variables to non tied explicit operands.
  125. for (auto &Op : Operands)
  126. if (Op.isExplicit() && !Op.isTied()) {
  127. const size_t VariableIndex = Variables.size();
  128. assert(VariableIndex < std::numeric_limits<uint8_t>::max());
  129. Op.VariableIndex = VariableIndex;
  130. Variables.emplace_back();
  131. Variables.back().Index = VariableIndex;
  132. }
  133. // Assigning Variables to tied operands.
  134. for (auto &Op : Operands)
  135. if (Op.isExplicit() && Op.isTied())
  136. Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
  137. // Assigning Operands to Variables.
  138. for (auto &Op : Operands)
  139. if (Op.isVariable())
  140. Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
  141. // Processing Aliasing.
  142. BitVector ImplDefRegs = RATC.emptyRegisters();
  143. BitVector ImplUseRegs = RATC.emptyRegisters();
  144. BitVector AllDefRegs = RATC.emptyRegisters();
  145. BitVector AllUseRegs = RATC.emptyRegisters();
  146. for (const auto &Op : Operands) {
  147. if (Op.isReg()) {
  148. const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
  149. if (Op.isDef())
  150. AllDefRegs |= AliasingBits;
  151. if (Op.isUse())
  152. AllUseRegs |= AliasingBits;
  153. if (Op.isDef() && Op.isImplicit())
  154. ImplDefRegs |= AliasingBits;
  155. if (Op.isUse() && Op.isImplicit())
  156. ImplUseRegs |= AliasingBits;
  157. }
  158. }
  159. // Can't use make_unique because constructor is private.
  160. return std::unique_ptr<Instruction>(new Instruction(
  161. Description, InstrInfo.getName(Opcode), std::move(Operands),
  162. std::move(Variables), BVC.getUnique(std::move(ImplDefRegs)),
  163. BVC.getUnique(std::move(ImplUseRegs)),
  164. BVC.getUnique(std::move(AllDefRegs)),
  165. BVC.getUnique(std::move(AllUseRegs))));
  166. }
  167. const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
  168. const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
  169. assert(PrimaryOperandIndex < Operands.size());
  170. return Operands[PrimaryOperandIndex];
  171. }
  172. bool Instruction::hasMemoryOperands() const {
  173. return any_of(Operands, [](const Operand &Op) {
  174. return Op.isReg() && Op.isExplicit() && Op.isMemory();
  175. });
  176. }
  177. bool Instruction::hasAliasingImplicitRegisters() const {
  178. return ImplDefRegs.anyCommon(ImplUseRegs);
  179. }
  180. // Returns true if there are registers that are both in `A` and `B` but not in
  181. // `Forbidden`.
  182. static bool anyCommonExcludingForbidden(const BitVector &A, const BitVector &B,
  183. const BitVector &Forbidden) {
  184. assert(A.size() == B.size() && B.size() == Forbidden.size());
  185. const auto Size = A.size();
  186. for (int AIndex = A.find_first(); AIndex != -1;) {
  187. const int BIndex = B.find_first_in(AIndex, Size);
  188. if (BIndex == -1)
  189. return false;
  190. if (AIndex == BIndex && !Forbidden.test(AIndex))
  191. return true;
  192. AIndex = A.find_first_in(BIndex + 1, Size);
  193. }
  194. return false;
  195. }
  196. bool Instruction::hasAliasingRegistersThrough(
  197. const Instruction &OtherInstr, const BitVector &ForbiddenRegisters) const {
  198. return anyCommonExcludingForbidden(AllDefRegs, OtherInstr.AllUseRegs,
  199. ForbiddenRegisters) &&
  200. anyCommonExcludingForbidden(OtherInstr.AllDefRegs, AllUseRegs,
  201. ForbiddenRegisters);
  202. }
  203. bool Instruction::hasTiedRegisters() const {
  204. return any_of(Variables,
  205. [](const Variable &Var) { return Var.hasTiedOperands(); });
  206. }
  207. bool Instruction::hasAliasingRegisters(
  208. const BitVector &ForbiddenRegisters) const {
  209. return anyCommonExcludingForbidden(AllDefRegs, AllUseRegs,
  210. ForbiddenRegisters);
  211. }
  212. bool Instruction::hasOneUseOrOneDef() const {
  213. return AllDefRegs.count() || AllUseRegs.count();
  214. }
  215. void Instruction::dump(const MCRegisterInfo &RegInfo,
  216. const RegisterAliasingTrackerCache &RATC,
  217. raw_ostream &Stream) const {
  218. Stream << "- " << Name << "\n";
  219. for (const auto &Op : Operands) {
  220. Stream << "- Op" << Op.getIndex();
  221. if (Op.isExplicit())
  222. Stream << " Explicit";
  223. if (Op.isImplicit())
  224. Stream << " Implicit";
  225. if (Op.isUse())
  226. Stream << " Use";
  227. if (Op.isDef())
  228. Stream << " Def";
  229. if (Op.isImmediate())
  230. Stream << " Immediate";
  231. if (Op.isMemory())
  232. Stream << " Memory";
  233. if (Op.isReg()) {
  234. if (Op.isImplicitReg())
  235. Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
  236. else
  237. Stream << " RegClass("
  238. << RegInfo.getRegClassName(
  239. &RegInfo.getRegClass(Op.Info->RegClass))
  240. << ")";
  241. }
  242. if (Op.isTied())
  243. Stream << " TiedToOp" << Op.getTiedToIndex();
  244. Stream << "\n";
  245. }
  246. for (const auto &Var : Variables) {
  247. Stream << "- Var" << Var.getIndex();
  248. Stream << " [";
  249. bool IsFirst = true;
  250. for (auto OperandIndex : Var.TiedOperands) {
  251. if (!IsFirst)
  252. Stream << ",";
  253. Stream << "Op" << OperandIndex;
  254. IsFirst = false;
  255. }
  256. Stream << "]";
  257. Stream << "\n";
  258. }
  259. if (hasMemoryOperands())
  260. Stream << "- hasMemoryOperands\n";
  261. if (hasAliasingImplicitRegisters())
  262. Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
  263. if (hasTiedRegisters())
  264. Stream << "- hasTiedRegisters (execution is always serial)\n";
  265. if (hasAliasingRegisters(RATC.emptyRegisters()))
  266. Stream << "- hasAliasingRegisters\n";
  267. }
  268. InstructionsCache::InstructionsCache(const MCInstrInfo &InstrInfo,
  269. const RegisterAliasingTrackerCache &RATC)
  270. : InstrInfo(InstrInfo), RATC(RATC), BVC() {}
  271. const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
  272. auto &Found = Instructions[Opcode];
  273. if (!Found)
  274. Found = Instruction::create(InstrInfo, RATC, BVC, Opcode);
  275. return *Found;
  276. }
  277. bool RegisterOperandAssignment::
  278. operator==(const RegisterOperandAssignment &Other) const {
  279. return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
  280. }
  281. bool AliasingRegisterOperands::
  282. operator==(const AliasingRegisterOperands &Other) const {
  283. return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
  284. }
  285. static void
  286. addOperandIfAlias(const MCPhysReg Reg, bool SelectDef,
  287. ArrayRef<Operand> Operands,
  288. SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
  289. for (const auto &Op : Operands) {
  290. if (Op.isReg() && Op.isDef() == SelectDef) {
  291. const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
  292. if (SourceReg >= 0)
  293. OperandValues.emplace_back(&Op, SourceReg);
  294. }
  295. }
  296. }
  297. bool AliasingRegisterOperands::hasImplicitAliasing() const {
  298. const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
  299. return ROV.Op->isImplicit();
  300. };
  301. return any_of(Defs, HasImplicit) && any_of(Uses, HasImplicit);
  302. }
  303. bool AliasingConfigurations::empty() const { return Configurations.empty(); }
  304. bool AliasingConfigurations::hasImplicitAliasing() const {
  305. return any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
  306. return ARO.hasImplicitAliasing();
  307. });
  308. }
  309. AliasingConfigurations::AliasingConfigurations(
  310. const Instruction &DefInstruction, const Instruction &UseInstruction) {
  311. if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
  312. auto CommonRegisters = UseInstruction.AllUseRegs;
  313. CommonRegisters &= DefInstruction.AllDefRegs;
  314. for (const MCPhysReg Reg : CommonRegisters.set_bits()) {
  315. AliasingRegisterOperands ARO;
  316. addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
  317. addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
  318. if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
  319. !is_contained(Configurations, ARO))
  320. Configurations.push_back(std::move(ARO));
  321. }
  322. }
  323. }
  324. void DumpMCOperand(const MCRegisterInfo &MCRegisterInfo, const MCOperand &Op,
  325. raw_ostream &OS) {
  326. if (!Op.isValid())
  327. OS << "Invalid";
  328. else if (Op.isReg())
  329. OS << MCRegisterInfo.getName(Op.getReg());
  330. else if (Op.isImm())
  331. OS << Op.getImm();
  332. else if (Op.isDFPImm())
  333. OS << bit_cast<double>(Op.getDFPImm());
  334. else if (Op.isSFPImm())
  335. OS << bit_cast<float>(Op.getSFPImm());
  336. else if (Op.isExpr())
  337. OS << "Expr";
  338. else if (Op.isInst())
  339. OS << "SubInst";
  340. }
  341. void DumpMCInst(const MCRegisterInfo &MCRegisterInfo,
  342. const MCInstrInfo &MCInstrInfo, const MCInst &MCInst,
  343. raw_ostream &OS) {
  344. OS << MCInstrInfo.getName(MCInst.getOpcode());
  345. for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
  346. if (I > 0)
  347. OS << ',';
  348. OS << ' ';
  349. DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
  350. }
  351. }
  352. } // namespace exegesis
  353. } // namespace llvm