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