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