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
20using namespace llvm;
21
22bool 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(i: 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(RegNo: MI.getOperand(i: OpIdx1).getReg()) ||
93 !X86II::isX86_64ExtendedReg(RegNo: MI.getOperand(i: OpIdx2).getReg()))
94 return false;
95 if (NewOpc)
96 MI.setOpcode(NewOpc);
97 else
98 std::swap(a&: MI.getOperand(i: OpIdx1), b&: MI.getOperand(i: 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.
104bool 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(i: MI.getNumOperands() - 1);
195 if (!LastOp.isImm() || LastOp.getImm() != 1)
196 return false;
197 MI.setOpcode(NewOpc);
198 MI.erase(I: &LastOp);
199 return true;
200}
201
202bool 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(i: 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(I: &LastOp);
286 return true;
287}
288
289bool 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
311bool 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
332static 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.
337bool 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(i: 0).isReg() && MI.getOperand(i: 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(i: 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(i: AddrOp).isExpr()) {
375 const MCExpr *MCE = MI.getOperand(i: AddrOp).getExpr();
376 if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val: MCE))
377 if (SRE->getKind() == MCSymbolRefExpr::VK_TLVP)
378 Absolute = false;
379 }
380 if (Absolute && (MI.getOperand(i: AddrBase + X86::AddrBaseReg).getReg() != 0 ||
381 MI.getOperand(i: AddrBase + X86::AddrScaleAmt).getImm() != 1 ||
382 MI.getOperand(i: AddrBase + X86::AddrIndexReg).getReg() != 0))
383 return false;
384 // If so, rewrite the instruction.
385 MCOperand Saved = MI.getOperand(i: AddrOp);
386 MCOperand Seg = MI.getOperand(i: AddrBase + X86::AddrSegmentReg);
387 MI.clear();
388 MI.setOpcode(NewOpc);
389 MI.addOperand(Op: Saved);
390 MI.addOperand(Op: 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.
396static 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(i: 0).getReg();
440 if (!isARegister(Reg))
441 return false;
442
443 // If so, rewrite the instruction.
444 MCOperand Saved = MI.getOperand(i: MI.getNumOperands() - 1);
445 MI.clear();
446 MI.setOpcode(NewOpc);
447 MI.addOperand(Op: Saved);
448 return true;
449}
450
451unsigned 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
462unsigned 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
473static 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(Opcode: MI.getOpcode()) ? 2 : 0;
485 MCOperand &LastOp = MI.getOperand(i: MI.getNumOperands() - 1 - SkipOperands);
486 if (LastOp.isExpr()) {
487 const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val: LastOp.getExpr());
488 if (!SRE || SRE->getKind() != MCSymbolRefExpr::VK_X86_ABS8)
489 return false;
490 } else if (LastOp.isImm()) {
491 if (!isInt<8>(x: LastOp.getImm()))
492 return false;
493 }
494 MI.setOpcode(NewOpc);
495 return true;
496}
497
498bool 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