Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- X86EncodingOptimization.cpp - X86 Encoding optimization -*- 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 implementation of the X86 encoding optimization
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "X86EncodingOptimization.h"
14
#include "X86BaseInfo.h"
15
#include "llvm/MC/MCExpr.h"
16
#include "llvm/MC/MCInst.h"
17
#include "llvm/MC/MCInstrDesc.h"
18
#include "llvm/Support/Casting.h"
19
20
using namespace llvm;
21
22
202k
bool X86::optimizeInstFromVEX3ToVEX2(MCInst &MI, const MCInstrDesc &Desc) {
23
202k
  unsigned OpIdx1, OpIdx2;
24
202k
  unsigned Opcode = MI.getOpcode();
25
202k
  unsigned NewOpc = 0;
26
202k
#define FROM_TO(FROM, TO, IDX1, IDX2)                                          \
27
202k
  case X86::FROM:                                                              \
28
0
    NewOpc = X86::TO;                                                          \
29
0
    OpIdx1 = IDX1;                                                             \
30
0
    OpIdx2 = IDX2;                                                             \
31
0
    break;
32
202k
#define TO_REV(FROM) FROM_TO(FROM, FROM##_REV, 0, 1)
33
202k
  switch (Opcode) {
34
202k
  default: {
35
    // If the instruction is a commutable arithmetic instruction we might be
36
    // able to commute the operands to get a 2 byte VEX prefix.
37
202k
    uint64_t TSFlags = Desc.TSFlags;
38
202k
    if (!Desc.isCommutable() || (TSFlags & X86II::EncodingMask) != X86II::VEX ||
39
202k
        (TSFlags & X86II::OpMapMask) != X86II::TB ||
40
202k
        (TSFlags & X86II::FormMask) != X86II::MRMSrcReg ||
41
202k
        (TSFlags & X86II::REX_W) || !(TSFlags & X86II::VEX_4V) ||
42
202k
        MI.getNumOperands() != 3)
43
202k
      return false;
44
    // These two are not truly commutable.
45
4
    if (Opcode == X86::VMOVHLPSrr || Opcode == X86::VUNPCKHPDrr)
46
0
      return false;
47
4
    OpIdx1 = 1;
48
4
    OpIdx2 = 2;
49
4
    break;
50
4
  }
51
0
  case X86::VCMPPDrri:
52
0
  case X86::VCMPPDYrri:
53
0
  case X86::VCMPPSrri:
54
0
  case X86::VCMPPSYrri:
55
0
  case X86::VCMPSDrr:
56
0
  case X86::VCMPSSrr: {
57
0
    switch (MI.getOperand(3).getImm() & 0x7) {
58
0
    default:
59
0
      return false;
60
0
    case 0x00: // EQUAL
61
0
    case 0x03: // UNORDERED
62
0
    case 0x04: // NOT EQUAL
63
0
    case 0x07: // ORDERED
64
0
      OpIdx1 = 1;
65
0
      OpIdx2 = 2;
66
0
      break;
67
0
    }
68
0
    break;
69
0
  }
70
    // Commute operands to get a smaller encoding by using VEX.R instead of
71
    // VEX.B if one of the registers is extended, but other isn't.
72
0
    FROM_TO(VMOVZPQILo2PQIrr, VMOVPQI2QIrr, 0, 1)
73
0
    TO_REV(VMOVAPDrr)
74
0
    TO_REV(VMOVAPDYrr)
75
0
    TO_REV(VMOVAPSrr)
76
0
    TO_REV(VMOVAPSYrr)
77
0
    TO_REV(VMOVDQArr)
78
0
    TO_REV(VMOVDQAYrr)
79
0
    TO_REV(VMOVDQUrr)
80
0
    TO_REV(VMOVDQUYrr)
81
0
    TO_REV(VMOVUPDrr)
82
0
    TO_REV(VMOVUPDYrr)
83
0
    TO_REV(VMOVUPSrr)
84
0
    TO_REV(VMOVUPSYrr)
85
0
#undef TO_REV
86
0
#define TO_REV(FROM) FROM_TO(FROM, FROM##_REV, 0, 2)
87
0
    TO_REV(VMOVSDrr)
88
202k
    TO_REV(VMOVSSrr)
89
202k
#undef TO_REV
90
202k
#undef FROM_TO
91
202k
  }
92
4
  if (X86II::isX86_64ExtendedReg(MI.getOperand(OpIdx1).getReg()) ||
93
4
      !X86II::isX86_64ExtendedReg(MI.getOperand(OpIdx2).getReg()))
94
4
    return false;
95
0
  if (NewOpc)
96
0
    MI.setOpcode(NewOpc);
97
0
  else
98
0
    std::swap(MI.getOperand(OpIdx1), MI.getOperand(OpIdx2));
99
0
  return true;
100
4
}
101
102
// NOTE: We may write this as an InstAlias if it's only used by AsmParser. See
103
// validateTargetOperandClass.
104
202k
bool X86::optimizeShiftRotateWithImmediateOne(MCInst &MI) {
105
202k
  unsigned NewOpc;
106
202k
#define TO_IMM1(FROM)                                                          \
107
202k
  case X86::FROM##i:                                                           \
108
3.68k
    NewOpc = X86::FROM##1;                                                     \
109
3.68k
    break;
110
202k
  switch (MI.getOpcode()) {
111
198k
  default:
112
198k
    return false;
113
0
    TO_IMM1(RCR8r)
114
0
    TO_IMM1(RCR16r)
115
0
    TO_IMM1(RCR32r)
116
0
    TO_IMM1(RCR64r)
117
0
    TO_IMM1(RCL8r)
118
0
    TO_IMM1(RCL16r)
119
0
    TO_IMM1(RCL32r)
120
0
    TO_IMM1(RCL64r)
121
0
    TO_IMM1(ROR8r)
122
2
    TO_IMM1(ROR16r)
123
2
    TO_IMM1(ROR32r)
124
0
    TO_IMM1(ROR64r)
125
0
    TO_IMM1(ROL8r)
126
14
    TO_IMM1(ROL16r)
127
8
    TO_IMM1(ROL32r)
128
2
    TO_IMM1(ROL64r)
129
490
    TO_IMM1(SAR8r)
130
0
    TO_IMM1(SAR16r)
131
230
    TO_IMM1(SAR32r)
132
168
    TO_IMM1(SAR64r)
133
456
    TO_IMM1(SHR8r)
134
0
    TO_IMM1(SHR16r)
135
509
    TO_IMM1(SHR32r)
136
306
    TO_IMM1(SHR64r)
137
431
    TO_IMM1(SHL8r)
138
0
    TO_IMM1(SHL16r)
139
726
    TO_IMM1(SHL32r)
140
342
    TO_IMM1(SHL64r)
141
0
    TO_IMM1(RCR8m)
142
0
    TO_IMM1(RCR16m)
143
0
    TO_IMM1(RCR32m)
144
0
    TO_IMM1(RCR64m)
145
0
    TO_IMM1(RCL8m)
146
0
    TO_IMM1(RCL16m)
147
0
    TO_IMM1(RCL32m)
148
0
    TO_IMM1(RCL64m)
149
0
    TO_IMM1(ROR8m)
150
0
    TO_IMM1(ROR16m)
151
0
    TO_IMM1(ROR32m)
152
0
    TO_IMM1(ROR64m)
153
0
    TO_IMM1(ROL8m)
154
0
    TO_IMM1(ROL16m)
155
0
    TO_IMM1(ROL32m)
156
0
    TO_IMM1(ROL64m)
157
0
    TO_IMM1(SAR8m)
158
0
    TO_IMM1(SAR16m)
159
0
    TO_IMM1(SAR32m)
160
0
    TO_IMM1(SAR64m)
161
0
    TO_IMM1(SHR8m)
162
0
    TO_IMM1(SHR16m)
163
0
    TO_IMM1(SHR32m)
164
0
    TO_IMM1(SHR64m)
165
0
    TO_IMM1(SHL8m)
166
0
    TO_IMM1(SHL16m)
167
0
    TO_IMM1(SHL32m)
168
202k
    TO_IMM1(SHL64m)
169
202k
#undef TO_IMM1
170
202k
  }
171
3.68k
  MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1);
172
3.68k
  if (!LastOp.isImm() || LastOp.getImm() != 1)
173
3.37k
    return false;
174
312
  MI.setOpcode(NewOpc);
175
312
  MI.erase(&LastOp);
176
312
  return true;
177
3.68k
}
178
179
202k
bool X86::optimizeVPCMPWithImmediateOneOrSix(MCInst &MI) {
180
202k
  unsigned Opc1;
181
202k
  unsigned Opc2;
182
202k
#define FROM_TO(FROM, TO1, TO2)                                                \
183
202k
  case X86::FROM:                                                              \
184
0
    Opc1 = X86::TO1;                                                           \
185
0
    Opc2 = X86::TO2;                                                           \
186
0
    break;
187
202k
  switch (MI.getOpcode()) {
188
202k
  default:
189
202k
    return false;
190
0
    FROM_TO(VPCMPBZ128rmi, VPCMPEQBZ128rm, VPCMPGTBZ128rm)
191
0
    FROM_TO(VPCMPBZ128rmik, VPCMPEQBZ128rmk, VPCMPGTBZ128rmk)
192
0
    FROM_TO(VPCMPBZ128rri, VPCMPEQBZ128rr, VPCMPGTBZ128rr)
193
0
    FROM_TO(VPCMPBZ128rrik, VPCMPEQBZ128rrk, VPCMPGTBZ128rrk)
194
0
    FROM_TO(VPCMPBZ256rmi, VPCMPEQBZ256rm, VPCMPGTBZ256rm)
195
0
    FROM_TO(VPCMPBZ256rmik, VPCMPEQBZ256rmk, VPCMPGTBZ256rmk)
196
0
    FROM_TO(VPCMPBZ256rri, VPCMPEQBZ256rr, VPCMPGTBZ256rr)
197
0
    FROM_TO(VPCMPBZ256rrik, VPCMPEQBZ256rrk, VPCMPGTBZ256rrk)
198
0
    FROM_TO(VPCMPBZrmi, VPCMPEQBZrm, VPCMPGTBZrm)
199
0
    FROM_TO(VPCMPBZrmik, VPCMPEQBZrmk, VPCMPGTBZrmk)
200
0
    FROM_TO(VPCMPBZrri, VPCMPEQBZrr, VPCMPGTBZrr)
201
0
    FROM_TO(VPCMPBZrrik, VPCMPEQBZrrk, VPCMPGTBZrrk)
202
0
    FROM_TO(VPCMPDZ128rmi, VPCMPEQDZ128rm, VPCMPGTDZ128rm)
203
0
    FROM_TO(VPCMPDZ128rmib, VPCMPEQDZ128rmb, VPCMPGTDZ128rmb)
204
0
    FROM_TO(VPCMPDZ128rmibk, VPCMPEQDZ128rmbk, VPCMPGTDZ128rmbk)
205
0
    FROM_TO(VPCMPDZ128rmik, VPCMPEQDZ128rmk, VPCMPGTDZ128rmk)
206
0
    FROM_TO(VPCMPDZ128rri, VPCMPEQDZ128rr, VPCMPGTDZ128rr)
207
0
    FROM_TO(VPCMPDZ128rrik, VPCMPEQDZ128rrk, VPCMPGTDZ128rrk)
208
0
    FROM_TO(VPCMPDZ256rmi, VPCMPEQDZ256rm, VPCMPGTDZ256rm)
209
0
    FROM_TO(VPCMPDZ256rmib, VPCMPEQDZ256rmb, VPCMPGTDZ256rmb)
210
0
    FROM_TO(VPCMPDZ256rmibk, VPCMPEQDZ256rmbk, VPCMPGTDZ256rmbk)
211
0
    FROM_TO(VPCMPDZ256rmik, VPCMPEQDZ256rmk, VPCMPGTDZ256rmk)
212
0
    FROM_TO(VPCMPDZ256rri, VPCMPEQDZ256rr, VPCMPGTDZ256rr)
213
0
    FROM_TO(VPCMPDZ256rrik, VPCMPEQDZ256rrk, VPCMPGTDZ256rrk)
214
0
    FROM_TO(VPCMPDZrmi, VPCMPEQDZrm, VPCMPGTDZrm)
215
0
    FROM_TO(VPCMPDZrmib, VPCMPEQDZrmb, VPCMPGTDZrmb)
216
0
    FROM_TO(VPCMPDZrmibk, VPCMPEQDZrmbk, VPCMPGTDZrmbk)
217
0
    FROM_TO(VPCMPDZrmik, VPCMPEQDZrmk, VPCMPGTDZrmk)
218
0
    FROM_TO(VPCMPDZrri, VPCMPEQDZrr, VPCMPGTDZrr)
219
0
    FROM_TO(VPCMPDZrrik, VPCMPEQDZrrk, VPCMPGTDZrrk)
220
0
    FROM_TO(VPCMPQZ128rmi, VPCMPEQQZ128rm, VPCMPGTQZ128rm)
221
0
    FROM_TO(VPCMPQZ128rmib, VPCMPEQQZ128rmb, VPCMPGTQZ128rmb)
222
0
    FROM_TO(VPCMPQZ128rmibk, VPCMPEQQZ128rmbk, VPCMPGTQZ128rmbk)
223
0
    FROM_TO(VPCMPQZ128rmik, VPCMPEQQZ128rmk, VPCMPGTQZ128rmk)
224
0
    FROM_TO(VPCMPQZ128rri, VPCMPEQQZ128rr, VPCMPGTQZ128rr)
225
0
    FROM_TO(VPCMPQZ128rrik, VPCMPEQQZ128rrk, VPCMPGTQZ128rrk)
226
0
    FROM_TO(VPCMPQZ256rmi, VPCMPEQQZ256rm, VPCMPGTQZ256rm)
227
0
    FROM_TO(VPCMPQZ256rmib, VPCMPEQQZ256rmb, VPCMPGTQZ256rmb)
228
0
    FROM_TO(VPCMPQZ256rmibk, VPCMPEQQZ256rmbk, VPCMPGTQZ256rmbk)
229
0
    FROM_TO(VPCMPQZ256rmik, VPCMPEQQZ256rmk, VPCMPGTQZ256rmk)
230
0
    FROM_TO(VPCMPQZ256rri, VPCMPEQQZ256rr, VPCMPGTQZ256rr)
231
0
    FROM_TO(VPCMPQZ256rrik, VPCMPEQQZ256rrk, VPCMPGTQZ256rrk)
232
0
    FROM_TO(VPCMPQZrmi, VPCMPEQQZrm, VPCMPGTQZrm)
233
0
    FROM_TO(VPCMPQZrmib, VPCMPEQQZrmb, VPCMPGTQZrmb)
234
0
    FROM_TO(VPCMPQZrmibk, VPCMPEQQZrmbk, VPCMPGTQZrmbk)
235
0
    FROM_TO(VPCMPQZrmik, VPCMPEQQZrmk, VPCMPGTQZrmk)
236
0
    FROM_TO(VPCMPQZrri, VPCMPEQQZrr, VPCMPGTQZrr)
237
0
    FROM_TO(VPCMPQZrrik, VPCMPEQQZrrk, VPCMPGTQZrrk)
238
0
    FROM_TO(VPCMPWZ128rmi, VPCMPEQWZ128rm, VPCMPGTWZ128rm)
239
0
    FROM_TO(VPCMPWZ128rmik, VPCMPEQWZ128rmk, VPCMPGTWZ128rmk)
240
0
    FROM_TO(VPCMPWZ128rri, VPCMPEQWZ128rr, VPCMPGTWZ128rr)
241
0
    FROM_TO(VPCMPWZ128rrik, VPCMPEQWZ128rrk, VPCMPGTWZ128rrk)
242
0
    FROM_TO(VPCMPWZ256rmi, VPCMPEQWZ256rm, VPCMPGTWZ256rm)
243
0
    FROM_TO(VPCMPWZ256rmik, VPCMPEQWZ256rmk, VPCMPGTWZ256rmk)
244
0
    FROM_TO(VPCMPWZ256rri, VPCMPEQWZ256rr, VPCMPGTWZ256rr)
245
0
    FROM_TO(VPCMPWZ256rrik, VPCMPEQWZ256rrk, VPCMPGTWZ256rrk)
246
0
    FROM_TO(VPCMPWZrmi, VPCMPEQWZrm, VPCMPGTWZrm)
247
0
    FROM_TO(VPCMPWZrmik, VPCMPEQWZrmk, VPCMPGTWZrmk)
248
0
    FROM_TO(VPCMPWZrri, VPCMPEQWZrr, VPCMPGTWZrr)
249
202k
    FROM_TO(VPCMPWZrrik, VPCMPEQWZrrk, VPCMPGTWZrrk)
250
202k
#undef FROM_TO
251
202k
  }
252
0
  MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1);
253
0
  int64_t Imm = LastOp.getImm();
254
0
  unsigned NewOpc;
255
0
  if (Imm == 0)
256
0
    NewOpc = Opc1;
257
0
  else if(Imm == 6)
258
0
    NewOpc = Opc2;
259
0
  else
260
0
    return false;
261
0
  MI.setOpcode(NewOpc);
262
0
  MI.erase(&LastOp);
263
0
  return true;
264
0
}
265
266
202k
bool X86::optimizeMOVSX(MCInst &MI) {
267
202k
  unsigned NewOpc;
268
202k
#define FROM_TO(FROM, TO, R0, R1)                                              \
269
202k
  case X86::FROM:                                                              \
270
619
    if (MI.getOperand(0).getReg() != X86::R0 ||                                \
271
619
        MI.getOperand(1).getReg() != X86::R1)                                  \
272
471
      return false;                                                            \
273
148
    NewOpc = X86::TO;                                                          \
274
148
    break;
275
202k
  switch (MI.getOpcode()) {
276
201k
  default:
277
201k
    return false;
278
    FROM_TO(MOVSX16rr8, CBW, AX, AL)     // movsbw %al, %ax   --> cbtw
279
    FROM_TO(MOVSX32rr16, CWDE, EAX, AX)  // movswl %ax, %eax  --> cwtl
280
    FROM_TO(MOVSX64rr32, CDQE, RAX, EAX) // movslq %eax, %rax --> cltq
281
202k
#undef FROM_TO
282
202k
  }
283
148
  MI.clear();
284
148
  MI.setOpcode(NewOpc);
285
148
  return true;
286
202k
}
287
288
202k
bool X86::optimizeINCDEC(MCInst &MI, bool In64BitMode) {
289
202k
  if (In64BitMode)
290
202k
    return false;
291
0
  unsigned NewOpc;
292
  // If we aren't in 64-bit mode we can use the 1-byte inc/dec instructions.
293
0
#define FROM_TO(FROM, TO)                                                      \
294
5.07k
  case X86::FROM:                                                              \
295
5.07k
    NewOpc = X86::TO;                                                          \
296
5.07k
    break;
297
0
  switch (MI.getOpcode()) {
298
0
  default:
299
0
    return false;
300
0
    FROM_TO(DEC16r, DEC16r_alt)
301
0
    FROM_TO(DEC32r, DEC32r_alt)
302
0
    FROM_TO(INC16r, INC16r_alt)
303
0
    FROM_TO(INC32r, INC32r_alt)
304
0
  }
305
0
  MI.setOpcode(NewOpc);
306
0
  return true;
307
0
}
308
309
5.07k
static bool isARegister(unsigned Reg) {
310
5.07k
  return Reg == X86::AL || Reg == X86::AX || Reg == X86::EAX || Reg == X86::RAX;
311
5.07k
}
312
313
/// Simplify things like MOV32rm to MOV32o32a.
314
202k
bool X86::optimizeMOV(MCInst &MI, bool In64BitMode) {
315
  // Don't make these simplifications in 64-bit mode; other assemblers don't
316
  // perform them because they make the code larger.
317
202k
  if (In64BitMode)
318
202k
    return false;
319
0
  unsigned NewOpc;
320
  // We don't currently select the correct instruction form for instructions
321
  // which have a short %eax, etc. form. Handle this by custom lowering, for
322
  // now.
323
  //
324
  // Note, we are currently not handling the following instructions:
325
  // MOV64ao8, MOV64o8a
326
  // XCHG16ar, XCHG32ar, XCHG64ar
327
0
  switch (MI.getOpcode()) {
328
0
  default:
329
0
    return false;
330
0
    FROM_TO(MOV8mr_NOREX, MOV8o32a)
331
0
    FROM_TO(MOV8mr, MOV8o32a)
332
0
    FROM_TO(MOV8rm_NOREX, MOV8ao32)
333
0
    FROM_TO(MOV8rm, MOV8ao32)
334
0
    FROM_TO(MOV16mr, MOV16o32a)
335
0
    FROM_TO(MOV16rm, MOV16ao32)
336
0
    FROM_TO(MOV32mr, MOV32o32a)
337
0
    FROM_TO(MOV32rm, MOV32ao32)
338
0
  }
339
0
  bool IsStore = MI.getOperand(0).isReg() && MI.getOperand(1).isReg();
340
0
  unsigned AddrBase = IsStore;
341
0
  unsigned RegOp = IsStore ? 0 : 5;
342
0
  unsigned AddrOp = AddrBase + 3;
343
  // Check whether the destination register can be fixed.
344
0
  unsigned Reg = MI.getOperand(RegOp).getReg();
345
0
  if (!isARegister(Reg))
346
0
    return false;
347
  // Check whether this is an absolute address.
348
  // FIXME: We know TLVP symbol refs aren't, but there should be a better way
349
  // to do this here.
350
0
  bool Absolute = true;
351
0
  if (MI.getOperand(AddrOp).isExpr()) {
352
0
    const MCExpr *MCE = MI.getOperand(AddrOp).getExpr();
353
0
    if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(MCE))
354
0
      if (SRE->getKind() == MCSymbolRefExpr::VK_TLVP)
355
0
        Absolute = false;
356
0
  }
357
0
  if (Absolute && (MI.getOperand(AddrBase + X86::AddrBaseReg).getReg() != 0 ||
358
0
                   MI.getOperand(AddrBase + X86::AddrScaleAmt).getImm() != 1 ||
359
0
                   MI.getOperand(AddrBase + X86::AddrIndexReg).getReg() != 0))
360
0
    return false;
361
  // If so, rewrite the instruction.
362
0
  MCOperand Saved = MI.getOperand(AddrOp);
363
0
  MCOperand Seg = MI.getOperand(AddrBase + X86::AddrSegmentReg);
364
0
  MI.clear();
365
0
  MI.setOpcode(NewOpc);
366
0
  MI.addOperand(Saved);
367
0
  MI.addOperand(Seg);
368
0
  return true;
369
0
}
370
371
/// Simplify FOO $imm, %{al,ax,eax,rax} to FOO $imm, for instruction with
372
/// a short fixed-register form.
373
202k
static bool optimizeToFixedRegisterForm(MCInst &MI) {
374
202k
  unsigned NewOpc;
375
202k
  switch (MI.getOpcode()) {
376
196k
  default:
377
196k
    return false;
378
13
    FROM_TO(ADC8ri, ADC8i8)
379
0
    FROM_TO(ADC16ri, ADC16i16)
380
1
    FROM_TO(ADC32ri, ADC32i32)
381
2
    FROM_TO(ADC64ri32, ADC64i32)
382
142
    FROM_TO(ADD8ri, ADD8i8)
383
0
    FROM_TO(ADD16ri, ADD16i16)
384
172
    FROM_TO(ADD32ri, ADD32i32)
385
221
    FROM_TO(ADD64ri32, ADD64i32)
386
826
    FROM_TO(AND8ri, AND8i8)
387
0
    FROM_TO(AND16ri, AND16i16)
388
300
    FROM_TO(AND32ri, AND32i32)
389
1
    FROM_TO(AND64ri32, AND64i32)
390
965
    FROM_TO(CMP8ri, CMP8i8)
391
0
    FROM_TO(CMP16ri, CMP16i16)
392
653
    FROM_TO(CMP32ri, CMP32i32)
393
531
    FROM_TO(CMP64ri32, CMP64i32)
394
74
    FROM_TO(OR8ri, OR8i8)
395
1
    FROM_TO(OR16ri, OR16i16)
396
56
    FROM_TO(OR32ri, OR32i32)
397
7
    FROM_TO(OR64ri32, OR64i32)
398
4
    FROM_TO(SBB8ri, SBB8i8)
399
0
    FROM_TO(SBB16ri, SBB16i16)
400
0
    FROM_TO(SBB32ri, SBB32i32)
401
0
    FROM_TO(SBB64ri32, SBB64i32)
402
34
    FROM_TO(SUB8ri, SUB8i8)
403
0
    FROM_TO(SUB16ri, SUB16i16)
404
0
    FROM_TO(SUB32ri, SUB32i32)
405
162
    FROM_TO(SUB64ri32, SUB64i32)
406
706
    FROM_TO(TEST8ri, TEST8i8)
407
0
    FROM_TO(TEST16ri, TEST16i16)
408
67
    FROM_TO(TEST32ri, TEST32i32)
409
0
    FROM_TO(TEST64ri32, TEST64i32)
410
86
    FROM_TO(XOR8ri, XOR8i8)
411
0
    FROM_TO(XOR16ri, XOR16i16)
412
33
    FROM_TO(XOR32ri, XOR32i32)
413
202k
    FROM_TO(XOR64ri32, XOR64i32)
414
202k
  }
415
  // Check whether the destination register can be fixed.
416
5.07k
  unsigned Reg = MI.getOperand(0).getReg();
417
5.07k
  if (!isARegister(Reg))
418
4.05k
    return false;
419
420
  // If so, rewrite the instruction.
421
1.01k
  MCOperand Saved = MI.getOperand(MI.getNumOperands() - 1);
422
1.01k
  MI.clear();
423
1.01k
  MI.setOpcode(NewOpc);
424
1.01k
  MI.addOperand(Saved);
425
1.01k
  return true;
426
5.07k
}
427
428
0
unsigned X86::getOpcodeForShortImmediateForm(unsigned Opcode) {
429
0
#define ENTRY(LONG, SHORT)                                                     \
430
0
  case X86::LONG:                                                              \
431
0
    return X86::SHORT;
432
0
  switch (Opcode) {
433
0
  default:
434
0
    return Opcode;
435
0
#include "X86EncodingOptimizationForImmediate.def"
436
0
  }
437
0
}
438
439
0
unsigned X86::getOpcodeForLongImmediateForm(unsigned Opcode) {
440
0
#define ENTRY(LONG, SHORT)                                                     \
441
0
  case X86::SHORT:                                                             \
442
0
    return X86::LONG;
443
0
  switch (Opcode) {
444
0
  default:
445
0
    return Opcode;
446
0
#include "X86EncodingOptimizationForImmediate.def"
447
0
  }
448
0
}
449
450
202k
static bool optimizeToShortImmediateForm(MCInst &MI) {
451
202k
  unsigned NewOpc;
452
202k
#define ENTRY(LONG, SHORT)                                                     \
453
202k
  case X86::LONG:                                                              \
454
9.09k
    NewOpc = X86::SHORT;                                                       \
455
9.09k
    break;
456
202k
  switch (MI.getOpcode()) {
457
192k
  default:
458
192k
    return false;
459
202k
#include "X86EncodingOptimizationForImmediate.def"
460
202k
  }
461
9.09k
  MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1);
462
9.09k
  if (LastOp.isExpr()) {
463
0
    const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(LastOp.getExpr());
464
0
    if (!SRE || SRE->getKind() != MCSymbolRefExpr::VK_X86_ABS8)
465
0
      return false;
466
9.09k
  } else if (LastOp.isImm()) {
467
9.09k
    if (!isInt<8>(LastOp.getImm()))
468
2.40k
      return false;
469
9.09k
  }
470
6.68k
  MI.setOpcode(NewOpc);
471
6.68k
  return true;
472
9.09k
}
473
474
202k
bool X86::optimizeToFixedRegisterOrShortImmediateForm(MCInst &MI) {
475
  // We may optimize twice here.
476
202k
  bool ShortImm = optimizeToShortImmediateForm(MI);
477
202k
  bool FixedReg = optimizeToFixedRegisterForm(MI);
478
202k
  return ShortImm || FixedReg;
479
202k
}