xref: /llvm-project/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp (revision 15100a2db84d976c2e1c97a8bf50cf26ec4968b3)
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"
15*15100a2dSShengchen Kan #include "llvm/MC/MCExpr.h"
16db39d479SShengchen Kan #include "llvm/MC/MCInst.h"
17db39d479SShengchen Kan #include "llvm/MC/MCInstrDesc.h"
18*15100a2dSShengchen Kan #include "llvm/Support/Casting.h"
19db39d479SShengchen Kan 
20db39d479SShengchen Kan using namespace llvm;
21db39d479SShengchen Kan 
22db39d479SShengchen Kan static bool shouldExchange(const MCInst &MI, unsigned OpIdx1, unsigned OpIdx2) {
23db39d479SShengchen Kan   return !X86II::isX86_64ExtendedReg(MI.getOperand(OpIdx1).getReg()) &&
24db39d479SShengchen Kan          X86II::isX86_64ExtendedReg(MI.getOperand(OpIdx2).getReg());
25db39d479SShengchen Kan }
26db39d479SShengchen Kan 
27db39d479SShengchen Kan bool X86::optimizeInstFromVEX3ToVEX2(MCInst &MI, const MCInstrDesc &Desc) {
28db39d479SShengchen Kan   unsigned OpIdx1, OpIdx2;
29db39d479SShengchen Kan   unsigned NewOpc;
30db39d479SShengchen Kan   unsigned Opcode = MI.getOpcode();
31db39d479SShengchen Kan #define FROM_TO(FROM, TO, IDX1, IDX2)                                          \
32db39d479SShengchen Kan   case X86::FROM:                                                              \
33db39d479SShengchen Kan     NewOpc = X86::TO;                                                          \
34db39d479SShengchen Kan     OpIdx1 = IDX1;                                                             \
35db39d479SShengchen Kan     OpIdx2 = IDX2;                                                             \
36db39d479SShengchen Kan     break;
37db39d479SShengchen Kan #define TO_REV(FROM) FROM_TO(FROM, FROM##_REV, 0, 1)
38db39d479SShengchen Kan   switch (MI.getOpcode()) {
39db39d479SShengchen Kan   default: {
40db39d479SShengchen Kan     // If the instruction is a commutable arithmetic instruction we might be
41db39d479SShengchen Kan     // able to commute the operands to get a 2 byte VEX prefix.
42db39d479SShengchen Kan     uint64_t TSFlags = Desc.TSFlags;
43db39d479SShengchen Kan     if (!Desc.isCommutable() || (TSFlags & X86II::EncodingMask) != X86II::VEX ||
44db39d479SShengchen Kan         (TSFlags & X86II::OpMapMask) != X86II::TB ||
45db39d479SShengchen Kan         (TSFlags & X86II::FormMask) != X86II::MRMSrcReg ||
46db39d479SShengchen Kan         (TSFlags & X86II::REX_W) || !(TSFlags & X86II::VEX_4V) ||
47db39d479SShengchen Kan         MI.getNumOperands() != 3)
48db39d479SShengchen Kan       return false;
49db39d479SShengchen Kan     // These two are not truly commutable.
50db39d479SShengchen Kan     if (Opcode == X86::VMOVHLPSrr || Opcode == X86::VUNPCKHPDrr)
51db39d479SShengchen Kan       return false;
52db39d479SShengchen Kan     OpIdx1 = 1;
53db39d479SShengchen Kan     OpIdx2 = 2;
54db39d479SShengchen Kan     if (!shouldExchange(MI, OpIdx1, OpIdx2))
55db39d479SShengchen Kan       return false;
56db39d479SShengchen Kan     std::swap(MI.getOperand(OpIdx1), MI.getOperand(OpIdx2));
57db39d479SShengchen Kan     return true;
58db39d479SShengchen Kan   }
59db39d479SShengchen Kan     // Commute operands to get a smaller encoding by using VEX.R instead of
60db39d479SShengchen Kan     // VEX.B if one of the registers is extended, but other isn't.
61db39d479SShengchen Kan     FROM_TO(VMOVZPQILo2PQIrr, VMOVPQI2QIrr, 0, 1)
62db39d479SShengchen Kan     TO_REV(VMOVAPDrr)
63db39d479SShengchen Kan     TO_REV(VMOVAPDYrr)
64db39d479SShengchen Kan     TO_REV(VMOVAPSrr)
65db39d479SShengchen Kan     TO_REV(VMOVAPSYrr)
66db39d479SShengchen Kan     TO_REV(VMOVDQArr)
67db39d479SShengchen Kan     TO_REV(VMOVDQAYrr)
68db39d479SShengchen Kan     TO_REV(VMOVDQUrr)
69db39d479SShengchen Kan     TO_REV(VMOVDQUYrr)
70db39d479SShengchen Kan     TO_REV(VMOVUPDrr)
71db39d479SShengchen Kan     TO_REV(VMOVUPDYrr)
72db39d479SShengchen Kan     TO_REV(VMOVUPSrr)
73db39d479SShengchen Kan     TO_REV(VMOVUPSYrr)
74db39d479SShengchen Kan #undef TO_REV
75db39d479SShengchen Kan #define TO_REV(FROM) FROM_TO(FROM, FROM##_REV, 0, 2)
76db39d479SShengchen Kan     TO_REV(VMOVSDrr)
77db39d479SShengchen Kan     TO_REV(VMOVSSrr)
78db39d479SShengchen Kan #undef TO_REV
79db39d479SShengchen Kan #undef FROM_TO
80db39d479SShengchen Kan   }
81db39d479SShengchen Kan   if (!shouldExchange(MI, OpIdx1, OpIdx2))
82db39d479SShengchen Kan     return false;
83db39d479SShengchen Kan   MI.setOpcode(NewOpc);
84db39d479SShengchen Kan   return true;
85db39d479SShengchen Kan }
86db39d479SShengchen Kan 
87db39d479SShengchen Kan // NOTE: We may write this as an InstAlias if it's only used by AsmParser. See
88db39d479SShengchen Kan // validateTargetOperandClass.
89db39d479SShengchen Kan bool X86::optimizeShiftRotateWithImmediateOne(MCInst &MI) {
90db39d479SShengchen Kan   unsigned NewOpc;
91db39d479SShengchen Kan #define TO_IMM1(FROM)                                                          \
92db39d479SShengchen Kan   case X86::FROM##i:                                                           \
93db39d479SShengchen Kan     NewOpc = X86::FROM##1;                                                     \
94db39d479SShengchen Kan     break;
95db39d479SShengchen Kan   switch (MI.getOpcode()) {
96db39d479SShengchen Kan   default:
97db39d479SShengchen Kan     return false;
98db39d479SShengchen Kan     TO_IMM1(RCR8r)
99db39d479SShengchen Kan     TO_IMM1(RCR16r)
100db39d479SShengchen Kan     TO_IMM1(RCR32r)
101db39d479SShengchen Kan     TO_IMM1(RCR64r)
102db39d479SShengchen Kan     TO_IMM1(RCL8r)
103db39d479SShengchen Kan     TO_IMM1(RCL16r)
104db39d479SShengchen Kan     TO_IMM1(RCL32r)
105db39d479SShengchen Kan     TO_IMM1(RCL64r)
106db39d479SShengchen Kan     TO_IMM1(ROR8r)
107db39d479SShengchen Kan     TO_IMM1(ROR16r)
108db39d479SShengchen Kan     TO_IMM1(ROR32r)
109db39d479SShengchen Kan     TO_IMM1(ROR64r)
110db39d479SShengchen Kan     TO_IMM1(ROL8r)
111db39d479SShengchen Kan     TO_IMM1(ROL16r)
112db39d479SShengchen Kan     TO_IMM1(ROL32r)
113db39d479SShengchen Kan     TO_IMM1(ROL64r)
114db39d479SShengchen Kan     TO_IMM1(SAR8r)
115db39d479SShengchen Kan     TO_IMM1(SAR16r)
116db39d479SShengchen Kan     TO_IMM1(SAR32r)
117db39d479SShengchen Kan     TO_IMM1(SAR64r)
118db39d479SShengchen Kan     TO_IMM1(SHR8r)
119db39d479SShengchen Kan     TO_IMM1(SHR16r)
120db39d479SShengchen Kan     TO_IMM1(SHR32r)
121db39d479SShengchen Kan     TO_IMM1(SHR64r)
122db39d479SShengchen Kan     TO_IMM1(SHL8r)
123db39d479SShengchen Kan     TO_IMM1(SHL16r)
124db39d479SShengchen Kan     TO_IMM1(SHL32r)
125db39d479SShengchen Kan     TO_IMM1(SHL64r)
126db39d479SShengchen Kan     TO_IMM1(RCR8m)
127db39d479SShengchen Kan     TO_IMM1(RCR16m)
128db39d479SShengchen Kan     TO_IMM1(RCR32m)
129db39d479SShengchen Kan     TO_IMM1(RCR64m)
130db39d479SShengchen Kan     TO_IMM1(RCL8m)
131db39d479SShengchen Kan     TO_IMM1(RCL16m)
132db39d479SShengchen Kan     TO_IMM1(RCL32m)
133db39d479SShengchen Kan     TO_IMM1(RCL64m)
134db39d479SShengchen Kan     TO_IMM1(ROR8m)
135db39d479SShengchen Kan     TO_IMM1(ROR16m)
136db39d479SShengchen Kan     TO_IMM1(ROR32m)
137db39d479SShengchen Kan     TO_IMM1(ROR64m)
138db39d479SShengchen Kan     TO_IMM1(ROL8m)
139db39d479SShengchen Kan     TO_IMM1(ROL16m)
140db39d479SShengchen Kan     TO_IMM1(ROL32m)
141db39d479SShengchen Kan     TO_IMM1(ROL64m)
142db39d479SShengchen Kan     TO_IMM1(SAR8m)
143db39d479SShengchen Kan     TO_IMM1(SAR16m)
144db39d479SShengchen Kan     TO_IMM1(SAR32m)
145db39d479SShengchen Kan     TO_IMM1(SAR64m)
146db39d479SShengchen Kan     TO_IMM1(SHR8m)
147db39d479SShengchen Kan     TO_IMM1(SHR16m)
148db39d479SShengchen Kan     TO_IMM1(SHR32m)
149db39d479SShengchen Kan     TO_IMM1(SHR64m)
150db39d479SShengchen Kan     TO_IMM1(SHL8m)
151db39d479SShengchen Kan     TO_IMM1(SHL16m)
152db39d479SShengchen Kan     TO_IMM1(SHL32m)
153db39d479SShengchen Kan     TO_IMM1(SHL64m)
1542fb7506fSShengchen Kan #undef TO_IMM1
155db39d479SShengchen Kan   }
156db39d479SShengchen Kan   MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1);
157db39d479SShengchen Kan   if (!LastOp.isImm() || LastOp.getImm() != 1)
158db39d479SShengchen Kan     return false;
159db39d479SShengchen Kan   MI.setOpcode(NewOpc);
160db39d479SShengchen Kan   MI.erase(&LastOp);
161db39d479SShengchen Kan   return true;
162db39d479SShengchen Kan }
1632fb7506fSShengchen Kan 
1642fb7506fSShengchen Kan bool X86::optimizeVPCMPWithImmediateOneOrSix(MCInst &MI) {
1652fb7506fSShengchen Kan   unsigned Opc1;
1662fb7506fSShengchen Kan   unsigned Opc2;
1672fb7506fSShengchen Kan #define FROM_TO(FROM, TO1, TO2)                                                \
1682fb7506fSShengchen Kan   case X86::FROM:                                                              \
1692fb7506fSShengchen Kan     Opc1 = X86::TO1;                                                           \
1702fb7506fSShengchen Kan     Opc2 = X86::TO2;                                                           \
1712fb7506fSShengchen Kan     break;
1722fb7506fSShengchen Kan   switch (MI.getOpcode()) {
1732fb7506fSShengchen Kan   default:
1742fb7506fSShengchen Kan     return false;
1752fb7506fSShengchen Kan     FROM_TO(VPCMPBZ128rmi, VPCMPEQBZ128rm, VPCMPGTBZ128rm)
1762fb7506fSShengchen Kan     FROM_TO(VPCMPBZ128rmik, VPCMPEQBZ128rmk, VPCMPGTBZ128rmk)
1772fb7506fSShengchen Kan     FROM_TO(VPCMPBZ128rri, VPCMPEQBZ128rr, VPCMPGTBZ128rr)
1782fb7506fSShengchen Kan     FROM_TO(VPCMPBZ128rrik, VPCMPEQBZ128rrk, VPCMPGTBZ128rrk)
1792fb7506fSShengchen Kan     FROM_TO(VPCMPBZ256rmi, VPCMPEQBZ256rm, VPCMPGTBZ256rm)
1802fb7506fSShengchen Kan     FROM_TO(VPCMPBZ256rmik, VPCMPEQBZ256rmk, VPCMPGTBZ256rmk)
1812fb7506fSShengchen Kan     FROM_TO(VPCMPBZ256rri, VPCMPEQBZ256rr, VPCMPGTBZ256rr)
1822fb7506fSShengchen Kan     FROM_TO(VPCMPBZ256rrik, VPCMPEQBZ256rrk, VPCMPGTBZ256rrk)
1832fb7506fSShengchen Kan     FROM_TO(VPCMPBZrmi, VPCMPEQBZrm, VPCMPGTBZrm)
1842fb7506fSShengchen Kan     FROM_TO(VPCMPBZrmik, VPCMPEQBZrmk, VPCMPGTBZrmk)
1852fb7506fSShengchen Kan     FROM_TO(VPCMPBZrri, VPCMPEQBZrr, VPCMPGTBZrr)
1862fb7506fSShengchen Kan     FROM_TO(VPCMPBZrrik, VPCMPEQBZrrk, VPCMPGTBZrrk)
1872fb7506fSShengchen Kan     FROM_TO(VPCMPDZ128rmi, VPCMPEQDZ128rm, VPCMPGTDZ128rm)
1882fb7506fSShengchen Kan     FROM_TO(VPCMPDZ128rmib, VPCMPEQDZ128rmb, VPCMPGTDZ128rmb)
1892fb7506fSShengchen Kan     FROM_TO(VPCMPDZ128rmibk, VPCMPEQDZ128rmbk, VPCMPGTDZ128rmbk)
1902fb7506fSShengchen Kan     FROM_TO(VPCMPDZ128rmik, VPCMPEQDZ128rmk, VPCMPGTDZ128rmk)
1912fb7506fSShengchen Kan     FROM_TO(VPCMPDZ128rri, VPCMPEQDZ128rr, VPCMPGTDZ128rr)
1922fb7506fSShengchen Kan     FROM_TO(VPCMPDZ128rrik, VPCMPEQDZ128rrk, VPCMPGTDZ128rrk)
1932fb7506fSShengchen Kan     FROM_TO(VPCMPDZ256rmi, VPCMPEQDZ256rm, VPCMPGTDZ256rm)
1942fb7506fSShengchen Kan     FROM_TO(VPCMPDZ256rmib, VPCMPEQDZ256rmb, VPCMPGTDZ256rmb)
1952fb7506fSShengchen Kan     FROM_TO(VPCMPDZ256rmibk, VPCMPEQDZ256rmbk, VPCMPGTDZ256rmbk)
1962fb7506fSShengchen Kan     FROM_TO(VPCMPDZ256rmik, VPCMPEQDZ256rmk, VPCMPGTDZ256rmk)
1972fb7506fSShengchen Kan     FROM_TO(VPCMPDZ256rri, VPCMPEQDZ256rr, VPCMPGTDZ256rr)
1982fb7506fSShengchen Kan     FROM_TO(VPCMPDZ256rrik, VPCMPEQDZ256rrk, VPCMPGTDZ256rrk)
1992fb7506fSShengchen Kan     FROM_TO(VPCMPDZrmi, VPCMPEQDZrm, VPCMPGTDZrm)
2002fb7506fSShengchen Kan     FROM_TO(VPCMPDZrmib, VPCMPEQDZrmb, VPCMPGTDZrmb)
2012fb7506fSShengchen Kan     FROM_TO(VPCMPDZrmibk, VPCMPEQDZrmbk, VPCMPGTDZrmbk)
2022fb7506fSShengchen Kan     FROM_TO(VPCMPDZrmik, VPCMPEQDZrmk, VPCMPGTDZrmk)
2032fb7506fSShengchen Kan     FROM_TO(VPCMPDZrri, VPCMPEQDZrr, VPCMPGTDZrr)
2042fb7506fSShengchen Kan     FROM_TO(VPCMPDZrrik, VPCMPEQDZrrk, VPCMPGTDZrrk)
2052fb7506fSShengchen Kan     FROM_TO(VPCMPQZ128rmi, VPCMPEQQZ128rm, VPCMPGTQZ128rm)
2062fb7506fSShengchen Kan     FROM_TO(VPCMPQZ128rmib, VPCMPEQQZ128rmb, VPCMPGTQZ128rmb)
2072fb7506fSShengchen Kan     FROM_TO(VPCMPQZ128rmibk, VPCMPEQQZ128rmbk, VPCMPGTQZ128rmbk)
2082fb7506fSShengchen Kan     FROM_TO(VPCMPQZ128rmik, VPCMPEQQZ128rmk, VPCMPGTQZ128rmk)
2092fb7506fSShengchen Kan     FROM_TO(VPCMPQZ128rri, VPCMPEQQZ128rr, VPCMPGTQZ128rr)
2102fb7506fSShengchen Kan     FROM_TO(VPCMPQZ128rrik, VPCMPEQQZ128rrk, VPCMPGTQZ128rrk)
2112fb7506fSShengchen Kan     FROM_TO(VPCMPQZ256rmi, VPCMPEQQZ256rm, VPCMPGTQZ256rm)
2122fb7506fSShengchen Kan     FROM_TO(VPCMPQZ256rmib, VPCMPEQQZ256rmb, VPCMPGTQZ256rmb)
2132fb7506fSShengchen Kan     FROM_TO(VPCMPQZ256rmibk, VPCMPEQQZ256rmbk, VPCMPGTQZ256rmbk)
2142fb7506fSShengchen Kan     FROM_TO(VPCMPQZ256rmik, VPCMPEQQZ256rmk, VPCMPGTQZ256rmk)
2152fb7506fSShengchen Kan     FROM_TO(VPCMPQZ256rri, VPCMPEQQZ256rr, VPCMPGTQZ256rr)
2162fb7506fSShengchen Kan     FROM_TO(VPCMPQZ256rrik, VPCMPEQQZ256rrk, VPCMPGTQZ256rrk)
2172fb7506fSShengchen Kan     FROM_TO(VPCMPQZrmi, VPCMPEQQZrm, VPCMPGTQZrm)
2182fb7506fSShengchen Kan     FROM_TO(VPCMPQZrmib, VPCMPEQQZrmb, VPCMPGTQZrmb)
2192fb7506fSShengchen Kan     FROM_TO(VPCMPQZrmibk, VPCMPEQQZrmbk, VPCMPGTQZrmbk)
2202fb7506fSShengchen Kan     FROM_TO(VPCMPQZrmik, VPCMPEQQZrmk, VPCMPGTQZrmk)
2212fb7506fSShengchen Kan     FROM_TO(VPCMPQZrri, VPCMPEQQZrr, VPCMPGTQZrr)
2222fb7506fSShengchen Kan     FROM_TO(VPCMPQZrrik, VPCMPEQQZrrk, VPCMPGTQZrrk)
2232fb7506fSShengchen Kan     FROM_TO(VPCMPWZ128rmi, VPCMPEQWZ128rm, VPCMPGTWZ128rm)
2242fb7506fSShengchen Kan     FROM_TO(VPCMPWZ128rmik, VPCMPEQWZ128rmk, VPCMPGTWZ128rmk)
2252fb7506fSShengchen Kan     FROM_TO(VPCMPWZ128rri, VPCMPEQWZ128rr, VPCMPGTWZ128rr)
2262fb7506fSShengchen Kan     FROM_TO(VPCMPWZ128rrik, VPCMPEQWZ128rrk, VPCMPGTWZ128rrk)
2272fb7506fSShengchen Kan     FROM_TO(VPCMPWZ256rmi, VPCMPEQWZ256rm, VPCMPGTWZ256rm)
2282fb7506fSShengchen Kan     FROM_TO(VPCMPWZ256rmik, VPCMPEQWZ256rmk, VPCMPGTWZ256rmk)
2292fb7506fSShengchen Kan     FROM_TO(VPCMPWZ256rri, VPCMPEQWZ256rr, VPCMPGTWZ256rr)
2302fb7506fSShengchen Kan     FROM_TO(VPCMPWZ256rrik, VPCMPEQWZ256rrk, VPCMPGTWZ256rrk)
2312fb7506fSShengchen Kan     FROM_TO(VPCMPWZrmi, VPCMPEQWZrm, VPCMPGTWZrm)
2322fb7506fSShengchen Kan     FROM_TO(VPCMPWZrmik, VPCMPEQWZrmk, VPCMPGTWZrmk)
2332fb7506fSShengchen Kan     FROM_TO(VPCMPWZrri, VPCMPEQWZrr, VPCMPGTWZrr)
2342fb7506fSShengchen Kan     FROM_TO(VPCMPWZrrik, VPCMPEQWZrrk, VPCMPGTWZrrk)
235d9610b4aSShengchen Kan #undef FROM_TO
2362fb7506fSShengchen Kan   }
2372fb7506fSShengchen Kan   MCOperand &LastOp = MI.getOperand(MI.getNumOperands() - 1);
2382fb7506fSShengchen Kan   int64_t Imm = LastOp.getImm();
2392fb7506fSShengchen Kan   unsigned NewOpc;
2402fb7506fSShengchen Kan   if (Imm == 0)
2412fb7506fSShengchen Kan     NewOpc = Opc1;
2422fb7506fSShengchen Kan   else if(Imm == 6)
2432fb7506fSShengchen Kan     NewOpc = Opc2;
2442fb7506fSShengchen Kan   else
2452fb7506fSShengchen Kan     return false;
2462fb7506fSShengchen Kan   MI.setOpcode(NewOpc);
2472fb7506fSShengchen Kan   MI.erase(&LastOp);
2482fb7506fSShengchen Kan   return true;
2492fb7506fSShengchen Kan }
250d9610b4aSShengchen Kan 
251d9610b4aSShengchen Kan bool X86::optimizeMOVSX(MCInst &MI) {
252d9610b4aSShengchen Kan   unsigned NewOpc;
253d9610b4aSShengchen Kan #define FROM_TO(FROM, TO, R0, R1)                                              \
254d9610b4aSShengchen Kan   case X86::FROM:                                                              \
255d9610b4aSShengchen Kan     if (MI.getOperand(0).getReg() != X86::R0 ||                                \
256d9610b4aSShengchen Kan         MI.getOperand(1).getReg() != X86::R1)                                  \
257d9610b4aSShengchen Kan       return false;                                                            \
258d9610b4aSShengchen Kan     NewOpc = X86::TO;                                                          \
259d9610b4aSShengchen Kan     break;
260d9610b4aSShengchen Kan   switch (MI.getOpcode()) {
261d9610b4aSShengchen Kan   default:
262d9610b4aSShengchen Kan     return false;
263d9610b4aSShengchen Kan     FROM_TO(MOVSX16rr8, CBW, AX, AL)     // movsbw %al, %ax   --> cbtw
264d9610b4aSShengchen Kan     FROM_TO(MOVSX32rr16, CWDE, EAX, AX)  // movswl %ax, %eax  --> cwtl
265d9610b4aSShengchen Kan     FROM_TO(MOVSX64rr32, CDQE, RAX, EAX) // movslq %eax, %rax --> cltq
2664a92d69aSShengchen Kan #undef FROM_TO
267d9610b4aSShengchen Kan   }
268d9610b4aSShengchen Kan   MI.clear();
269d9610b4aSShengchen Kan   MI.setOpcode(NewOpc);
270d9610b4aSShengchen Kan   return true;
271d9610b4aSShengchen Kan }
2724a92d69aSShengchen Kan 
2734a92d69aSShengchen Kan bool X86::optimizeINCDEC(MCInst &MI, bool In64BitMode) {
2744a92d69aSShengchen Kan   if (In64BitMode)
2754a92d69aSShengchen Kan     return false;
2764a92d69aSShengchen Kan   unsigned NewOpc;
2774a92d69aSShengchen Kan   // If we aren't in 64-bit mode we can use the 1-byte inc/dec instructions.
2784a92d69aSShengchen Kan #define FROM_TO(FROM, TO)                                                      \
2794a92d69aSShengchen Kan   case X86::FROM:                                                              \
2804a92d69aSShengchen Kan     NewOpc = X86::TO;                                                          \
2814a92d69aSShengchen Kan     break;
2824a92d69aSShengchen Kan   switch (MI.getOpcode()) {
2834a92d69aSShengchen Kan   default:
2844a92d69aSShengchen Kan     return false;
2854a92d69aSShengchen Kan     FROM_TO(DEC16r, DEC16r_alt)
2864a92d69aSShengchen Kan     FROM_TO(DEC32r, DEC32r_alt)
2874a92d69aSShengchen Kan     FROM_TO(INC16r, INC16r_alt)
2884a92d69aSShengchen Kan     FROM_TO(INC32r, INC32r_alt)
2894a92d69aSShengchen Kan   }
2904a92d69aSShengchen Kan   MI.setOpcode(NewOpc);
2914a92d69aSShengchen Kan   return true;
2924a92d69aSShengchen Kan }
293*15100a2dSShengchen Kan 
294*15100a2dSShengchen Kan /// Simplify things like MOV32rm to MOV32o32a.
295*15100a2dSShengchen Kan bool X86::optimizeMOV(MCInst &MI, bool In64BitMode) {
296*15100a2dSShengchen Kan   // Don't make these simplifications in 64-bit mode; other assemblers don't
297*15100a2dSShengchen Kan   // perform them because they make the code larger.
298*15100a2dSShengchen Kan   if (In64BitMode)
299*15100a2dSShengchen Kan     return false;
300*15100a2dSShengchen Kan   unsigned NewOpc;
301*15100a2dSShengchen Kan   // We don't currently select the correct instruction form for instructions
302*15100a2dSShengchen Kan   // which have a short %eax, etc. form. Handle this by custom lowering, for
303*15100a2dSShengchen Kan   // now.
304*15100a2dSShengchen Kan   //
305*15100a2dSShengchen Kan   // Note, we are currently not handling the following instructions:
306*15100a2dSShengchen Kan   // MOV64ao8, MOV64o8a
307*15100a2dSShengchen Kan   // XCHG16ar, XCHG32ar, XCHG64ar
308*15100a2dSShengchen Kan   switch (MI.getOpcode()) {
309*15100a2dSShengchen Kan   default:
310*15100a2dSShengchen Kan     return false;
311*15100a2dSShengchen Kan     FROM_TO(MOV8mr_NOREX, MOV8o32a)
312*15100a2dSShengchen Kan     FROM_TO(MOV8mr, MOV8o32a)
313*15100a2dSShengchen Kan     FROM_TO(MOV8rm_NOREX, MOV8ao32)
314*15100a2dSShengchen Kan     FROM_TO(MOV8rm, MOV8ao32)
315*15100a2dSShengchen Kan     FROM_TO(MOV16mr, MOV16o32a)
316*15100a2dSShengchen Kan     FROM_TO(MOV16rm, MOV16ao32)
317*15100a2dSShengchen Kan     FROM_TO(MOV32mr, MOV32o32a)
318*15100a2dSShengchen Kan     FROM_TO(MOV32rm, MOV32ao32)
319*15100a2dSShengchen Kan   }
320*15100a2dSShengchen Kan   bool IsStore = MI.getOperand(0).isReg() && MI.getOperand(1).isReg();
321*15100a2dSShengchen Kan   unsigned AddrBase = IsStore;
322*15100a2dSShengchen Kan   unsigned RegOp = IsStore ? 0 : 5;
323*15100a2dSShengchen Kan   unsigned AddrOp = AddrBase + 3;
324*15100a2dSShengchen Kan   // Check whether the destination register can be fixed.
325*15100a2dSShengchen Kan   unsigned Reg = MI.getOperand(RegOp).getReg();
326*15100a2dSShengchen Kan   if (Reg != X86::AL && Reg != X86::AX && Reg != X86::EAX && Reg != X86::RAX)
327*15100a2dSShengchen Kan     return false;
328*15100a2dSShengchen Kan   // Check whether this is an absolute address.
329*15100a2dSShengchen Kan   // FIXME: We know TLVP symbol refs aren't, but there should be a better way
330*15100a2dSShengchen Kan   // to do this here.
331*15100a2dSShengchen Kan   bool Absolute = true;
332*15100a2dSShengchen Kan   if (MI.getOperand(AddrOp).isExpr()) {
333*15100a2dSShengchen Kan     const MCExpr *MCE = MI.getOperand(AddrOp).getExpr();
334*15100a2dSShengchen Kan     if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(MCE))
335*15100a2dSShengchen Kan       if (SRE->getKind() == MCSymbolRefExpr::VK_TLVP)
336*15100a2dSShengchen Kan         Absolute = false;
337*15100a2dSShengchen Kan   }
338*15100a2dSShengchen Kan   if (Absolute && (MI.getOperand(AddrBase + X86::AddrBaseReg).getReg() != 0 ||
339*15100a2dSShengchen Kan                    MI.getOperand(AddrBase + X86::AddrScaleAmt).getImm() != 1 ||
340*15100a2dSShengchen Kan                    MI.getOperand(AddrBase + X86::AddrIndexReg).getReg() != 0))
341*15100a2dSShengchen Kan     return false;
342*15100a2dSShengchen Kan   // If so, rewrite the instruction.
343*15100a2dSShengchen Kan   MCOperand Saved = MI.getOperand(AddrOp);
344*15100a2dSShengchen Kan   MCOperand Seg = MI.getOperand(AddrBase + X86::AddrSegmentReg);
345*15100a2dSShengchen Kan   MI.clear();
346*15100a2dSShengchen Kan   MI.setOpcode(NewOpc);
347*15100a2dSShengchen Kan   MI.addOperand(Saved);
348*15100a2dSShengchen Kan   MI.addOperand(Seg);
349*15100a2dSShengchen Kan   return true;
350*15100a2dSShengchen Kan }
351