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: 55025c1587SShengchen Kan case X86::VCMPSDrr: 56025c1587SShengchen Kan case X86::VCMPSSrr: { 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; \ 109db39d479SShengchen Kan break; 110db39d479SShengchen Kan switch (MI.getOpcode()) { 111db39d479SShengchen Kan default: 112db39d479SShengchen Kan return false; 113db39d479SShengchen Kan TO_IMM1(RCR8r) 114db39d479SShengchen Kan TO_IMM1(RCR16r) 115db39d479SShengchen Kan TO_IMM1(RCR32r) 116db39d479SShengchen Kan TO_IMM1(RCR64r) 117db39d479SShengchen Kan TO_IMM1(RCL8r) 118db39d479SShengchen Kan TO_IMM1(RCL16r) 119db39d479SShengchen Kan TO_IMM1(RCL32r) 120db39d479SShengchen Kan TO_IMM1(RCL64r) 121db39d479SShengchen Kan TO_IMM1(ROR8r) 122db39d479SShengchen Kan TO_IMM1(ROR16r) 123db39d479SShengchen Kan TO_IMM1(ROR32r) 124db39d479SShengchen Kan TO_IMM1(ROR64r) 125db39d479SShengchen Kan TO_IMM1(ROL8r) 126db39d479SShengchen Kan TO_IMM1(ROL16r) 127db39d479SShengchen Kan TO_IMM1(ROL32r) 128db39d479SShengchen Kan TO_IMM1(ROL64r) 129db39d479SShengchen Kan TO_IMM1(SAR8r) 130db39d479SShengchen Kan TO_IMM1(SAR16r) 131db39d479SShengchen Kan TO_IMM1(SAR32r) 132db39d479SShengchen Kan TO_IMM1(SAR64r) 133db39d479SShengchen Kan TO_IMM1(SHR8r) 134db39d479SShengchen Kan TO_IMM1(SHR16r) 135db39d479SShengchen Kan TO_IMM1(SHR32r) 136db39d479SShengchen Kan TO_IMM1(SHR64r) 137db39d479SShengchen Kan TO_IMM1(SHL8r) 138db39d479SShengchen Kan TO_IMM1(SHL16r) 139db39d479SShengchen Kan TO_IMM1(SHL32r) 140db39d479SShengchen Kan TO_IMM1(SHL64r) 141db39d479SShengchen Kan TO_IMM1(RCR8m) 142db39d479SShengchen Kan TO_IMM1(RCR16m) 143db39d479SShengchen Kan TO_IMM1(RCR32m) 144db39d479SShengchen Kan TO_IMM1(RCR64m) 145db39d479SShengchen Kan TO_IMM1(RCL8m) 146db39d479SShengchen Kan TO_IMM1(RCL16m) 147db39d479SShengchen Kan TO_IMM1(RCL32m) 148db39d479SShengchen Kan TO_IMM1(RCL64m) 149db39d479SShengchen Kan TO_IMM1(ROR8m) 150db39d479SShengchen Kan TO_IMM1(ROR16m) 151db39d479SShengchen Kan TO_IMM1(ROR32m) 152db39d479SShengchen Kan TO_IMM1(ROR64m) 153db39d479SShengchen Kan TO_IMM1(ROL8m) 154db39d479SShengchen Kan TO_IMM1(ROL16m) 155db39d479SShengchen Kan TO_IMM1(ROL32m) 156db39d479SShengchen Kan TO_IMM1(ROL64m) 157db39d479SShengchen Kan TO_IMM1(SAR8m) 158db39d479SShengchen Kan TO_IMM1(SAR16m) 159db39d479SShengchen Kan TO_IMM1(SAR32m) 160db39d479SShengchen Kan TO_IMM1(SAR64m) 161db39d479SShengchen Kan TO_IMM1(SHR8m) 162db39d479SShengchen Kan TO_IMM1(SHR16m) 163db39d479SShengchen Kan TO_IMM1(SHR32m) 164db39d479SShengchen Kan TO_IMM1(SHR64m) 165db39d479SShengchen Kan TO_IMM1(SHL8m) 166db39d479SShengchen Kan TO_IMM1(SHL16m) 167db39d479SShengchen Kan TO_IMM1(SHL32m) 168db39d479SShengchen Kan TO_IMM1(SHL64m) 1692fb7506fSShengchen Kan #undef TO_IMM1 170db39d479SShengchen Kan } 171db39d479SShengchen Kan MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1); 172db39d479SShengchen Kan if (!LastOp.isImm() || LastOp.getImm() != 1) 173db39d479SShengchen Kan return false; 174db39d479SShengchen Kan MI.setOpcode(NewOpc); 175db39d479SShengchen Kan MI.erase(&LastOp); 176db39d479SShengchen Kan return true; 177db39d479SShengchen Kan } 1782fb7506fSShengchen Kan 1792fb7506fSShengchen Kan bool X86::optimizeVPCMPWithImmediateOneOrSix(MCInst &MI) { 1802fb7506fSShengchen Kan unsigned Opc1; 1812fb7506fSShengchen Kan unsigned Opc2; 1822fb7506fSShengchen Kan #define FROM_TO(FROM, TO1, TO2) \ 1832fb7506fSShengchen Kan case X86::FROM: \ 1842fb7506fSShengchen Kan Opc1 = X86::TO1; \ 1852fb7506fSShengchen Kan Opc2 = X86::TO2; \ 1862fb7506fSShengchen Kan break; 1872fb7506fSShengchen Kan switch (MI.getOpcode()) { 1882fb7506fSShengchen Kan default: 1892fb7506fSShengchen Kan return false; 1902fb7506fSShengchen Kan FROM_TO(VPCMPBZ128rmi, VPCMPEQBZ128rm, VPCMPGTBZ128rm) 1912fb7506fSShengchen Kan FROM_TO(VPCMPBZ128rmik, VPCMPEQBZ128rmk, VPCMPGTBZ128rmk) 1922fb7506fSShengchen Kan FROM_TO(VPCMPBZ128rri, VPCMPEQBZ128rr, VPCMPGTBZ128rr) 1932fb7506fSShengchen Kan FROM_TO(VPCMPBZ128rrik, VPCMPEQBZ128rrk, VPCMPGTBZ128rrk) 1942fb7506fSShengchen Kan FROM_TO(VPCMPBZ256rmi, VPCMPEQBZ256rm, VPCMPGTBZ256rm) 1952fb7506fSShengchen Kan FROM_TO(VPCMPBZ256rmik, VPCMPEQBZ256rmk, VPCMPGTBZ256rmk) 1962fb7506fSShengchen Kan FROM_TO(VPCMPBZ256rri, VPCMPEQBZ256rr, VPCMPGTBZ256rr) 1972fb7506fSShengchen Kan FROM_TO(VPCMPBZ256rrik, VPCMPEQBZ256rrk, VPCMPGTBZ256rrk) 1982fb7506fSShengchen Kan FROM_TO(VPCMPBZrmi, VPCMPEQBZrm, VPCMPGTBZrm) 1992fb7506fSShengchen Kan FROM_TO(VPCMPBZrmik, VPCMPEQBZrmk, VPCMPGTBZrmk) 2002fb7506fSShengchen Kan FROM_TO(VPCMPBZrri, VPCMPEQBZrr, VPCMPGTBZrr) 2012fb7506fSShengchen Kan FROM_TO(VPCMPBZrrik, VPCMPEQBZrrk, VPCMPGTBZrrk) 2022fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rmi, VPCMPEQDZ128rm, VPCMPGTDZ128rm) 2032fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rmib, VPCMPEQDZ128rmb, VPCMPGTDZ128rmb) 2042fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rmibk, VPCMPEQDZ128rmbk, VPCMPGTDZ128rmbk) 2052fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rmik, VPCMPEQDZ128rmk, VPCMPGTDZ128rmk) 2062fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rri, VPCMPEQDZ128rr, VPCMPGTDZ128rr) 2072fb7506fSShengchen Kan FROM_TO(VPCMPDZ128rrik, VPCMPEQDZ128rrk, VPCMPGTDZ128rrk) 2082fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rmi, VPCMPEQDZ256rm, VPCMPGTDZ256rm) 2092fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rmib, VPCMPEQDZ256rmb, VPCMPGTDZ256rmb) 2102fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rmibk, VPCMPEQDZ256rmbk, VPCMPGTDZ256rmbk) 2112fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rmik, VPCMPEQDZ256rmk, VPCMPGTDZ256rmk) 2122fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rri, VPCMPEQDZ256rr, VPCMPGTDZ256rr) 2132fb7506fSShengchen Kan FROM_TO(VPCMPDZ256rrik, VPCMPEQDZ256rrk, VPCMPGTDZ256rrk) 2142fb7506fSShengchen Kan FROM_TO(VPCMPDZrmi, VPCMPEQDZrm, VPCMPGTDZrm) 2152fb7506fSShengchen Kan FROM_TO(VPCMPDZrmib, VPCMPEQDZrmb, VPCMPGTDZrmb) 2162fb7506fSShengchen Kan FROM_TO(VPCMPDZrmibk, VPCMPEQDZrmbk, VPCMPGTDZrmbk) 2172fb7506fSShengchen Kan FROM_TO(VPCMPDZrmik, VPCMPEQDZrmk, VPCMPGTDZrmk) 2182fb7506fSShengchen Kan FROM_TO(VPCMPDZrri, VPCMPEQDZrr, VPCMPGTDZrr) 2192fb7506fSShengchen Kan FROM_TO(VPCMPDZrrik, VPCMPEQDZrrk, VPCMPGTDZrrk) 2202fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rmi, VPCMPEQQZ128rm, VPCMPGTQZ128rm) 2212fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rmib, VPCMPEQQZ128rmb, VPCMPGTQZ128rmb) 2222fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rmibk, VPCMPEQQZ128rmbk, VPCMPGTQZ128rmbk) 2232fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rmik, VPCMPEQQZ128rmk, VPCMPGTQZ128rmk) 2242fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rri, VPCMPEQQZ128rr, VPCMPGTQZ128rr) 2252fb7506fSShengchen Kan FROM_TO(VPCMPQZ128rrik, VPCMPEQQZ128rrk, VPCMPGTQZ128rrk) 2262fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rmi, VPCMPEQQZ256rm, VPCMPGTQZ256rm) 2272fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rmib, VPCMPEQQZ256rmb, VPCMPGTQZ256rmb) 2282fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rmibk, VPCMPEQQZ256rmbk, VPCMPGTQZ256rmbk) 2292fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rmik, VPCMPEQQZ256rmk, VPCMPGTQZ256rmk) 2302fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rri, VPCMPEQQZ256rr, VPCMPGTQZ256rr) 2312fb7506fSShengchen Kan FROM_TO(VPCMPQZ256rrik, VPCMPEQQZ256rrk, VPCMPGTQZ256rrk) 2322fb7506fSShengchen Kan FROM_TO(VPCMPQZrmi, VPCMPEQQZrm, VPCMPGTQZrm) 2332fb7506fSShengchen Kan FROM_TO(VPCMPQZrmib, VPCMPEQQZrmb, VPCMPGTQZrmb) 2342fb7506fSShengchen Kan FROM_TO(VPCMPQZrmibk, VPCMPEQQZrmbk, VPCMPGTQZrmbk) 2352fb7506fSShengchen Kan FROM_TO(VPCMPQZrmik, VPCMPEQQZrmk, VPCMPGTQZrmk) 2362fb7506fSShengchen Kan FROM_TO(VPCMPQZrri, VPCMPEQQZrr, VPCMPGTQZrr) 2372fb7506fSShengchen Kan FROM_TO(VPCMPQZrrik, VPCMPEQQZrrk, VPCMPGTQZrrk) 2382fb7506fSShengchen Kan FROM_TO(VPCMPWZ128rmi, VPCMPEQWZ128rm, VPCMPGTWZ128rm) 2392fb7506fSShengchen Kan FROM_TO(VPCMPWZ128rmik, VPCMPEQWZ128rmk, VPCMPGTWZ128rmk) 2402fb7506fSShengchen Kan FROM_TO(VPCMPWZ128rri, VPCMPEQWZ128rr, VPCMPGTWZ128rr) 2412fb7506fSShengchen Kan FROM_TO(VPCMPWZ128rrik, VPCMPEQWZ128rrk, VPCMPGTWZ128rrk) 2422fb7506fSShengchen Kan FROM_TO(VPCMPWZ256rmi, VPCMPEQWZ256rm, VPCMPGTWZ256rm) 2432fb7506fSShengchen Kan FROM_TO(VPCMPWZ256rmik, VPCMPEQWZ256rmk, VPCMPGTWZ256rmk) 2442fb7506fSShengchen Kan FROM_TO(VPCMPWZ256rri, VPCMPEQWZ256rr, VPCMPGTWZ256rr) 2452fb7506fSShengchen Kan FROM_TO(VPCMPWZ256rrik, VPCMPEQWZ256rrk, VPCMPGTWZ256rrk) 2462fb7506fSShengchen Kan FROM_TO(VPCMPWZrmi, VPCMPEQWZrm, VPCMPGTWZrm) 2472fb7506fSShengchen Kan FROM_TO(VPCMPWZrmik, VPCMPEQWZrmk, VPCMPGTWZrmk) 2482fb7506fSShengchen Kan FROM_TO(VPCMPWZrri, VPCMPEQWZrr, VPCMPGTWZrr) 2492fb7506fSShengchen Kan FROM_TO(VPCMPWZrrik, VPCMPEQWZrrk, VPCMPGTWZrrk) 250d9610b4aSShengchen Kan #undef FROM_TO 2512fb7506fSShengchen Kan } 2522fb7506fSShengchen Kan MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1); 2532fb7506fSShengchen Kan int64_t Imm = LastOp.getImm(); 2542fb7506fSShengchen Kan unsigned NewOpc; 2552fb7506fSShengchen Kan if (Imm == 0) 2562fb7506fSShengchen Kan NewOpc = Opc1; 2572fb7506fSShengchen Kan else if(Imm == 6) 2582fb7506fSShengchen Kan NewOpc = Opc2; 2592fb7506fSShengchen Kan else 2602fb7506fSShengchen Kan return false; 2612fb7506fSShengchen Kan MI.setOpcode(NewOpc); 2622fb7506fSShengchen Kan MI.erase(&LastOp); 2632fb7506fSShengchen Kan return true; 2642fb7506fSShengchen Kan } 265d9610b4aSShengchen Kan 266d9610b4aSShengchen Kan bool X86::optimizeMOVSX(MCInst &MI) { 267d9610b4aSShengchen Kan unsigned NewOpc; 268d9610b4aSShengchen Kan #define FROM_TO(FROM, TO, R0, R1) \ 269d9610b4aSShengchen Kan case X86::FROM: \ 270d9610b4aSShengchen Kan if (MI.getOperand(0).getReg() != X86::R0 || \ 271d9610b4aSShengchen Kan MI.getOperand(1).getReg() != X86::R1) \ 272d9610b4aSShengchen Kan return false; \ 273d9610b4aSShengchen Kan NewOpc = X86::TO; \ 274d9610b4aSShengchen Kan break; 275d9610b4aSShengchen Kan switch (MI.getOpcode()) { 276d9610b4aSShengchen Kan default: 277d9610b4aSShengchen Kan return false; 278d9610b4aSShengchen Kan FROM_TO(MOVSX16rr8, CBW, AX, AL) // movsbw %al, %ax --> cbtw 279d9610b4aSShengchen Kan FROM_TO(MOVSX32rr16, CWDE, EAX, AX) // movswl %ax, %eax --> cwtl 280d9610b4aSShengchen Kan FROM_TO(MOVSX64rr32, CDQE, RAX, EAX) // movslq %eax, %rax --> cltq 2814a92d69aSShengchen Kan #undef FROM_TO 282d9610b4aSShengchen Kan } 283d9610b4aSShengchen Kan MI.clear(); 284d9610b4aSShengchen Kan MI.setOpcode(NewOpc); 285d9610b4aSShengchen Kan return true; 286d9610b4aSShengchen Kan } 2874a92d69aSShengchen Kan 2884a92d69aSShengchen Kan bool X86::optimizeINCDEC(MCInst &MI, bool In64BitMode) { 2894a92d69aSShengchen Kan if (In64BitMode) 2904a92d69aSShengchen Kan return false; 2914a92d69aSShengchen Kan unsigned NewOpc; 2924a92d69aSShengchen Kan // If we aren't in 64-bit mode we can use the 1-byte inc/dec instructions. 2934a92d69aSShengchen Kan #define FROM_TO(FROM, TO) \ 2944a92d69aSShengchen Kan case X86::FROM: \ 2954a92d69aSShengchen Kan NewOpc = X86::TO; \ 2964a92d69aSShengchen Kan break; 2974a92d69aSShengchen Kan switch (MI.getOpcode()) { 2984a92d69aSShengchen Kan default: 2994a92d69aSShengchen Kan return false; 3004a92d69aSShengchen Kan FROM_TO(DEC16r, DEC16r_alt) 3014a92d69aSShengchen Kan FROM_TO(DEC32r, DEC32r_alt) 3024a92d69aSShengchen Kan FROM_TO(INC16r, INC16r_alt) 3034a92d69aSShengchen Kan FROM_TO(INC32r, INC32r_alt) 3044a92d69aSShengchen Kan } 3054a92d69aSShengchen Kan MI.setOpcode(NewOpc); 3064a92d69aSShengchen Kan return true; 3074a92d69aSShengchen Kan } 30815100a2dSShengchen Kan 309b87bb4e0SShengchen Kan static bool isARegister(unsigned Reg) { 310b87bb4e0SShengchen Kan return Reg == X86::AL || Reg == X86::AX || Reg == X86::EAX || Reg == X86::RAX; 311b87bb4e0SShengchen Kan } 312b87bb4e0SShengchen Kan 31315100a2dSShengchen Kan /// Simplify things like MOV32rm to MOV32o32a. 31415100a2dSShengchen Kan bool X86::optimizeMOV(MCInst &MI, bool In64BitMode) { 31515100a2dSShengchen Kan // Don't make these simplifications in 64-bit mode; other assemblers don't 31615100a2dSShengchen Kan // perform them because they make the code larger. 31715100a2dSShengchen Kan if (In64BitMode) 31815100a2dSShengchen Kan return false; 31915100a2dSShengchen Kan unsigned NewOpc; 32015100a2dSShengchen Kan // We don't currently select the correct instruction form for instructions 32115100a2dSShengchen Kan // which have a short %eax, etc. form. Handle this by custom lowering, for 32215100a2dSShengchen Kan // now. 32315100a2dSShengchen Kan // 32415100a2dSShengchen Kan // Note, we are currently not handling the following instructions: 32515100a2dSShengchen Kan // MOV64ao8, MOV64o8a 32615100a2dSShengchen Kan // XCHG16ar, XCHG32ar, XCHG64ar 32715100a2dSShengchen Kan switch (MI.getOpcode()) { 32815100a2dSShengchen Kan default: 32915100a2dSShengchen Kan return false; 33015100a2dSShengchen Kan FROM_TO(MOV8mr_NOREX, MOV8o32a) 33115100a2dSShengchen Kan FROM_TO(MOV8mr, MOV8o32a) 33215100a2dSShengchen Kan FROM_TO(MOV8rm_NOREX, MOV8ao32) 33315100a2dSShengchen Kan FROM_TO(MOV8rm, MOV8ao32) 33415100a2dSShengchen Kan FROM_TO(MOV16mr, MOV16o32a) 33515100a2dSShengchen Kan FROM_TO(MOV16rm, MOV16ao32) 33615100a2dSShengchen Kan FROM_TO(MOV32mr, MOV32o32a) 33715100a2dSShengchen Kan FROM_TO(MOV32rm, MOV32ao32) 33815100a2dSShengchen Kan } 33915100a2dSShengchen Kan bool IsStore = MI.getOperand(0).isReg() && MI.getOperand(1).isReg(); 34015100a2dSShengchen Kan unsigned AddrBase = IsStore; 34115100a2dSShengchen Kan unsigned RegOp = IsStore ? 0 : 5; 34215100a2dSShengchen Kan unsigned AddrOp = AddrBase + 3; 34315100a2dSShengchen Kan // Check whether the destination register can be fixed. 34415100a2dSShengchen Kan unsigned Reg = MI.getOperand(RegOp).getReg(); 345b87bb4e0SShengchen Kan if (!isARegister(Reg)) 34615100a2dSShengchen Kan return false; 34715100a2dSShengchen Kan // Check whether this is an absolute address. 34815100a2dSShengchen Kan // FIXME: We know TLVP symbol refs aren't, but there should be a better way 34915100a2dSShengchen Kan // to do this here. 35015100a2dSShengchen Kan bool Absolute = true; 35115100a2dSShengchen Kan if (MI.getOperand(AddrOp).isExpr()) { 35215100a2dSShengchen Kan const MCExpr *MCE = MI.getOperand(AddrOp).getExpr(); 35315100a2dSShengchen Kan if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(MCE)) 35415100a2dSShengchen Kan if (SRE->getKind() == MCSymbolRefExpr::VK_TLVP) 35515100a2dSShengchen Kan Absolute = false; 35615100a2dSShengchen Kan } 35715100a2dSShengchen Kan if (Absolute && (MI.getOperand(AddrBase + X86::AddrBaseReg).getReg() != 0 || 35815100a2dSShengchen Kan MI.getOperand(AddrBase + X86::AddrScaleAmt).getImm() != 1 || 35915100a2dSShengchen Kan MI.getOperand(AddrBase + X86::AddrIndexReg).getReg() != 0)) 36015100a2dSShengchen Kan return false; 36115100a2dSShengchen Kan // If so, rewrite the instruction. 36215100a2dSShengchen Kan MCOperand Saved = MI.getOperand(AddrOp); 36315100a2dSShengchen Kan MCOperand Seg = MI.getOperand(AddrBase + X86::AddrSegmentReg); 36415100a2dSShengchen Kan MI.clear(); 36515100a2dSShengchen Kan MI.setOpcode(NewOpc); 36615100a2dSShengchen Kan MI.addOperand(Saved); 36715100a2dSShengchen Kan MI.addOperand(Seg); 36815100a2dSShengchen Kan return true; 36915100a2dSShengchen Kan } 370b87bb4e0SShengchen Kan 371b87bb4e0SShengchen Kan /// Simplify FOO $imm, %{al,ax,eax,rax} to FOO $imm, for instruction with 372b87bb4e0SShengchen Kan /// a short fixed-register form. 373*c81a121fSShengchen Kan static bool optimizeToFixedRegisterForm(MCInst &MI) { 374b87bb4e0SShengchen Kan unsigned NewOpc; 375b87bb4e0SShengchen Kan switch (MI.getOpcode()) { 376b87bb4e0SShengchen Kan default: 377b87bb4e0SShengchen Kan return false; 378b87bb4e0SShengchen Kan FROM_TO(ADC8ri, ADC8i8) 379b87bb4e0SShengchen Kan FROM_TO(ADC16ri, ADC16i16) 380b87bb4e0SShengchen Kan FROM_TO(ADC32ri, ADC32i32) 381b87bb4e0SShengchen Kan FROM_TO(ADC64ri32, ADC64i32) 382b87bb4e0SShengchen Kan FROM_TO(ADD8ri, ADD8i8) 383b87bb4e0SShengchen Kan FROM_TO(ADD16ri, ADD16i16) 384b87bb4e0SShengchen Kan FROM_TO(ADD32ri, ADD32i32) 385b87bb4e0SShengchen Kan FROM_TO(ADD64ri32, ADD64i32) 386b87bb4e0SShengchen Kan FROM_TO(AND8ri, AND8i8) 387b87bb4e0SShengchen Kan FROM_TO(AND16ri, AND16i16) 388b87bb4e0SShengchen Kan FROM_TO(AND32ri, AND32i32) 389b87bb4e0SShengchen Kan FROM_TO(AND64ri32, AND64i32) 390b87bb4e0SShengchen Kan FROM_TO(CMP8ri, CMP8i8) 391b87bb4e0SShengchen Kan FROM_TO(CMP16ri, CMP16i16) 392b87bb4e0SShengchen Kan FROM_TO(CMP32ri, CMP32i32) 393b87bb4e0SShengchen Kan FROM_TO(CMP64ri32, CMP64i32) 394b87bb4e0SShengchen Kan FROM_TO(OR8ri, OR8i8) 395b87bb4e0SShengchen Kan FROM_TO(OR16ri, OR16i16) 396b87bb4e0SShengchen Kan FROM_TO(OR32ri, OR32i32) 397b87bb4e0SShengchen Kan FROM_TO(OR64ri32, OR64i32) 398b87bb4e0SShengchen Kan FROM_TO(SBB8ri, SBB8i8) 399b87bb4e0SShengchen Kan FROM_TO(SBB16ri, SBB16i16) 400b87bb4e0SShengchen Kan FROM_TO(SBB32ri, SBB32i32) 401b87bb4e0SShengchen Kan FROM_TO(SBB64ri32, SBB64i32) 402b87bb4e0SShengchen Kan FROM_TO(SUB8ri, SUB8i8) 403b87bb4e0SShengchen Kan FROM_TO(SUB16ri, SUB16i16) 404b87bb4e0SShengchen Kan FROM_TO(SUB32ri, SUB32i32) 405b87bb4e0SShengchen Kan FROM_TO(SUB64ri32, SUB64i32) 406b87bb4e0SShengchen Kan FROM_TO(TEST8ri, TEST8i8) 407b87bb4e0SShengchen Kan FROM_TO(TEST16ri, TEST16i16) 408b87bb4e0SShengchen Kan FROM_TO(TEST32ri, TEST32i32) 409b87bb4e0SShengchen Kan FROM_TO(TEST64ri32, TEST64i32) 410b87bb4e0SShengchen Kan FROM_TO(XOR8ri, XOR8i8) 411b87bb4e0SShengchen Kan FROM_TO(XOR16ri, XOR16i16) 412b87bb4e0SShengchen Kan FROM_TO(XOR32ri, XOR32i32) 413b87bb4e0SShengchen Kan FROM_TO(XOR64ri32, XOR64i32) 414b87bb4e0SShengchen Kan } 415b87bb4e0SShengchen Kan // Check whether the destination register can be fixed. 416b87bb4e0SShengchen Kan unsigned Reg = MI.getOperand(0).getReg(); 417b87bb4e0SShengchen Kan if (!isARegister(Reg)) 418b87bb4e0SShengchen Kan return false; 419b87bb4e0SShengchen Kan 420b87bb4e0SShengchen Kan // If so, rewrite the instruction. 421b87bb4e0SShengchen Kan MCOperand Saved = MI.getOperand(MI.getNumOperands() - 1); 422b87bb4e0SShengchen Kan MI.clear(); 423b87bb4e0SShengchen Kan MI.setOpcode(NewOpc); 424b87bb4e0SShengchen Kan MI.addOperand(Saved); 425b87bb4e0SShengchen Kan return true; 426b87bb4e0SShengchen Kan } 427*c81a121fSShengchen Kan 428*c81a121fSShengchen Kan static bool optimizeToShortImmediateForm(MCInst &MI) { 429*c81a121fSShengchen Kan unsigned NewOpc; 430*c81a121fSShengchen Kan switch (MI.getOpcode()) { 431*c81a121fSShengchen Kan default: 432*c81a121fSShengchen Kan return false; 433*c81a121fSShengchen Kan FROM_TO(ADC16mi, ADC16mi8) 434*c81a121fSShengchen Kan FROM_TO(ADC16ri, ADC16ri8) 435*c81a121fSShengchen Kan FROM_TO(ADC32mi, ADC32mi8) 436*c81a121fSShengchen Kan FROM_TO(ADC32ri, ADC32ri8) 437*c81a121fSShengchen Kan FROM_TO(ADC64mi32, ADC64mi8) 438*c81a121fSShengchen Kan FROM_TO(ADC64ri32, ADC64ri8) 439*c81a121fSShengchen Kan FROM_TO(SBB16mi, SBB16mi8) 440*c81a121fSShengchen Kan FROM_TO(SBB16ri, SBB16ri8) 441*c81a121fSShengchen Kan FROM_TO(SBB32mi, SBB32mi8) 442*c81a121fSShengchen Kan FROM_TO(SBB32ri, SBB32ri8) 443*c81a121fSShengchen Kan FROM_TO(SBB64mi32, SBB64mi8) 444*c81a121fSShengchen Kan FROM_TO(SBB64ri32, SBB64ri8) 445*c81a121fSShengchen Kan FROM_TO(ADD16mi, ADD16mi8) 446*c81a121fSShengchen Kan FROM_TO(ADD16ri, ADD16ri8) 447*c81a121fSShengchen Kan FROM_TO(ADD32mi, ADD32mi8) 448*c81a121fSShengchen Kan FROM_TO(ADD32ri, ADD32ri8) 449*c81a121fSShengchen Kan FROM_TO(ADD64mi32, ADD64mi8) 450*c81a121fSShengchen Kan FROM_TO(ADD64ri32, ADD64ri8) 451*c81a121fSShengchen Kan FROM_TO(AND16mi, AND16mi8) 452*c81a121fSShengchen Kan FROM_TO(AND16ri, AND16ri8) 453*c81a121fSShengchen Kan FROM_TO(AND32mi, AND32mi8) 454*c81a121fSShengchen Kan FROM_TO(AND32ri, AND32ri8) 455*c81a121fSShengchen Kan FROM_TO(AND64mi32, AND64mi8) 456*c81a121fSShengchen Kan FROM_TO(AND64ri32, AND64ri8) 457*c81a121fSShengchen Kan FROM_TO(OR16mi, OR16mi8) 458*c81a121fSShengchen Kan FROM_TO(OR16ri, OR16ri8) 459*c81a121fSShengchen Kan FROM_TO(OR32mi, OR32mi8) 460*c81a121fSShengchen Kan FROM_TO(OR32ri, OR32ri8) 461*c81a121fSShengchen Kan FROM_TO(OR64mi32, OR64mi8) 462*c81a121fSShengchen Kan FROM_TO(OR64ri32, OR64ri8) 463*c81a121fSShengchen Kan FROM_TO(SUB16mi, SUB16mi8) 464*c81a121fSShengchen Kan FROM_TO(SUB16ri, SUB16ri8) 465*c81a121fSShengchen Kan FROM_TO(SUB32mi, SUB32mi8) 466*c81a121fSShengchen Kan FROM_TO(SUB32ri, SUB32ri8) 467*c81a121fSShengchen Kan FROM_TO(SUB64mi32, SUB64mi8) 468*c81a121fSShengchen Kan FROM_TO(SUB64ri32, SUB64ri8) 469*c81a121fSShengchen Kan FROM_TO(XOR16mi, XOR16mi8) 470*c81a121fSShengchen Kan FROM_TO(XOR16ri, XOR16ri8) 471*c81a121fSShengchen Kan FROM_TO(XOR32mi, XOR32mi8) 472*c81a121fSShengchen Kan FROM_TO(XOR32ri, XOR32ri8) 473*c81a121fSShengchen Kan FROM_TO(XOR64mi32, XOR64mi8) 474*c81a121fSShengchen Kan FROM_TO(XOR64ri32, XOR64ri8) 475*c81a121fSShengchen Kan FROM_TO(CMP16mi, CMP16mi8) 476*c81a121fSShengchen Kan FROM_TO(CMP16ri, CMP16ri8) 477*c81a121fSShengchen Kan FROM_TO(CMP32mi, CMP32mi8) 478*c81a121fSShengchen Kan FROM_TO(CMP32ri, CMP32ri8) 479*c81a121fSShengchen Kan FROM_TO(CMP64mi32, CMP64mi8) 480*c81a121fSShengchen Kan FROM_TO(CMP64ri32, CMP64ri8) 481*c81a121fSShengchen Kan } 482*c81a121fSShengchen Kan MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1); 483*c81a121fSShengchen Kan if (LastOp.isExpr()) { 484*c81a121fSShengchen Kan const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(LastOp.getExpr()); 485*c81a121fSShengchen Kan if (!SRE || SRE->getKind() != MCSymbolRefExpr::VK_X86_ABS8) 486*c81a121fSShengchen Kan return false; 487*c81a121fSShengchen Kan } else if (LastOp.isImm()) { 488*c81a121fSShengchen Kan if (!isInt<8>(LastOp.getImm())) 489*c81a121fSShengchen Kan return false; 490*c81a121fSShengchen Kan } 491*c81a121fSShengchen Kan MI.setOpcode(NewOpc); 492*c81a121fSShengchen Kan return true; 493*c81a121fSShengchen Kan } 494*c81a121fSShengchen Kan 495*c81a121fSShengchen Kan bool X86::optimizeToFixedRegisterOrShortImmediateForm(MCInst &MI) { 496*c81a121fSShengchen Kan // We may optimize twice here. 497*c81a121fSShengchen Kan bool ShortImm = optimizeToShortImmediateForm(MI); 498*c81a121fSShengchen Kan bool FixedReg = optimizeToFixedRegisterForm(MI); 499*c81a121fSShengchen Kan return ShortImm || FixedReg; 500*c81a121fSShengchen Kan } 501