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.has_value(); }
  36. bool Operand::isVariable() const { return VariableIndex.has_value(); }
  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->operands()[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 (MCPhysReg MCPhysReg : Description->implicit_defs()) {
  106. Operand Operand;
  107. Operand.Index = OpIndex++;
  108. Operand.IsDef = true;
  109. Operand.Tracker = &RATC.getRegister(MCPhysReg);
  110. Operand.ImplicitReg = MCPhysReg;
  111. Operands.push_back(Operand);
  112. }
  113. for (MCPhysReg MCPhysReg : Description->implicit_uses()) {
  114. Operand Operand;
  115. Operand.Index = OpIndex++;
  116. Operand.IsDef = false;
  117. Operand.Tracker = &RATC.getRegister(MCPhysReg);
  118. Operand.ImplicitReg = MCPhysReg;
  119. Operands.push_back(Operand);
  120. }
  121. Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
  122. // Assigning Variables to non tied explicit operands.
  123. for (auto &Op : Operands)
  124. if (Op.isExplicit() && !Op.isTied()) {
  125. const size_t VariableIndex = Variables.size();
  126. assert(VariableIndex < std::numeric_limits<uint8_t>::max());
  127. Op.VariableIndex = VariableIndex;
  128. Variables.emplace_back();
  129. Variables.back().Index = VariableIndex;
  130. }
  131. // Assigning Variables to tied operands.
  132. for (auto &Op : Operands)
  133. if (Op.isExplicit() && Op.isTied())
  134. Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
  135. // Assigning Operands to Variables.
  136. for (auto &Op : Operands)
  137. if (Op.isVariable())
  138. Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
  139. // Processing Aliasing.
  140. BitVector ImplDefRegs = RATC.emptyRegisters();
  141. BitVector ImplUseRegs = RATC.emptyRegisters();
  142. BitVector AllDefRegs = RATC.emptyRegisters();
  143. BitVector AllUseRegs = RATC.emptyRegisters();
  144. for (const auto &Op : Operands) {
  145. if (Op.isReg()) {
  146. const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
  147. if (Op.isDef())
  148. AllDefRegs |= AliasingBits;
  149. if (Op.isUse())
  150. AllUseRegs |= AliasingBits;
  151. if (Op.isDef() && Op.isImplicit())
  152. ImplDefRegs |= AliasingBits;
  153. if (Op.isUse() && Op.isImplicit())
  154. ImplUseRegs |= AliasingBits;
  155. }
  156. }
  157. // Can't use make_unique because constructor is private.
  158. return std::unique_ptr<Instruction>(new Instruction(
  159. Description, InstrInfo.getName(Opcode), std::move(Operands),
  160. std::move(Variables), BVC.getUnique(std::move(ImplDefRegs)),
  161. BVC.getUnique(std::move(ImplUseRegs)),
  162. BVC.getUnique(std::move(AllDefRegs)),
  163. BVC.getUnique(std::move(AllUseRegs))));
  164. }
  165. const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
  166. const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
  167. assert(PrimaryOperandIndex < Operands.size());
  168. return Operands[PrimaryOperandIndex];
  169. }
  170. bool Instruction::hasMemoryOperands() const {
  171. return any_of(Operands, [](const Operand &Op) {
  172. return Op.isReg() && Op.isExplicit() && Op.isMemory();
  173. });
  174. }
  175. bool Instruction::hasAliasingImplicitRegisters() const {
  176. return ImplDefRegs.anyCommon(ImplUseRegs);
  177. }
  178. // Returns true if there are registers that are both in `A` and `B` but not in
  179. // `Forbidden`.
  180. static bool anyCommonExcludingForbidden(const BitVector &A, const BitVector &B,
  181. const BitVector &Forbidden) {
  182. assert(A.size() == B.size() && B.size() == Forbidden.size());
  183. const auto Size = A.size();
  184. for (int AIndex = A.find_first(); AIndex != -1;) {
  185. const int BIndex = B.find_first_in(AIndex, Size);
  186. if (BIndex == -1)
  187. return false;
  188. if (AIndex == BIndex && !Forbidden.test(AIndex))
  189. return true;
  190. AIndex = A.find_first_in(BIndex + 1, Size);
  191. }
  192. return false;
  193. }
  194. bool Instruction::hasAliasingRegistersThrough(
  195. const Instruction &OtherInstr, const BitVector &ForbiddenRegisters) const {
  196. return anyCommonExcludingForbidden(AllDefRegs, OtherInstr.AllUseRegs,
  197. ForbiddenRegisters) &&
  198. anyCommonExcludingForbidden(OtherInstr.AllDefRegs, AllUseRegs,
  199. ForbiddenRegisters);
  200. }
  201. bool Instruction::hasTiedRegisters() const {
  202. return any_of(Variables,
  203. [](const Variable &Var) { return Var.hasTiedOperands(); });
  204. }
  205. bool Instruction::hasAliasingRegisters(
  206. const BitVector &ForbiddenRegisters) const {
  207. return anyCommonExcludingForbidden(AllDefRegs, AllUseRegs,
  208. ForbiddenRegisters);
  209. }
  210. bool Instruction::hasOneUseOrOneDef() const {
  211. return AllDefRegs.count() || AllUseRegs.count();
  212. }
  213. void Instruction::dump(const MCRegisterInfo &RegInfo,
  214. const RegisterAliasingTrackerCache &RATC,
  215. raw_ostream &Stream) const {
  216. Stream << "- " << Name << "\n";
  217. for (const auto &Op : Operands) {
  218. Stream << "- Op" << Op.getIndex();
  219. if (Op.isExplicit())
  220. Stream << " Explicit";
  221. if (Op.isImplicit())
  222. Stream << " Implicit";
  223. if (Op.isUse())
  224. Stream << " Use";
  225. if (Op.isDef())
  226. Stream << " Def";
  227. if (Op.isImmediate())
  228. Stream << " Immediate";
  229. if (Op.isMemory())
  230. Stream << " Memory";
  231. if (Op.isReg()) {
  232. if (Op.isImplicitReg())
  233. Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
  234. else
  235. Stream << " RegClass("
  236. << RegInfo.getRegClassName(
  237. &RegInfo.getRegClass(Op.Info->RegClass))
  238. << ")";
  239. }
  240. if (Op.isTied())
  241. Stream << " TiedToOp" << Op.getTiedToIndex();
  242. Stream << "\n";
  243. }
  244. for (const auto &Var : Variables) {
  245. Stream << "- Var" << Var.getIndex();
  246. Stream << " [";
  247. bool IsFirst = true;
  248. for (auto OperandIndex : Var.TiedOperands) {
  249. if (!IsFirst)
  250. Stream << ",";
  251. Stream << "Op" << OperandIndex;
  252. IsFirst = false;
  253. }
  254. Stream << "]";
  255. Stream << "\n";
  256. }
  257. if (hasMemoryOperands())
  258. Stream << "- hasMemoryOperands\n";
  259. if (hasAliasingImplicitRegisters())
  260. Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
  261. if (hasTiedRegisters())
  262. Stream << "- hasTiedRegisters (execution is always serial)\n";
  263. if (hasAliasingRegisters(RATC.emptyRegisters()))
  264. Stream << "- hasAliasingRegisters\n";
  265. }
  266. InstructionsCache::InstructionsCache(const MCInstrInfo &InstrInfo,
  267. const RegisterAliasingTrackerCache &RATC)
  268. : InstrInfo(InstrInfo), RATC(RATC), BVC() {}
  269. const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
  270. auto &Found = Instructions[Opcode];
  271. if (!Found)
  272. Found = Instruction::create(InstrInfo, RATC, BVC, Opcode);
  273. return *Found;
  274. }
  275. bool RegisterOperandAssignment::
  276. operator==(const RegisterOperandAssignment &Other) const {
  277. return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
  278. }
  279. bool AliasingRegisterOperands::
  280. operator==(const AliasingRegisterOperands &Other) const {
  281. return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
  282. }
  283. static void
  284. addOperandIfAlias(const MCPhysReg Reg, bool SelectDef,
  285. ArrayRef<Operand> Operands,
  286. SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
  287. for (const auto &Op : Operands) {
  288. if (Op.isReg() && Op.isDef() == SelectDef) {
  289. const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
  290. if (SourceReg >= 0)
  291. OperandValues.emplace_back(&Op, SourceReg);
  292. }
  293. }
  294. }
  295. bool AliasingRegisterOperands::hasImplicitAliasing() const {
  296. const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
  297. return ROV.Op->isImplicit();
  298. };
  299. return any_of(Defs, HasImplicit) && any_of(Uses, HasImplicit);
  300. }
  301. bool AliasingConfigurations::empty() const { return Configurations.empty(); }
  302. bool AliasingConfigurations::hasImplicitAliasing() const {
  303. return any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
  304. return ARO.hasImplicitAliasing();
  305. });
  306. }
  307. AliasingConfigurations::AliasingConfigurations(
  308. const Instruction &DefInstruction, const Instruction &UseInstruction,
  309. const BitVector &ForbiddenRegisters) {
  310. auto CommonRegisters = UseInstruction.AllUseRegs;
  311. CommonRegisters &= DefInstruction.AllDefRegs;
  312. CommonRegisters.reset(ForbiddenRegisters);
  313. if (!CommonRegisters.empty()) {
  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