X86InstrRelaxTables.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. //===- X86InstrRelaxTables.cpp - X86 Instruction Relaxation Tables -*- 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. //
  9. // This file contains the X86 instruction relaxation tables.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "X86InstrRelaxTables.h"
  13. #include "X86InstrInfo.h"
  14. #include "llvm/ADT/STLExtras.h"
  15. #include <atomic>
  16. using namespace llvm;
  17. // These tables are sorted by their ShortOp value allowing them to be binary
  18. // searched at runtime without the need for additional storage. The enum values
  19. // are currently emitted in X86GenInstrInfo.inc in alphabetical order. Which
  20. // makes sorting these tables a simple matter of alphabetizing the table.
  21. static const X86InstrRelaxTableEntry InstrRelaxTable[] = {
  22. // ADC
  23. { X86::ADC16mi8, X86::ADC16mi },
  24. { X86::ADC16ri8, X86::ADC16ri },
  25. { X86::ADC32mi8, X86::ADC32mi },
  26. { X86::ADC32ri8, X86::ADC32ri },
  27. { X86::ADC64mi8, X86::ADC64mi32 },
  28. { X86::ADC64ri8, X86::ADC64ri32 },
  29. // ADD
  30. { X86::ADD16mi8, X86::ADD16mi },
  31. { X86::ADD16ri8, X86::ADD16ri },
  32. { X86::ADD32mi8, X86::ADD32mi },
  33. { X86::ADD32ri8, X86::ADD32ri },
  34. { X86::ADD64mi8, X86::ADD64mi32 },
  35. { X86::ADD64ri8, X86::ADD64ri32 },
  36. // AND
  37. { X86::AND16mi8, X86::AND16mi },
  38. { X86::AND16ri8, X86::AND16ri },
  39. { X86::AND32mi8, X86::AND32mi },
  40. { X86::AND32ri8, X86::AND32ri },
  41. { X86::AND64mi8, X86::AND64mi32 },
  42. { X86::AND64ri8, X86::AND64ri32 },
  43. // CMP
  44. { X86::CMP16mi8, X86::CMP16mi },
  45. { X86::CMP16ri8, X86::CMP16ri },
  46. { X86::CMP32mi8, X86::CMP32mi },
  47. { X86::CMP32ri8, X86::CMP32ri },
  48. { X86::CMP64mi8, X86::CMP64mi32 },
  49. { X86::CMP64ri8, X86::CMP64ri32 },
  50. // IMUL
  51. { X86::IMUL16rmi8, X86::IMUL16rmi },
  52. { X86::IMUL16rri8, X86::IMUL16rri },
  53. { X86::IMUL32rmi8, X86::IMUL32rmi },
  54. { X86::IMUL32rri8, X86::IMUL32rri },
  55. { X86::IMUL64rmi8, X86::IMUL64rmi32 },
  56. { X86::IMUL64rri8, X86::IMUL64rri32 },
  57. // OR
  58. { X86::OR16mi8, X86::OR16mi },
  59. { X86::OR16ri8, X86::OR16ri },
  60. { X86::OR32mi8, X86::OR32mi },
  61. { X86::OR32ri8, X86::OR32ri },
  62. { X86::OR64mi8, X86::OR64mi32 },
  63. { X86::OR64ri8, X86::OR64ri32 },
  64. // PUSH
  65. { X86::PUSH16i8, X86::PUSHi16 },
  66. { X86::PUSH32i8, X86::PUSHi32 },
  67. { X86::PUSH64i8, X86::PUSH64i32 },
  68. // SBB
  69. { X86::SBB16mi8, X86::SBB16mi },
  70. { X86::SBB16ri8, X86::SBB16ri },
  71. { X86::SBB32mi8, X86::SBB32mi },
  72. { X86::SBB32ri8, X86::SBB32ri },
  73. { X86::SBB64mi8, X86::SBB64mi32 },
  74. { X86::SBB64ri8, X86::SBB64ri32 },
  75. // SUB
  76. { X86::SUB16mi8, X86::SUB16mi },
  77. { X86::SUB16ri8, X86::SUB16ri },
  78. { X86::SUB32mi8, X86::SUB32mi },
  79. { X86::SUB32ri8, X86::SUB32ri },
  80. { X86::SUB64mi8, X86::SUB64mi32 },
  81. { X86::SUB64ri8, X86::SUB64ri32 },
  82. // XOR
  83. { X86::XOR16mi8, X86::XOR16mi },
  84. { X86::XOR16ri8, X86::XOR16ri },
  85. { X86::XOR32mi8, X86::XOR32mi },
  86. { X86::XOR32ri8, X86::XOR32ri },
  87. { X86::XOR64mi8, X86::XOR64mi32 },
  88. { X86::XOR64ri8, X86::XOR64ri32 },
  89. };
  90. static const X86InstrRelaxTableEntry *
  91. lookupRelaxTableImpl(ArrayRef<X86InstrRelaxTableEntry> Table,
  92. unsigned ShortOp) {
  93. #ifndef NDEBUG
  94. // Make sure the tables are sorted.
  95. static std::atomic<bool> RelaxTableChecked(false);
  96. if (!RelaxTableChecked.load(std::memory_order_relaxed)) {
  97. assert(llvm::is_sorted(InstrRelaxTable) &&
  98. std::adjacent_find(std::begin(InstrRelaxTable),
  99. std::end(InstrRelaxTable)) ==
  100. std::end(InstrRelaxTable) &&
  101. "InstrRelaxTable is not sorted and unique!");
  102. RelaxTableChecked.store(true, std::memory_order_relaxed);
  103. }
  104. #endif
  105. const X86InstrRelaxTableEntry *Data = llvm::lower_bound(Table, ShortOp);
  106. if (Data != Table.end() && Data->KeyOp == ShortOp)
  107. return Data;
  108. return nullptr;
  109. }
  110. const X86InstrRelaxTableEntry *llvm::lookupRelaxTable(unsigned ShortOp) {
  111. return lookupRelaxTableImpl(InstrRelaxTable, ShortOp);
  112. }
  113. namespace {
  114. // This class stores the short form tables. It is instantiated as a
  115. // function scope static variable to lazily init the short form table.
  116. struct X86ShortFormTable {
  117. // Stores relaxation table entries sorted by relaxed form opcode.
  118. SmallVector<X86InstrRelaxTableEntry, 0> Table;
  119. X86ShortFormTable() {
  120. for (const X86InstrRelaxTableEntry &Entry : InstrRelaxTable)
  121. Table.push_back({Entry.DstOp, Entry.KeyOp});
  122. llvm::sort(Table);
  123. // Now that it's sorted, ensure its unique.
  124. assert(std::adjacent_find(Table.begin(), Table.end()) == Table.end() &&
  125. "Short form table is not unique!");
  126. }
  127. };
  128. } // namespace
  129. const X86InstrRelaxTableEntry *llvm::lookupShortTable(unsigned RelaxOp) {
  130. static X86ShortFormTable ShortTable;
  131. auto &Table = ShortTable.Table;
  132. auto I = llvm::lower_bound(Table, RelaxOp);
  133. if (I != Table.end() && I->KeyOp == RelaxOp)
  134. return &*I;
  135. return nullptr;
  136. }
  137. namespace llvm {
  138. /// Get the short instruction opcode for a given relaxed opcode.
  139. unsigned X86::getShortOpcodeArith(unsigned RelaxOp) {
  140. if (const X86InstrRelaxTableEntry *I = lookupShortTable(RelaxOp))
  141. return I->DstOp;
  142. return RelaxOp;
  143. }
  144. /// Get the relaxed instruction opcode for a given short opcode.
  145. unsigned X86::getRelaxedOpcodeArith(unsigned ShortOp) {
  146. if (const X86InstrRelaxTableEntry *I = lookupRelaxTable(ShortOp))
  147. return I->DstOp;
  148. return ShortOp;
  149. }
  150. } // namespace llvm