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