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