//===- X86InstrRelaxTables.cpp - X86 Instruction Relaxation Tables -*- C++ -*-// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains the X86 instruction relaxation tables. // //===----------------------------------------------------------------------===// #include "X86InstrRelaxTables.h" #include "X86InstrInfo.h" #include "llvm/ADT/STLExtras.h" #include using namespace llvm; // These tables are sorted by their ShortOp value allowing them to be binary // searched at runtime without the need for additional storage. The enum values // are currently emitted in X86GenInstrInfo.inc in alphabetical order. Which // makes sorting these tables a simple matter of alphabetizing the table. static const X86InstrRelaxTableEntry InstrRelaxTable[] = { // ADC { X86::ADC16mi8, X86::ADC16mi }, { X86::ADC16ri8, X86::ADC16ri }, { X86::ADC32mi8, X86::ADC32mi }, { X86::ADC32ri8, X86::ADC32ri }, { X86::ADC64mi8, X86::ADC64mi32 }, { X86::ADC64ri8, X86::ADC64ri32 }, // ADD { X86::ADD16mi8, X86::ADD16mi }, { X86::ADD16ri8, X86::ADD16ri }, { X86::ADD32mi8, X86::ADD32mi }, { X86::ADD32ri8, X86::ADD32ri }, { X86::ADD64mi8, X86::ADD64mi32 }, { X86::ADD64ri8, X86::ADD64ri32 }, // AND { X86::AND16mi8, X86::AND16mi }, { X86::AND16ri8, X86::AND16ri }, { X86::AND32mi8, X86::AND32mi }, { X86::AND32ri8, X86::AND32ri }, { X86::AND64mi8, X86::AND64mi32 }, { X86::AND64ri8, X86::AND64ri32 }, // CMP { X86::CMP16mi8, X86::CMP16mi }, { X86::CMP16ri8, X86::CMP16ri }, { X86::CMP32mi8, X86::CMP32mi }, { X86::CMP32ri8, X86::CMP32ri }, { X86::CMP64mi8, X86::CMP64mi32 }, { X86::CMP64ri8, X86::CMP64ri32 }, // IMUL { X86::IMUL16rmi8, X86::IMUL16rmi }, { X86::IMUL16rri8, X86::IMUL16rri }, { X86::IMUL32rmi8, X86::IMUL32rmi }, { X86::IMUL32rri8, X86::IMUL32rri }, { X86::IMUL64rmi8, X86::IMUL64rmi32 }, { X86::IMUL64rri8, X86::IMUL64rri32 }, // OR { X86::OR16mi8, X86::OR16mi }, { X86::OR16ri8, X86::OR16ri }, { X86::OR32mi8, X86::OR32mi }, { X86::OR32ri8, X86::OR32ri }, { X86::OR64mi8, X86::OR64mi32 }, { X86::OR64ri8, X86::OR64ri32 }, // PUSH { X86::PUSH16i8, X86::PUSHi16 }, { X86::PUSH32i8, X86::PUSHi32 }, { X86::PUSH64i8, X86::PUSH64i32 }, // SBB { X86::SBB16mi8, X86::SBB16mi }, { X86::SBB16ri8, X86::SBB16ri }, { X86::SBB32mi8, X86::SBB32mi }, { X86::SBB32ri8, X86::SBB32ri }, { X86::SBB64mi8, X86::SBB64mi32 }, { X86::SBB64ri8, X86::SBB64ri32 }, // SUB { X86::SUB16mi8, X86::SUB16mi }, { X86::SUB16ri8, X86::SUB16ri }, { X86::SUB32mi8, X86::SUB32mi }, { X86::SUB32ri8, X86::SUB32ri }, { X86::SUB64mi8, X86::SUB64mi32 }, { X86::SUB64ri8, X86::SUB64ri32 }, // XOR { X86::XOR16mi8, X86::XOR16mi }, { X86::XOR16ri8, X86::XOR16ri }, { X86::XOR32mi8, X86::XOR32mi }, { X86::XOR32ri8, X86::XOR32ri }, { X86::XOR64mi8, X86::XOR64mi32 }, { X86::XOR64ri8, X86::XOR64ri32 }, }; static const X86InstrRelaxTableEntry * lookupRelaxTableImpl(ArrayRef Table, unsigned ShortOp) { #ifndef NDEBUG // Make sure the tables are sorted. static std::atomic RelaxTableChecked(false); if (!RelaxTableChecked.load(std::memory_order_relaxed)) { assert(llvm::is_sorted(InstrRelaxTable) && std::adjacent_find(std::begin(InstrRelaxTable), std::end(InstrRelaxTable)) == std::end(InstrRelaxTable) && "InstrRelaxTable is not sorted and unique!"); RelaxTableChecked.store(true, std::memory_order_relaxed); } #endif const X86InstrRelaxTableEntry *Data = llvm::lower_bound(Table, ShortOp); if (Data != Table.end() && Data->KeyOp == ShortOp) return Data; return nullptr; } const X86InstrRelaxTableEntry *llvm::lookupRelaxTable(unsigned ShortOp) { return lookupRelaxTableImpl(InstrRelaxTable, ShortOp); } namespace { // This class stores the short form tables. It is instantiated as a // function scope static variable to lazily init the short form table. struct X86ShortFormTable { // Stores relaxation table entries sorted by relaxed form opcode. SmallVector Table; X86ShortFormTable() { for (const X86InstrRelaxTableEntry &Entry : InstrRelaxTable) Table.push_back({Entry.DstOp, Entry.KeyOp}); llvm::sort(Table); // Now that it's sorted, ensure its unique. assert(std::adjacent_find(Table.begin(), Table.end()) == Table.end() && "Short form table is not unique!"); } }; } // namespace const X86InstrRelaxTableEntry *llvm::lookupShortTable(unsigned RelaxOp) { static X86ShortFormTable ShortTable; auto &Table = ShortTable.Table; auto I = llvm::lower_bound(Table, RelaxOp); if (I != Table.end() && I->KeyOp == RelaxOp) return &*I; return nullptr; } namespace llvm { /// Get the short instruction opcode for a given relaxed opcode. unsigned X86::getShortOpcodeArith(unsigned RelaxOp) { if (const X86InstrRelaxTableEntry *I = lookupShortTable(RelaxOp)) return I->DstOp; return RelaxOp; } /// Get the relaxed instruction opcode for a given short opcode. unsigned X86::getRelaxedOpcodeArith(unsigned ShortOp) { if (const X86InstrRelaxTableEntry *I = lookupRelaxTable(ShortOp)) return I->DstOp; return ShortOp; } } // namespace llvm