1db39d479SShengchen Kan //===-- X86EncodingOptimization.cpp - X86 Encoding optimization -*- C++ -*-===// 2db39d479SShengchen Kan // 3db39d479SShengchen Kan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4db39d479SShengchen Kan // See https://llvm.org/LICENSE.txt for license information. 5db39d479SShengchen Kan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6db39d479SShengchen Kan // 7db39d479SShengchen Kan //===----------------------------------------------------------------------===// 8db39d479SShengchen Kan // 9db39d479SShengchen Kan // This file contains the implementation of the X86 encoding optimization 10db39d479SShengchen Kan // 11db39d479SShengchen Kan //===----------------------------------------------------------------------===// 12db39d479SShengchen Kan 13db39d479SShengchen Kan #include "X86EncodingOptimization.h" 14db39d479SShengchen Kan #include "X86BaseInfo.h" 1515100a2dSShengchen Kan #include "llvm/MC/MCExpr.h" 16db39d479SShengchen Kan #include "llvm/MC/MCInst.h" 17db39d479SShengchen Kan #include "llvm/MC/MCInstrDesc.h" 1815100a2dSShengchen Kan #include "llvm/Support/Casting.h" 19db39d479SShengchen Kan 20db39d479SShengchen Kan using namespace llvm; 21db39d479SShengchen Kan 22db39d479SShengchen Kan bool X86::optimizeInstFromVEX3ToVEX2(MCInst &MI, const MCInstrDesc &Desc) { 23db39d479SShengchen Kan unsigned OpIdx1, OpIdx2; 24db39d479SShengchen Kan unsigned Opcode = MI.getOpcode(); 2587671db0SShengchen Kan unsigned NewOpc = 0; 26db39d479SShengchen Kan #define FROM_TO(FROM, TO, IDX1, IDX2) \ 27db39d479SShengchen Kan case X86::FROM: \ 28db39d479SShengchen Kan NewOpc = X86::TO; \ 29db39d479SShengchen Kan OpIdx1 = IDX1; \ 30db39d479SShengchen Kan OpIdx2 = IDX2; \ 31db39d479SShengchen Kan break; 32db39d479SShengchen Kan #define TO_REV(FROM) FROM_TO(FROM, FROM##_REV, 0, 1) 3387671db0SShengchen Kan switch (Opcode) { 34db39d479SShengchen Kan default: { 35db39d479SShengchen Kan // If the instruction is a commutable arithmetic instruction we might be 36db39d479SShengchen Kan // able to commute the operands to get a 2 byte VEX prefix. 37db39d479SShengchen Kan uint64_t TSFlags = Desc.TSFlags; 38db39d479SShengchen Kan if (!Desc.isCommutable() || (TSFlags & X86II::EncodingMask) != X86II::VEX || 39db39d479SShengchen Kan (TSFlags & X86II::OpMapMask) != X86II::TB || 40db39d479SShengchen Kan (TSFlags & X86II::FormMask) != X86II::MRMSrcReg || 41db39d479SShengchen Kan (TSFlags & X86II::REX_W) || !(TSFlags & X86II::VEX_4V) || 42db39d479SShengchen Kan MI.getNumOperands() != 3) 43db39d479SShengchen Kan return false; 44db39d479SShengchen Kan // These two are not truly commutable. 45db39d479SShengchen Kan if (Opcode == X86::VMOVHLPSrr || Opcode == X86::VUNPCKHPDrr) 46db39d479SShengchen Kan return false; 47db39d479SShengchen Kan OpIdx1 = 1; 48db39d479SShengchen Kan OpIdx2 = 2; 4987671db0SShengchen Kan break; 50db39d479SShengchen Kan } 51025c1587SShengchen Kan case X86::VCMPPDrri: 52025c1587SShengchen Kan case X86::VCMPPDYrri: 53025c1587SShengchen Kan case X86::VCMPPSrri: 54025c1587SShengchen Kan case X86::VCMPPSYrri: 5592d7aca4SSimon Pilgrim case X86::VCMPSDrri: 5692d7aca4SSimon Pilgrim case X86::VCMPSSrri: { 57025c1587SShengchen Kan switch (MI.getOperand(3).getImm() & 0x7) { 58025c1587SShengchen Kan default: 59025c1587SShengchen Kan return false; 60025c1587SShengchen Kan case 0x00: // EQUAL 61025c1587SShengchen Kan case 0x03: // UNORDERED 62025c1587SShengchen Kan case 0x04: // NOT EQUAL 63025c1587SShengchen Kan case 0x07: // ORDERED 64025c1587SShengchen Kan OpIdx1 = 1; 65025c1587SShengchen Kan OpIdx2 = 2; 66025c1587SShengchen Kan break; 67025c1587SShengchen Kan } 68025c1587SShengchen Kan break; 69025c1587SShengchen Kan } 70db39d479SShengchen Kan // Commute operands to get a smaller encoding by using VEX.R instead of 71db39d479SShengchen Kan // VEX.B if one of the registers is extended, but other isn't. 72db39d479SShengchen Kan FROM_TO(VMOVZPQILo2PQIrr, VMOVPQI2QIrr, 0, 1) 73db39d479SShengchen Kan TO_REV(VMOVAPDrr) 74db39d479SShengchen Kan TO_REV(VMOVAPDYrr) 75db39d479SShengchen Kan TO_REV(VMOVAPSrr) 76db39d479SShengchen Kan TO_REV(VMOVAPSYrr) 77db39d479SShengchen Kan TO_REV(VMOVDQArr) 78db39d479SShengchen Kan TO_REV(VMOVDQAYrr) 79db39d479SShengchen Kan TO_REV(VMOVDQUrr) 80db39d479SShengchen Kan TO_REV(VMOVDQUYrr) 81db39d479SShengchen Kan TO_REV(VMOVUPDrr) 82db39d479SShengchen Kan TO_REV(VMOVUPDYrr) 83db39d479SShengchen Kan TO_REV(VMOVUPSrr) 84db39d479SShengchen Kan TO_REV(VMOVUPSYrr) 85db39d479SShengchen Kan #undef TO_REV 86db39d479SShengchen Kan #define TO_REV(FROM) FROM_TO(FROM, FROM##_REV, 0, 2) 87db39d479SShengchen Kan TO_REV(VMOVSDrr) 88db39d479SShengchen Kan TO_REV(VMOVSSrr) 89db39d479SShengchen Kan #undef TO_REV 90db39d479SShengchen Kan #undef FROM_TO 91db39d479SShengchen Kan } 9287671db0SShengchen Kan if (X86II::isX86_64ExtendedReg(MI.getOperand(OpIdx1).getReg()) || 9387671db0SShengchen Kan !X86II::isX86_64ExtendedReg(MI.getOperand(OpIdx2).getReg())) 94db39d479SShengchen Kan return false; 9587671db0SShengchen Kan if (NewOpc) 96db39d479SShengchen Kan MI.setOpcode(NewOpc); 9787671db0SShengchen Kan else 9887671db0SShengchen Kan std::swap(MI.getOperand(OpIdx1), MI.getOperand(OpIdx2)); 99db39d479SShengchen Kan return true; 100db39d479SShengchen Kan } 101db39d479SShengchen Kan 102db39d479SShengchen Kan // NOTE: We may write this as an InstAlias if it's only used by AsmParser. See 103db39d479SShengchen Kan // validateTargetOperandClass. 104db39d479SShengchen Kan bool X86::optimizeShiftRotateWithImmediateOne(MCInst &MI) { 105db39d479SShengchen Kan unsigned NewOpc; 106db39d479SShengchen Kan #define TO_IMM1(FROM) \ 107db39d479SShengchen Kan case X86::FROM##i: \ 108db39d479SShengchen Kan NewOpc = X86::FROM##1; \ 1095910e34aSXinWang10 break; \ 1105910e34aSXinWang10 case X86::FROM##i_EVEX: \ 1115910e34aSXinWang10 NewOpc = X86::FROM##1_EVEX; \ 1125910e34aSXinWang10 break; \ 1135910e34aSXinWang10 case X86::FROM##i_ND: \ 1145910e34aSXinWang10 NewOpc = X86::FROM##1_ND; \ 115db39d479SShengchen Kan break; 116db39d479SShengchen Kan switch (MI.getOpcode()) { 117db39d479SShengchen Kan default: 118db39d479SShengchen Kan return false; 119db39d479SShengchen Kan TO_IMM1(RCR8r) 120db39d479SShengchen Kan TO_IMM1(RCR16r) 121db39d479SShengchen Kan TO_IMM1(RCR32r) 122db39d479SShengchen Kan TO_IMM1(RCR64r) 123db39d479SShengchen Kan TO_IMM1(RCL8r) 124db39d479SShengchen Kan TO_IMM1(RCL16r) 125db39d479SShengchen Kan TO_IMM1(RCL32r) 126db39d479SShengchen Kan TO_IMM1(RCL64r) 1275910e34aSXinWang10 TO_IMM1(RCR8m) 1285910e34aSXinWang10 TO_IMM1(RCR16m) 1295910e34aSXinWang10 TO_IMM1(RCR32m) 1305910e34aSXinWang10 TO_IMM1(RCR64m) 1315910e34aSXinWang10 TO_IMM1(RCL8m) 1325910e34aSXinWang10 TO_IMM1(RCL16m) 1335910e34aSXinWang10 TO_IMM1(RCL32m) 1345910e34aSXinWang10 TO_IMM1(RCL64m) 1355910e34aSXinWang10 #undef TO_IMM1 1365910e34aSXinWang10 #define TO_IMM1(FROM) \ 1375910e34aSXinWang10 case X86::FROM##i: \ 1385910e34aSXinWang10 NewOpc = X86::FROM##1; \ 1395910e34aSXinWang10 break; \ 1405910e34aSXinWang10 case X86::FROM##i_EVEX: \ 1415910e34aSXinWang10 NewOpc = X86::FROM##1_EVEX; \ 1425910e34aSXinWang10 break; \ 1435910e34aSXinWang10 case X86::FROM##i_NF: \ 1445910e34aSXinWang10 NewOpc = X86::FROM##1_NF; \ 1455910e34aSXinWang10 break; \ 1465910e34aSXinWang10 case X86::FROM##i_ND: \ 1475910e34aSXinWang10 NewOpc = X86::FROM##1_ND; \ 1485910e34aSXinWang10 break; \ 1495910e34aSXinWang10 case X86::FROM##i_NF_ND: \ 1505910e34aSXinWang10 NewOpc = X86::FROM##1_NF_ND; \ 1515910e34aSXinWang10 break; 152db39d479SShengchen Kan TO_IMM1(ROR8r) 153db39d479SShengchen Kan TO_IMM1(ROR16r) 154db39d479SShengchen Kan TO_IMM1(ROR32r) 155db39d479SShengchen Kan TO_IMM1(ROR64r) 156db39d479SShengchen Kan TO_IMM1(ROL8r) 157db39d479SShengchen Kan TO_IMM1(ROL16r) 158db39d479SShengchen Kan TO_IMM1(ROL32r) 159db39d479SShengchen Kan TO_IMM1(ROL64r) 160db39d479SShengchen Kan TO_IMM1(SAR8r) 161db39d479SShengchen Kan TO_IMM1(SAR16r) 162db39d479SShengchen Kan TO_IMM1(SAR32r) 163db39d479SShengchen Kan TO_IMM1(SAR64r) 164db39d479SShengchen Kan TO_IMM1(SHR8r) 165db39d479SShengchen Kan TO_IMM1(SHR16r) 166db39d479SShengchen Kan TO_IMM1(SHR32r) 167db39d479SShengchen Kan TO_IMM1(SHR64r) 168db39d479SShengchen Kan TO_IMM1(SHL8r) 169db39d479SShengchen Kan TO_IMM1(SHL16r) 170db39d479SShengchen Kan TO_IMM1(SHL32r) 171db39d479SShengchen Kan TO_IMM1(SHL64r) 172db39d479SShengchen Kan TO_IMM1(ROR8m) 173db39d479SShengchen Kan TO_IMM1(ROR16m) 174db39d479SShengchen Kan TO_IMM1(ROR32m) 175db39d479SShengchen Kan TO_IMM1(ROR64m) 176db39d479SShengchen Kan TO_IMM1(ROL8m) 177db39d479SShengchen Kan TO_IMM1(ROL16m) 178db39d479SShengchen Kan TO_IMM1(ROL32m) 179db39d479SShengchen Kan TO_IMM1(ROL64m) 180db39d479SShengchen Kan TO_IMM1(SAR8m) 181db39d479SShengchen Kan TO_IMM1(SAR16m) 182db39d479SShengchen Kan TO_IMM1(SAR32m) 183db39d479SShengchen Kan TO_IMM1(SAR64m) 184db39d479SShengchen Kan TO_IMM1(SHR8m) 185db39d479SShengchen Kan TO_IMM1(SHR16m) 186db39d479SShengchen Kan TO_IMM1(SHR32m) 187db39d479SShengchen Kan TO_IMM1(SHR64m) 188db39d479SShengchen Kan TO_IMM1(SHL8m) 189db39d479SShengchen Kan TO_IMM1(SHL16m) 190db39d479SShengchen Kan TO_IMM1(SHL32m) 191db39d479SShengchen Kan TO_IMM1(SHL64m) 1922fb7506fSShengchen Kan #undef TO_IMM1 193db39d479SShengchen Kan } 194db39d479SShengchen Kan MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1); 195db39d479SShengchen Kan if (!LastOp.isImm() || LastOp.getImm() != 1) 196db39d479SShengchen Kan return false; 197db39d479SShengchen Kan MI.setOpcode(NewOpc); 198db39d479SShengchen Kan MI.erase(&LastOp); 199db39d479SShengchen Kan return true; 200db39d479SShengchen Kan } 2012fb7506fSShengchen Kan 2022fb7506fSShengchen Kan bool X86::optimizeVPCMPWithImmediateOneOrSix(MCInst &MI) { 2032fb7506fSShengchen Kan unsigned Opc1; 2042fb7506fSShengchen Kan unsigned Opc2; 2052fb7506fSShengchen Kan #define FROM_TO(FROM, TO1, TO2) \ 2062fb7506fSShengchen Kan case X86::FROM: \ 2072fb7506fSShengchen Kan Opc1 = X86::TO1; \ 2082fb7506fSShengchen Kan Opc2 = X86::TO2; \ 2092fb7506fSShengchen Kan break; 2102fb7506fSShengchen Kan switch (MI.getOpcode()) { 2112fb7506fSShengchen Kan default: 2122fb7506fSShengchen Kan return false; 2132fb7506fSShengchen Kan FROM_TO(VPCMPBZ128rmi, VPCMPEQBZ128rm, VPCMPGTBZ128rm) 2142fb7506fSShengchen Kan FROM_TO(VPCMPBZ128rmik, VPCMPEQBZ128rmk, VPCMPGTBZ128rmk) 2152fb7506fSShengchen Kan FROM_TO(VPCMPBZ128rri, VPCMPEQBZ128rr, VPCMPGTBZ128rr) 2162fb7506fSShengchen Kan FROM_TO(VPCMPBZ128rrik, VPCMPEQBZ128rrk, VPCMPGTBZ128rrk) 2172fb7506fSShengchen Kan FROM_TO(VPCMPBZ256rmi, VPCMPEQBZ256rm, VPCMPGTBZ256rm) 2182fb7506fSShengchen Kan FROM_TO(VPCMPBZ256rmik, VPCMPEQBZ256rmk, VPCMPGTBZ256rmk) 2192fb7506fSShengchen Kan FROM_TO(VPCMPBZ256rri, VPCMPEQBZ256rr, VPCMPGTBZ256rr) 2202fb7506fSShengchen Kan FROM_TO(VPCMPBZ256rrik, VPCMPEQBZ256rrk, VPCMPGTBZ256rrk) 2212fb7506fSShengchen Kan FROM_TO(VPCMPBZrmi, VPCMPEQBZrm, VPCMPGTBZrm) 2222fb7506fSShengchen Kan FROM_TO(VPCMPBZrmik, VPCMPEQBZrmk, VPCMPGTBZrmk) 2232fb7506fSShengchen Kan FROM_TO(VPCMPBZrri, VPCMPEQBZrr, VPCMPGTBZrr) 2242fb7506fSShengchen Kan FROM_TO(VPCMPBZrrik, VPCMPEQBZrrk, VPCMPGTBZrrk) 2252fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rmi, VPCMPEQDZ128rm, VPCMPGTDZ128rm) 226*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPDZ128rmbi, VPCMPEQDZ128rmb, VPCMPGTDZ128rmb) 227*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPDZ128rmbik, VPCMPEQDZ128rmbk, VPCMPGTDZ128rmbk) 2282fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rmik, VPCMPEQDZ128rmk, VPCMPGTDZ128rmk) 2292fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rri, VPCMPEQDZ128rr, VPCMPGTDZ128rr) 2302fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rrik, VPCMPEQDZ128rrk, VPCMPGTDZ128rrk) 2312fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rmi, VPCMPEQDZ256rm, VPCMPGTDZ256rm) 232*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPDZ256rmbi, VPCMPEQDZ256rmb, VPCMPGTDZ256rmb) 233*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPDZ256rmbik, VPCMPEQDZ256rmbk, VPCMPGTDZ256rmbk) 2342fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rmik, VPCMPEQDZ256rmk, VPCMPGTDZ256rmk) 2352fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rri, VPCMPEQDZ256rr, VPCMPGTDZ256rr) 2362fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rrik, VPCMPEQDZ256rrk, VPCMPGTDZ256rrk) 2372fb7506fSShengchen Kan FROM_TO(VPCMPDZrmi, VPCMPEQDZrm, VPCMPGTDZrm) 238*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPDZrmbi, VPCMPEQDZrmb, VPCMPGTDZrmb) 239*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPDZrmbik, VPCMPEQDZrmbk, VPCMPGTDZrmbk) 2402fb7506fSShengchen Kan FROM_TO(VPCMPDZrmik, VPCMPEQDZrmk, VPCMPGTDZrmk) 2412fb7506fSShengchen Kan FROM_TO(VPCMPDZrri, VPCMPEQDZrr, VPCMPGTDZrr) 2422fb7506fSShengchen Kan FROM_TO(VPCMPDZrrik, VPCMPEQDZrrk, VPCMPGTDZrrk) 2432fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rmi, VPCMPEQQZ128rm, VPCMPGTQZ128rm) 244*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPQZ128rmbi, VPCMPEQQZ128rmb, VPCMPGTQZ128rmb) 245*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPQZ128rmbik, VPCMPEQQZ128rmbk, VPCMPGTQZ128rmbk) 2462fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rmik, VPCMPEQQZ128rmk, VPCMPGTQZ128rmk) 2472fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rri, VPCMPEQQZ128rr, VPCMPGTQZ128rr) 2482fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rrik, VPCMPEQQZ128rrk, VPCMPGTQZ128rrk) 2492fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rmi, VPCMPEQQZ256rm, VPCMPGTQZ256rm) 250*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPQZ256rmbi, VPCMPEQQZ256rmb, VPCMPGTQZ256rmb) 251*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPQZ256rmbik, VPCMPEQQZ256rmbk, VPCMPGTQZ256rmbk) 2522fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rmik, VPCMPEQQZ256rmk, VPCMPGTQZ256rmk) 2532fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rri, VPCMPEQQZ256rr, VPCMPGTQZ256rr) 2542fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rrik, VPCMPEQQZ256rrk, VPCMPGTQZ256rrk) 2552fb7506fSShengchen Kan FROM_TO(VPCMPQZrmi, VPCMPEQQZrm, VPCMPGTQZrm) 256*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPQZrmbi, VPCMPEQQZrmb, VPCMPGTQZrmb) 257*d4f2b71cSSimon Pilgrim FROM_TO(VPCMPQZrmbik, VPCMPEQQZrmbk, VPCMPGTQZrmbk) 2582fb7506fSShengchen Kan FROM_TO(VPCMPQZrmik, VPCMPEQQZrmk, VPCMPGTQZrmk) 2592fb7506fSShengchen Kan FROM_TO(VPCMPQZrri, VPCMPEQQZrr, VPCMPGTQZrr) 2602fb7506fSShengchen Kan FROM_TO(VPCMPQZrrik, VPCMPEQQZrrk, VPCMPGTQZrrk) 2612fb7506fSShengchen Kan FROM_TO(VPCMPWZ128rmi, VPCMPEQWZ128rm, VPCMPGTWZ128rm) 2622fb7506fSShengchen Kan FROM_TO(VPCMPWZ128rmik, VPCMPEQWZ128rmk, VPCMPGTWZ128rmk) 2632fb7506fSShengchen Kan FROM_TO(VPCMPWZ128rri, VPCMPEQWZ128rr, VPCMPGTWZ128rr) 2642fb7506fSShengchen Kan FROM_TO(VPCMPWZ128rrik, VPCMPEQWZ128rrk, VPCMPGTWZ128rrk) 2652fb7506fSShengchen Kan FROM_TO(VPCMPWZ256rmi, VPCMPEQWZ256rm, VPCMPGTWZ256rm) 2662fb7506fSShengchen Kan FROM_TO(VPCMPWZ256rmik, VPCMPEQWZ256rmk, VPCMPGTWZ256rmk) 2672fb7506fSShengchen Kan FROM_TO(VPCMPWZ256rri, VPCMPEQWZ256rr, VPCMPGTWZ256rr) 2682fb7506fSShengchen Kan FROM_TO(VPCMPWZ256rrik, VPCMPEQWZ256rrk, VPCMPGTWZ256rrk) 2692fb7506fSShengchen Kan FROM_TO(VPCMPWZrmi, VPCMPEQWZrm, VPCMPGTWZrm) 2702fb7506fSShengchen Kan FROM_TO(VPCMPWZrmik, VPCMPEQWZrmk, VPCMPGTWZrmk) 2712fb7506fSShengchen Kan FROM_TO(VPCMPWZrri, VPCMPEQWZrr, VPCMPGTWZrr) 2722fb7506fSShengchen Kan FROM_TO(VPCMPWZrrik, VPCMPEQWZrrk, VPCMPGTWZrrk) 273d9610b4aSShengchen Kan #undef FROM_TO 2742fb7506fSShengchen Kan } 2752fb7506fSShengchen Kan MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1); 2762fb7506fSShengchen Kan int64_t Imm = LastOp.getImm(); 2772fb7506fSShengchen Kan unsigned NewOpc; 2782fb7506fSShengchen Kan if (Imm == 0) 2792fb7506fSShengchen Kan NewOpc = Opc1; 2802fb7506fSShengchen Kan else if(Imm == 6) 2812fb7506fSShengchen Kan NewOpc = Opc2; 2822fb7506fSShengchen Kan else 2832fb7506fSShengchen Kan return false; 2842fb7506fSShengchen Kan MI.setOpcode(NewOpc); 2852fb7506fSShengchen Kan MI.erase(&LastOp); 2862fb7506fSShengchen Kan return true; 2872fb7506fSShengchen Kan } 288d9610b4aSShengchen Kan 289d9610b4aSShengchen Kan bool X86::optimizeMOVSX(MCInst &MI) { 290d9610b4aSShengchen Kan unsigned NewOpc; 291d9610b4aSShengchen Kan #define FROM_TO(FROM, TO, R0, R1) \ 292d9610b4aSShengchen Kan case X86::FROM: \ 293d9610b4aSShengchen Kan if (MI.getOperand(0).getReg() != X86::R0 || \ 294d9610b4aSShengchen Kan MI.getOperand(1).getReg() != X86::R1) \ 295d9610b4aSShengchen Kan return false; \ 296d9610b4aSShengchen Kan NewOpc = X86::TO; \ 297d9610b4aSShengchen Kan break; 298d9610b4aSShengchen Kan switch (MI.getOpcode()) { 299d9610b4aSShengchen Kan default: 300d9610b4aSShengchen Kan return false; 301d9610b4aSShengchen Kan FROM_TO(MOVSX16rr8, CBW, AX, AL) // movsbw %al, %ax --> cbtw 302d9610b4aSShengchen Kan FROM_TO(MOVSX32rr16, CWDE, EAX, AX) // movswl %ax, %eax --> cwtl 303d9610b4aSShengchen Kan FROM_TO(MOVSX64rr32, CDQE, RAX, EAX) // movslq %eax, %rax --> cltq 3044a92d69aSShengchen Kan #undef FROM_TO 305d9610b4aSShengchen Kan } 306d9610b4aSShengchen Kan MI.clear(); 307d9610b4aSShengchen Kan MI.setOpcode(NewOpc); 308d9610b4aSShengchen Kan return true; 309d9610b4aSShengchen Kan } 3104a92d69aSShengchen Kan 3114a92d69aSShengchen Kan bool X86::optimizeINCDEC(MCInst &MI, bool In64BitMode) { 3124a92d69aSShengchen Kan if (In64BitMode) 3134a92d69aSShengchen Kan return false; 3144a92d69aSShengchen Kan unsigned NewOpc; 3154a92d69aSShengchen Kan // If we aren't in 64-bit mode we can use the 1-byte inc/dec instructions. 3164a92d69aSShengchen Kan #define FROM_TO(FROM, TO) \ 3174a92d69aSShengchen Kan case X86::FROM: \ 3184a92d69aSShengchen Kan NewOpc = X86::TO; \ 3194a92d69aSShengchen Kan break; 3204a92d69aSShengchen Kan switch (MI.getOpcode()) { 3214a92d69aSShengchen Kan default: 3224a92d69aSShengchen Kan return false; 3234a92d69aSShengchen Kan FROM_TO(DEC16r, DEC16r_alt) 3244a92d69aSShengchen Kan FROM_TO(DEC32r, DEC32r_alt) 3254a92d69aSShengchen Kan FROM_TO(INC16r, INC16r_alt) 3264a92d69aSShengchen Kan FROM_TO(INC32r, INC32r_alt) 3274a92d69aSShengchen Kan } 3284a92d69aSShengchen Kan MI.setOpcode(NewOpc); 3294a92d69aSShengchen Kan return true; 3304a92d69aSShengchen Kan } 33115100a2dSShengchen Kan 332a20a9738SCraig Topper static bool isARegister(MCRegister Reg) { 333b87bb4e0SShengchen Kan return Reg == X86::AL || Reg == X86::AX || Reg == X86::EAX || Reg == X86::RAX; 334b87bb4e0SShengchen Kan } 335b87bb4e0SShengchen Kan 33615100a2dSShengchen Kan /// Simplify things like MOV32rm to MOV32o32a. 33715100a2dSShengchen Kan bool X86::optimizeMOV(MCInst &MI, bool In64BitMode) { 33815100a2dSShengchen Kan // Don't make these simplifications in 64-bit mode; other assemblers don't 33915100a2dSShengchen Kan // perform them because they make the code larger. 34015100a2dSShengchen Kan if (In64BitMode) 34115100a2dSShengchen Kan return false; 34215100a2dSShengchen Kan unsigned NewOpc; 34315100a2dSShengchen Kan // We don't currently select the correct instruction form for instructions 34415100a2dSShengchen Kan // which have a short %eax, etc. form. Handle this by custom lowering, for 34515100a2dSShengchen Kan // now. 34615100a2dSShengchen Kan // 34715100a2dSShengchen Kan // Note, we are currently not handling the following instructions: 34815100a2dSShengchen Kan // MOV64ao8, MOV64o8a 34915100a2dSShengchen Kan // XCHG16ar, XCHG32ar, XCHG64ar 35015100a2dSShengchen Kan switch (MI.getOpcode()) { 35115100a2dSShengchen Kan default: 35215100a2dSShengchen Kan return false; 35315100a2dSShengchen Kan FROM_TO(MOV8mr_NOREX, MOV8o32a) 35415100a2dSShengchen Kan FROM_TO(MOV8mr, MOV8o32a) 35515100a2dSShengchen Kan FROM_TO(MOV8rm_NOREX, MOV8ao32) 35615100a2dSShengchen Kan FROM_TO(MOV8rm, MOV8ao32) 35715100a2dSShengchen Kan FROM_TO(MOV16mr, MOV16o32a) 35815100a2dSShengchen Kan FROM_TO(MOV16rm, MOV16ao32) 35915100a2dSShengchen Kan FROM_TO(MOV32mr, MOV32o32a) 36015100a2dSShengchen Kan FROM_TO(MOV32rm, MOV32ao32) 36115100a2dSShengchen Kan } 36215100a2dSShengchen Kan bool IsStore = MI.getOperand(0).isReg() && MI.getOperand(1).isReg(); 36315100a2dSShengchen Kan unsigned AddrBase = IsStore; 36415100a2dSShengchen Kan unsigned RegOp = IsStore ? 0 : 5; 36515100a2dSShengchen Kan unsigned AddrOp = AddrBase + 3; 36615100a2dSShengchen Kan // Check whether the destination register can be fixed. 367a20a9738SCraig Topper MCRegister Reg = MI.getOperand(RegOp).getReg(); 368b87bb4e0SShengchen Kan if (!isARegister(Reg)) 36915100a2dSShengchen Kan return false; 37015100a2dSShengchen Kan // Check whether this is an absolute address. 37115100a2dSShengchen Kan // FIXME: We know TLVP symbol refs aren't, but there should be a better way 37215100a2dSShengchen Kan // to do this here. 37315100a2dSShengchen Kan bool Absolute = true; 37415100a2dSShengchen Kan if (MI.getOperand(AddrOp).isExpr()) { 37515100a2dSShengchen Kan const MCExpr *MCE = MI.getOperand(AddrOp).getExpr(); 37615100a2dSShengchen Kan if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(MCE)) 37715100a2dSShengchen Kan if (SRE->getKind() == MCSymbolRefExpr::VK_TLVP) 37815100a2dSShengchen Kan Absolute = false; 37915100a2dSShengchen Kan } 380b47af5d1SCraig Topper if (Absolute && (MI.getOperand(AddrBase + X86::AddrBaseReg).getReg() || 38115100a2dSShengchen Kan MI.getOperand(AddrBase + X86::AddrScaleAmt).getImm() != 1 || 382b47af5d1SCraig Topper MI.getOperand(AddrBase + X86::AddrIndexReg).getReg())) 38315100a2dSShengchen Kan return false; 38415100a2dSShengchen Kan // If so, rewrite the instruction. 38515100a2dSShengchen Kan MCOperand Saved = MI.getOperand(AddrOp); 38615100a2dSShengchen Kan MCOperand Seg = MI.getOperand(AddrBase + X86::AddrSegmentReg); 38715100a2dSShengchen Kan MI.clear(); 38815100a2dSShengchen Kan MI.setOpcode(NewOpc); 38915100a2dSShengchen Kan MI.addOperand(Saved); 39015100a2dSShengchen Kan MI.addOperand(Seg); 39115100a2dSShengchen Kan return true; 39215100a2dSShengchen Kan } 393b87bb4e0SShengchen Kan 394b87bb4e0SShengchen Kan /// Simplify FOO $imm, %{al,ax,eax,rax} to FOO $imm, for instruction with 395b87bb4e0SShengchen Kan /// a short fixed-register form. 396c81a121fSShengchen Kan static bool optimizeToFixedRegisterForm(MCInst &MI) { 397b87bb4e0SShengchen Kan unsigned NewOpc; 398b87bb4e0SShengchen Kan switch (MI.getOpcode()) { 399b87bb4e0SShengchen Kan default: 400b87bb4e0SShengchen Kan return false; 401b87bb4e0SShengchen Kan FROM_TO(ADC8ri, ADC8i8) 402b87bb4e0SShengchen Kan FROM_TO(ADC16ri, ADC16i16) 403b87bb4e0SShengchen Kan FROM_TO(ADC32ri, ADC32i32) 404b87bb4e0SShengchen Kan FROM_TO(ADC64ri32, ADC64i32) 405b87bb4e0SShengchen Kan FROM_TO(ADD8ri, ADD8i8) 406b87bb4e0SShengchen Kan FROM_TO(ADD16ri, ADD16i16) 407b87bb4e0SShengchen Kan FROM_TO(ADD32ri, ADD32i32) 408b87bb4e0SShengchen Kan FROM_TO(ADD64ri32, ADD64i32) 409b87bb4e0SShengchen Kan FROM_TO(AND8ri, AND8i8) 410b87bb4e0SShengchen Kan FROM_TO(AND16ri, AND16i16) 411b87bb4e0SShengchen Kan FROM_TO(AND32ri, AND32i32) 412b87bb4e0SShengchen Kan FROM_TO(AND64ri32, AND64i32) 413b87bb4e0SShengchen Kan FROM_TO(CMP8ri, CMP8i8) 414b87bb4e0SShengchen Kan FROM_TO(CMP16ri, CMP16i16) 415b87bb4e0SShengchen Kan FROM_TO(CMP32ri, CMP32i32) 416b87bb4e0SShengchen Kan FROM_TO(CMP64ri32, CMP64i32) 417b87bb4e0SShengchen Kan FROM_TO(OR8ri, OR8i8) 418b87bb4e0SShengchen Kan FROM_TO(OR16ri, OR16i16) 419b87bb4e0SShengchen Kan FROM_TO(OR32ri, OR32i32) 420b87bb4e0SShengchen Kan FROM_TO(OR64ri32, OR64i32) 421b87bb4e0SShengchen Kan FROM_TO(SBB8ri, SBB8i8) 422b87bb4e0SShengchen Kan FROM_TO(SBB16ri, SBB16i16) 423b87bb4e0SShengchen Kan FROM_TO(SBB32ri, SBB32i32) 424b87bb4e0SShengchen Kan FROM_TO(SBB64ri32, SBB64i32) 425b87bb4e0SShengchen Kan FROM_TO(SUB8ri, SUB8i8) 426b87bb4e0SShengchen Kan FROM_TO(SUB16ri, SUB16i16) 427b87bb4e0SShengchen Kan FROM_TO(SUB32ri, SUB32i32) 428b87bb4e0SShengchen Kan FROM_TO(SUB64ri32, SUB64i32) 429b87bb4e0SShengchen Kan FROM_TO(TEST8ri, TEST8i8) 430b87bb4e0SShengchen Kan FROM_TO(TEST16ri, TEST16i16) 431b87bb4e0SShengchen Kan FROM_TO(TEST32ri, TEST32i32) 432b87bb4e0SShengchen Kan FROM_TO(TEST64ri32, TEST64i32) 433b87bb4e0SShengchen Kan FROM_TO(XOR8ri, XOR8i8) 434b87bb4e0SShengchen Kan FROM_TO(XOR16ri, XOR16i16) 435b87bb4e0SShengchen Kan FROM_TO(XOR32ri, XOR32i32) 436b87bb4e0SShengchen Kan FROM_TO(XOR64ri32, XOR64i32) 437b87bb4e0SShengchen Kan } 438b87bb4e0SShengchen Kan // Check whether the destination register can be fixed. 439a20a9738SCraig Topper MCRegister Reg = MI.getOperand(0).getReg(); 440b87bb4e0SShengchen Kan if (!isARegister(Reg)) 441b87bb4e0SShengchen Kan return false; 442b87bb4e0SShengchen Kan 443b87bb4e0SShengchen Kan // If so, rewrite the instruction. 444b87bb4e0SShengchen Kan MCOperand Saved = MI.getOperand(MI.getNumOperands() - 1); 445b87bb4e0SShengchen Kan MI.clear(); 446b87bb4e0SShengchen Kan MI.setOpcode(NewOpc); 447b87bb4e0SShengchen Kan MI.addOperand(Saved); 448b87bb4e0SShengchen Kan return true; 449b87bb4e0SShengchen Kan } 450c81a121fSShengchen Kan 4513f1e9468SShengchen Kan unsigned X86::getOpcodeForShortImmediateForm(unsigned Opcode) { 4523f1e9468SShengchen Kan #define ENTRY(LONG, SHORT) \ 4533f1e9468SShengchen Kan case X86::LONG: \ 4543f1e9468SShengchen Kan return X86::SHORT; 4553f1e9468SShengchen Kan switch (Opcode) { 4563f1e9468SShengchen Kan default: 4573f1e9468SShengchen Kan return Opcode; 4583f1e9468SShengchen Kan #include "X86EncodingOptimizationForImmediate.def" 4593f1e9468SShengchen Kan } 4603f1e9468SShengchen Kan } 4613f1e9468SShengchen Kan 4623f1e9468SShengchen Kan unsigned X86::getOpcodeForLongImmediateForm(unsigned Opcode) { 4633f1e9468SShengchen Kan #define ENTRY(LONG, SHORT) \ 4643f1e9468SShengchen Kan case X86::SHORT: \ 4653f1e9468SShengchen Kan return X86::LONG; 4663f1e9468SShengchen Kan switch (Opcode) { 4673f1e9468SShengchen Kan default: 4683f1e9468SShengchen Kan return Opcode; 4693f1e9468SShengchen Kan #include "X86EncodingOptimizationForImmediate.def" 4703f1e9468SShengchen Kan } 4713f1e9468SShengchen Kan } 4723f1e9468SShengchen Kan 473c81a121fSShengchen Kan static bool optimizeToShortImmediateForm(MCInst &MI) { 474c81a121fSShengchen Kan unsigned NewOpc; 4753f1e9468SShengchen Kan #define ENTRY(LONG, SHORT) \ 4763f1e9468SShengchen Kan case X86::LONG: \ 4773f1e9468SShengchen Kan NewOpc = X86::SHORT; \ 4783f1e9468SShengchen Kan break; 479c81a121fSShengchen Kan switch (MI.getOpcode()) { 480c81a121fSShengchen Kan default: 481c81a121fSShengchen Kan return false; 4823f1e9468SShengchen Kan #include "X86EncodingOptimizationForImmediate.def" 483c81a121fSShengchen Kan } 484a9183b88SShengchen Kan unsigned SkipOperands = X86::isCCMPCC(MI.getOpcode()) ? 2 : 0; 485a9183b88SShengchen Kan MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1 - SkipOperands); 486c81a121fSShengchen Kan if (LastOp.isExpr()) { 487c81a121fSShengchen Kan const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(LastOp.getExpr()); 488c81a121fSShengchen Kan if (!SRE || SRE->getKind() != MCSymbolRefExpr::VK_X86_ABS8) 489c81a121fSShengchen Kan return false; 490c81a121fSShengchen Kan } else if (LastOp.isImm()) { 491c81a121fSShengchen Kan if (!isInt<8>(LastOp.getImm())) 492c81a121fSShengchen Kan return false; 493c81a121fSShengchen Kan } 494c81a121fSShengchen Kan MI.setOpcode(NewOpc); 495c81a121fSShengchen Kan return true; 496c81a121fSShengchen Kan } 497c81a121fSShengchen Kan 498c81a121fSShengchen Kan bool X86::optimizeToFixedRegisterOrShortImmediateForm(MCInst &MI) { 499c81a121fSShengchen Kan // We may optimize twice here. 500c81a121fSShengchen Kan bool ShortImm = optimizeToShortImmediateForm(MI); 501c81a121fSShengchen Kan bool FixedReg = optimizeToFixedRegisterForm(MI); 502c81a121fSShengchen Kan return ShortImm || FixedReg; 503c81a121fSShengchen Kan } 504