123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- //===- 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 <atomic>
- 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<X86InstrRelaxTableEntry> Table,
- unsigned ShortOp) {
- #ifndef NDEBUG
- // Make sure the tables are sorted.
- static std::atomic<bool> 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<X86InstrRelaxTableEntry, 0> 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
|