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