56#define COMP_EVEX_DESC "Compressing EVEX instrs when possible"
57#define COMP_EVEX_NAME "x86-compress-evex"
59#define DEBUG_TYPE COMP_EVEX_NAME
65#define GET_X86_COMPRESS_EVEX_TABLE
66#include "X86GenInstrMapping.inc"
84char CompressEVEXPass::ID = 0;
89 if (Reg >= X86::XMM16 && Reg <= X86::XMM31)
92 if (Reg >= X86::YMM16 && Reg <= X86::YMM31)
108 "ZMM instructions should not be in the EVEX->VEX tables");
119 unsigned Opc =
MI.getOpcode();
121 case X86::VALIGNDZ128rri:
122 case X86::VALIGNDZ128rmi:
123 case X86::VALIGNQZ128rri:
124 case X86::VALIGNQZ128rmi: {
125 assert((NewOpc == X86::VPALIGNRrri || NewOpc == X86::VPALIGNRrmi) &&
126 "Unexpected new opcode!");
128 (
Opc == X86::VALIGNQZ128rri ||
Opc == X86::VALIGNQZ128rmi) ? 8 : 4;
130 Imm.setImm(Imm.getImm() * Scale);
133 case X86::VSHUFF32X4Z256rmi:
134 case X86::VSHUFF32X4Z256rri:
135 case X86::VSHUFF64X2Z256rmi:
136 case X86::VSHUFF64X2Z256rri:
137 case X86::VSHUFI32X4Z256rmi:
138 case X86::VSHUFI32X4Z256rri:
139 case X86::VSHUFI64X2Z256rmi:
140 case X86::VSHUFI64X2Z256rri: {
141 assert((NewOpc == X86::VPERM2F128rri || NewOpc == X86::VPERM2I128rri ||
142 NewOpc == X86::VPERM2F128rmi || NewOpc == X86::VPERM2I128rmi) &&
143 "Unexpected new opcode!");
145 int64_t ImmVal = Imm.getImm();
147 Imm.setImm(0x20 | ((ImmVal & 2) << 3) | (ImmVal & 1));
150 case X86::VRNDSCALEPDZ128rri:
151 case X86::VRNDSCALEPDZ128rmi:
152 case X86::VRNDSCALEPSZ128rri:
153 case X86::VRNDSCALEPSZ128rmi:
154 case X86::VRNDSCALEPDZ256rri:
155 case X86::VRNDSCALEPDZ256rmi:
156 case X86::VRNDSCALEPSZ256rri:
157 case X86::VRNDSCALEPSZ256rmi:
158 case X86::VRNDSCALESDZrri:
159 case X86::VRNDSCALESDZrmi:
160 case X86::VRNDSCALESSZrri:
161 case X86::VRNDSCALESSZrmi:
162 case X86::VRNDSCALESDZrri_Int:
163 case X86::VRNDSCALESDZrmi_Int:
164 case X86::VRNDSCALESSZrri_Int:
165 case X86::VRNDSCALESSZrmi_Int:
167 int64_t ImmVal = Imm.getImm();
169 if ((ImmVal & 0xf) != ImmVal)
188 auto IsRedundantNewDataDest = [&](
unsigned &
Opc) {
196 X86::isCFCMOVCC(
MI.getOpcode()))
203 if (!
Desc.isCommutable() ||
Desc.getNumOperands() < 3 ||
204 !
MI.getOperand(2).isReg() ||
MI.getOperand(2).getReg() != Reg0)
207 ST.getInstrInfo()->commuteInstruction(
MI,
false, 1, 2);
208 Opc =
MI.getOpcode();
225 unsigned Opc =
MI.getOpcode();
227 bool IsNDLike = IsND ||
Opc == X86::MOVBE32rr ||
Opc == X86::MOVBE64rr;
228 bool IsRedundantNDD = IsNDLike ? IsRedundantNewDataDest(
Opc) :
false;
230 auto GetCompressedOpc = [&](
unsigned Opc) ->
unsigned {
233 if (
I == Table.
end() ||
I->OldOpc !=
Opc)
248 if (IsRedundantNDD) {
253 if (
MI.definesRegister(Super,
nullptr))
254 IsRedundantNDD =
false;
262 "Unexpected NDD instruction with relocation!");
267 unsigned NewOpc = IsRedundantNDD
269 : ((IsNDLike && ST.hasNF() &&
270 MI.registerDefIsDead(X86::EFLAGS,
nullptr))
272 : GetCompressedOpc(
Opc));
277 const MCInstrDesc &NewDesc = ST.getInstrInfo()->get(NewOpc);
290 "Unknown EVEX2EVEX compression");
295 MI.setAsmPrinterFlag(AsmComment);
297 MI.tieOperands(0, 1);
306 static std::atomic<bool> TableChecked(
false);
307 if (!TableChecked.load(std::memory_order_relaxed)) {
309 "X86CompressEVEXTable is not sorted!");
310 TableChecked.store(
true, std::memory_order_relaxed);
314 if (!
ST.hasAVX512() && !
ST.hasEGPR() && !
ST.hasNDD())
317 bool Changed =
false;
331 return new CompressEVEXPass();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static bool performCustomAdjustments(MachineInstr &MI, unsigned NewOpc)
static bool CompressEVEXImpl(MachineInstr &MI, const X86Subtarget &ST)
cl::opt< bool > X86EnableAPXForRelocation
static bool usesExtendedRegister(const MachineInstr &MI)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
FunctionPass class - This class is used to implement most global optimizations.
Describe properties that are true of each instruction in the target description file.
Wrapper class representing physical registers. Should be passed by value.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
StringRef - Represent a constant reference to a string, i.e.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ EVEX
EVEX - Specifies that this instruction use EVEX form which provides syntax support up to 32 512-bit r...
@ VEX
VEX - encoding using 0xC4/0xC5.
@ LEGACY
LEGACY - encoding using REX/REX2 or w/o opcode prefix.
bool isZMMReg(MCRegister Reg)
bool hasNewDataDest(uint64_t TSFlags)
bool isApxExtendedReg(MCRegister Reg)
int getFirstAddrOperandIdx(const MachineInstr &MI)
Return the index of the instruction's first address operand, if it has a memory reference,...
unsigned getNonNDVariant(unsigned Opc)
unsigned getNFVariant(unsigned Opc)
This is an optimization pass for GlobalISel generic memory operations.
static bool isAddMemInstrWithRelocation(const MachineInstr &MI)
MCRegister getX86SubSuperRegister(MCRegister Reg, unsigned Size, bool High=false)
FunctionPass * createX86CompressEVEXPass()
This pass compress instructions from EVEX space to legacy/VEX/EVEX space when possible in order to re...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Description of the encoding of one expression Op.