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 21 using namespace llvm; 22 23 bool 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(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(MI.getOperand(OpIdx1).getReg()) || 94 !X86II::isX86_64ExtendedReg(MI.getOperand(OpIdx2).getReg())) 95 return false; 96 if (NewOpc) 97 MI.setOpcode(NewOpc); 98 else 99 std::swap(MI.getOperand(OpIdx1), MI.getOperand(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. 105 bool 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(MI.getNumOperands() - 1); 196 if (!LastOp.isImm() || LastOp.getImm() != 1) 197 return false; 198 MI.setOpcode(NewOpc); 199 MI.erase(&LastOp); 200 return true; 201 } 202 203 bool 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(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(&LastOp); 287 return true; 288 } 289 290 bool 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 312 bool 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 333 static 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. 338 bool 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(0).isReg() && MI.getOperand(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(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(AddrOp).isExpr()) { 376 const MCExpr *MCE = MI.getOperand(AddrOp).getExpr(); 377 if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(MCE)) 378 if (SRE->getSpecifier() == X86::S_TLVP) 379 Absolute = false; 380 } 381 if (Absolute && (MI.getOperand(AddrBase + X86::AddrBaseReg).getReg() || 382 MI.getOperand(AddrBase + X86::AddrScaleAmt).getImm() != 1 || 383 MI.getOperand(AddrBase + X86::AddrIndexReg).getReg())) 384 return false; 385 // If so, rewrite the instruction. 386 MCOperand Saved = MI.getOperand(AddrOp); 387 MCOperand Seg = MI.getOperand(AddrBase + X86::AddrSegmentReg); 388 MI.clear(); 389 MI.setOpcode(NewOpc); 390 MI.addOperand(Saved); 391 MI.addOperand(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. 397 static 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(0).getReg(); 441 if (!isARegister(Reg)) 442 return false; 443 444 // If so, rewrite the instruction. 445 MCOperand Saved = MI.getOperand(MI.getNumOperands() - 1); 446 MI.clear(); 447 MI.setOpcode(NewOpc); 448 MI.addOperand(Saved); 449 return true; 450 } 451 452 unsigned 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 463 unsigned 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 474 static 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(MI.getOpcode()) ? 2 : 0; 486 MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1 - SkipOperands); 487 if (LastOp.isExpr()) { 488 const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(LastOp.getExpr()); 489 if (!SRE || SRE->getSpecifier() != X86::S_ABS8) 490 return false; 491 } else if (LastOp.isImm()) { 492 if (!isInt<8>(LastOp.getImm())) 493 return false; 494 } 495 MI.setOpcode(NewOpc); 496 return true; 497 } 498 499 bool 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