xref: /llvm-project/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp (revision d4f2b71c3fd89da4dbdec0091a97a6a2c411145d)
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