diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp --- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp +++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp @@ -11,7 +11,7 @@ //===----------------------------------------------------------------------===// #include "MCTargetDesc/X86BaseInfo.h" -#include "MCTargetDesc/X86InstrRelaxTables.h" +#include "MCTargetDesc/X86EncodingOptimization.h" #include "MCTargetDesc/X86MCTargetDesc.h" #include "X86MCSymbolizer.h" #include "bolt/Core/MCPlus.h" @@ -50,10 +50,6 @@ namespace { -unsigned getShortArithOpcode(unsigned Opcode) { - return X86::getShortOpcodeArith(Opcode); -} - bool isMOVSX64rm32(const MCInst &Inst) { return Inst.getOpcode() == X86::MOVSX64rm32; } @@ -1714,7 +1710,7 @@ } } else { // If it's arithmetic instruction check if signed operand fits in 1 byte. - const unsigned ShortOpcode = getShortArithOpcode(OldOpcode); + const unsigned ShortOpcode = X86::getOpcodeForShortImmediateForm(OldOpcode); if (ShortOpcode != OldOpcode && Inst.getOperand(MCPlus::getNumPrimeOperands(Inst) - 1).isImm()) { int64_t Imm = diff --git a/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt --- a/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt @@ -3,7 +3,6 @@ X86IntelInstPrinter.cpp X86InstComments.cpp X86InstPrinterCommon.cpp - X86InstrRelaxTables.cpp X86EncodingOptimization.cpp X86ShuffleDecode.cpp X86AsmBackend.cpp diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -8,7 +8,7 @@ #include "MCTargetDesc/X86BaseInfo.h" #include "MCTargetDesc/X86FixupKinds.h" -#include "MCTargetDesc/X86InstrRelaxTables.h" +#include "MCTargetDesc/X86EncodingOptimization.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MachO.h" @@ -221,13 +221,13 @@ } } -static unsigned getRelaxedOpcodeArith(const MCInst &Inst) { +static unsigned getOpcodeForLongImmediateForm(const MCInst &Inst) { unsigned Op = Inst.getOpcode(); - return X86::getRelaxedOpcodeArith(Op); + return X86::getOpcodeForLongImmediateForm(Op); } static unsigned getRelaxedOpcode(const MCInst &Inst, bool Is16BitMode) { - unsigned R = getRelaxedOpcodeArith(Inst); + unsigned R = getOpcodeForLongImmediateForm(Inst); if (R != Inst.getOpcode()) return R; return getRelaxedOpcodeBranch(Inst, Is16BitMode); @@ -728,7 +728,7 @@ return true; // Check if this instruction is ever relaxable. - if (getRelaxedOpcodeArith(Inst) == Inst.getOpcode()) + if (getOpcodeForLongImmediateForm(Inst) == Inst.getOpcode()) return false; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.h b/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.h --- a/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.h +++ b/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.h @@ -23,6 +23,8 @@ bool optimizeINCDEC(MCInst &MI, bool In64BitMode); bool optimizeMOV(MCInst &MI, bool In64BitMode); bool optimizeToFixedRegisterOrShortImmediateForm(MCInst &MI); +unsigned getOpcodeForShortImmediateForm(unsigned Opcode); +unsigned getOpcodeForLongImmediateForm(unsigned Opcode); } // namespace X86 } // namespace llvm #endif diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp @@ -425,68 +425,38 @@ return true; } +unsigned X86::getOpcodeForShortImmediateForm(unsigned Opcode) { +#define ENTRY(LONG, SHORT) \ + case X86::LONG: \ + return X86::SHORT; + switch (Opcode) { + default: + return Opcode; +#include "X86EncodingOptimizationForImmediate.def" + } +} + +unsigned X86::getOpcodeForLongImmediateForm(unsigned Opcode) { +#define ENTRY(LONG, SHORT) \ + case X86::SHORT: \ + return X86::LONG; + switch (Opcode) { + default: + return Opcode; +#include "X86EncodingOptimizationForImmediate.def" + } +} + static bool optimizeToShortImmediateForm(MCInst &MI) { unsigned NewOpc; +#define ENTRY(LONG, SHORT) \ + case X86::LONG: \ + NewOpc = X86::SHORT; \ + break; switch (MI.getOpcode()) { default: return false; - FROM_TO(ADC16mi, ADC16mi8) - FROM_TO(ADC16ri, ADC16ri8) - FROM_TO(ADC32mi, ADC32mi8) - FROM_TO(ADC32ri, ADC32ri8) - FROM_TO(ADC64mi32, ADC64mi8) - FROM_TO(ADC64ri32, ADC64ri8) - FROM_TO(SBB16mi, SBB16mi8) - FROM_TO(SBB16ri, SBB16ri8) - FROM_TO(SBB32mi, SBB32mi8) - FROM_TO(SBB32ri, SBB32ri8) - FROM_TO(SBB64mi32, SBB64mi8) - FROM_TO(SBB64ri32, SBB64ri8) - FROM_TO(ADD16mi, ADD16mi8) - FROM_TO(ADD16ri, ADD16ri8) - FROM_TO(ADD32mi, ADD32mi8) - FROM_TO(ADD32ri, ADD32ri8) - FROM_TO(ADD64mi32, ADD64mi8) - FROM_TO(ADD64ri32, ADD64ri8) - FROM_TO(AND16mi, AND16mi8) - FROM_TO(AND16ri, AND16ri8) - FROM_TO(AND32mi, AND32mi8) - FROM_TO(AND32ri, AND32ri8) - FROM_TO(AND64mi32, AND64mi8) - FROM_TO(AND64ri32, AND64ri8) - FROM_TO(OR16mi, OR16mi8) - FROM_TO(OR16ri, OR16ri8) - FROM_TO(OR32mi, OR32mi8) - FROM_TO(OR32ri, OR32ri8) - FROM_TO(OR64mi32, OR64mi8) - FROM_TO(OR64ri32, OR64ri8) - FROM_TO(SUB16mi, SUB16mi8) - FROM_TO(SUB16ri, SUB16ri8) - FROM_TO(SUB32mi, SUB32mi8) - FROM_TO(SUB32ri, SUB32ri8) - FROM_TO(SUB64mi32, SUB64mi8) - FROM_TO(SUB64ri32, SUB64ri8) - FROM_TO(XOR16mi, XOR16mi8) - FROM_TO(XOR16ri, XOR16ri8) - FROM_TO(XOR32mi, XOR32mi8) - FROM_TO(XOR32ri, XOR32ri8) - FROM_TO(XOR64mi32, XOR64mi8) - FROM_TO(XOR64ri32, XOR64ri8) - FROM_TO(CMP16mi, CMP16mi8) - FROM_TO(CMP16ri, CMP16ri8) - FROM_TO(CMP32mi, CMP32mi8) - FROM_TO(CMP32ri, CMP32ri8) - FROM_TO(CMP64mi32, CMP64mi8) - FROM_TO(CMP64ri32, CMP64ri8) - FROM_TO(IMUL16rmi, IMUL16rmi8) - FROM_TO(IMUL16rri, IMUL16rri8) - FROM_TO(IMUL32rmi, IMUL32rmi8) - FROM_TO(IMUL32rri, IMUL32rri8) - FROM_TO(IMUL64rmi32, IMUL64rmi8) - FROM_TO(IMUL64rri32, IMUL64rri8) - FROM_TO(PUSH16i, PUSH16i8) - FROM_TO(PUSH32i, PUSH32i8) - FROM_TO(PUSH64i32, PUSH64i8) +#include "X86EncodingOptimizationForImmediate.def" } MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1); if (LastOp.isExpr()) { diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimizationForImmediate.def b/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimizationForImmediate.def new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimizationForImmediate.def @@ -0,0 +1,72 @@ +//===- X86EncodingOptimizationForImmediate.def.def ---------------*- 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 +// +//===----------------------------------------------------------------------===// +// \file +// This file defines all the entries of X86 instruction relaxation for immediate +//===----------------------------------------------------------------------===// + +#ifndef ENTRY +#define ENTRY(LONG, SHORT) +#endif +ENTRY(ADC16mi, ADC16mi8) +ENTRY(ADC16ri, ADC16ri8) +ENTRY(ADC32mi, ADC32mi8) +ENTRY(ADC32ri, ADC32ri8) +ENTRY(ADC64mi32, ADC64mi8) +ENTRY(ADC64ri32, ADC64ri8) +ENTRY(SBB16mi, SBB16mi8) +ENTRY(SBB16ri, SBB16ri8) +ENTRY(SBB32mi, SBB32mi8) +ENTRY(SBB32ri, SBB32ri8) +ENTRY(SBB64mi32, SBB64mi8) +ENTRY(SBB64ri32, SBB64ri8) +ENTRY(ADD16mi, ADD16mi8) +ENTRY(ADD16ri, ADD16ri8) +ENTRY(ADD32mi, ADD32mi8) +ENTRY(ADD32ri, ADD32ri8) +ENTRY(ADD64mi32, ADD64mi8) +ENTRY(ADD64ri32, ADD64ri8) +ENTRY(AND16mi, AND16mi8) +ENTRY(AND16ri, AND16ri8) +ENTRY(AND32mi, AND32mi8) +ENTRY(AND32ri, AND32ri8) +ENTRY(AND64mi32, AND64mi8) +ENTRY(AND64ri32, AND64ri8) +ENTRY(OR16mi, OR16mi8) +ENTRY(OR16ri, OR16ri8) +ENTRY(OR32mi, OR32mi8) +ENTRY(OR32ri, OR32ri8) +ENTRY(OR64mi32, OR64mi8) +ENTRY(OR64ri32, OR64ri8) +ENTRY(SUB16mi, SUB16mi8) +ENTRY(SUB16ri, SUB16ri8) +ENTRY(SUB32mi, SUB32mi8) +ENTRY(SUB32ri, SUB32ri8) +ENTRY(SUB64mi32, SUB64mi8) +ENTRY(SUB64ri32, SUB64ri8) +ENTRY(XOR16mi, XOR16mi8) +ENTRY(XOR16ri, XOR16ri8) +ENTRY(XOR32mi, XOR32mi8) +ENTRY(XOR32ri, XOR32ri8) +ENTRY(XOR64mi32, XOR64mi8) +ENTRY(XOR64ri32, XOR64ri8) +ENTRY(CMP16mi, CMP16mi8) +ENTRY(CMP16ri, CMP16ri8) +ENTRY(CMP32mi, CMP32mi8) +ENTRY(CMP32ri, CMP32ri8) +ENTRY(CMP64mi32, CMP64mi8) +ENTRY(CMP64ri32, CMP64ri8) +ENTRY(IMUL16rmi, IMUL16rmi8) +ENTRY(IMUL16rri, IMUL16rri8) +ENTRY(IMUL32rmi, IMUL32rmi8) +ENTRY(IMUL32rri, IMUL32rri8) +ENTRY(IMUL64rmi32, IMUL64rmi8) +ENTRY(IMUL64rri32, IMUL64rri8) +ENTRY(PUSH16i, PUSH16i8) +ENTRY(PUSH32i, PUSH32i8) +ENTRY(PUSH64i32, PUSH64i8) +#undef ENTRY diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86InstrRelaxTables.h b/llvm/lib/Target/X86/MCTargetDesc/X86InstrRelaxTables.h deleted file mode 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86InstrRelaxTables.h +++ /dev/null @@ -1,54 +0,0 @@ -//===-- X86InstrRelaxTables.h - 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 interface to query the X86 instruction relaxation -// tables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_X86_X86INSTRRELAXTABLES_H -#define LLVM_LIB_TARGET_X86_X86INSTRRELAXTABLES_H - -#include - -namespace llvm { - -// This struct is used for both the relaxed and short tables. The KeyOp is used -// to determine the sorting order. -struct X86InstrRelaxTableEntry { - uint16_t KeyOp; - uint16_t DstOp; - - bool operator<(const X86InstrRelaxTableEntry &RHS) const { - return KeyOp < RHS.KeyOp; - } - bool operator==(const X86InstrRelaxTableEntry &RHS) const { - return KeyOp == RHS.KeyOp; - } - friend bool operator<(const X86InstrRelaxTableEntry &TE, unsigned Opcode) { - return TE.KeyOp < Opcode; - } -}; - -/// Look up the relaxed form table entry for a given \p ShortOp. -const X86InstrRelaxTableEntry *lookupRelaxTable(unsigned ShortOp); - -/// Look up the short form table entry for a given \p RelaxOp. -const X86InstrRelaxTableEntry *lookupShortTable(unsigned RelaxOp); - -namespace X86 { - -/// Get the short instruction opcode for a given relaxed opcode. -unsigned getShortOpcodeArith(unsigned RelaxOp); - -/// Get the relaxed instruction opcode for a given short opcode. -unsigned getRelaxedOpcodeArith(unsigned ShortOp); -} // namespace X86 -} // namespace llvm - -#endif diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86InstrRelaxTables.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86InstrRelaxTables.cpp deleted file mode 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86InstrRelaxTables.cpp +++ /dev/null @@ -1,165 +0,0 @@ -//===- 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::PUSH16i }, - { X86::PUSH32i8, X86::PUSH32i }, - { 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