60#define COMP_EVEX_DESC "Compressing EVEX instrs when possible"
61#define COMP_EVEX_NAME "x86-compress-evex"
63#define DEBUG_TYPE COMP_EVEX_NAME
69#define GET_X86_COMPRESS_EVEX_TABLE
70#include "X86GenInstrMapping.inc"
88char CompressEVEXLegacy::ID = 0;
93 if (
Reg >= X86::XMM16 &&
Reg <= X86::XMM31)
96 if (
Reg >= X86::YMM16 &&
Reg <= X86::YMM31)
112 "ZMM instructions should not be in the EVEX->VEX tables");
123 unsigned Opc =
MI.getOpcode();
125 case X86::VALIGNDZ128rri:
126 case X86::VALIGNDZ128rmi:
127 case X86::VALIGNQZ128rri:
128 case X86::VALIGNQZ128rmi: {
129 assert((NewOpc == X86::VPALIGNRrri || NewOpc == X86::VPALIGNRrmi) &&
130 "Unexpected new opcode!");
132 (
Opc == X86::VALIGNQZ128rri ||
Opc == X86::VALIGNQZ128rmi) ? 8 : 4;
134 Imm.setImm(Imm.getImm() * Scale);
137 case X86::VSHUFF32X4Z256rmi:
138 case X86::VSHUFF32X4Z256rri:
139 case X86::VSHUFF64X2Z256rmi:
140 case X86::VSHUFF64X2Z256rri:
141 case X86::VSHUFI32X4Z256rmi:
142 case X86::VSHUFI32X4Z256rri:
143 case X86::VSHUFI64X2Z256rmi:
144 case X86::VSHUFI64X2Z256rri: {
145 assert((NewOpc == X86::VPERM2F128rri || NewOpc == X86::VPERM2I128rri ||
146 NewOpc == X86::VPERM2F128rmi || NewOpc == X86::VPERM2I128rmi) &&
147 "Unexpected new opcode!");
149 int64_t ImmVal = Imm.getImm();
151 Imm.setImm(0x20 | ((ImmVal & 2) << 3) | (ImmVal & 1));
154 case X86::VRNDSCALEPDZ128rri:
155 case X86::VRNDSCALEPDZ128rmi:
156 case X86::VRNDSCALEPSZ128rri:
157 case X86::VRNDSCALEPSZ128rmi:
158 case X86::VRNDSCALEPDZ256rri:
159 case X86::VRNDSCALEPDZ256rmi:
160 case X86::VRNDSCALEPSZ256rri:
161 case X86::VRNDSCALEPSZ256rmi:
162 case X86::VRNDSCALESDZrri:
163 case X86::VRNDSCALESDZrmi:
164 case X86::VRNDSCALESSZrri:
165 case X86::VRNDSCALESSZrmi:
166 case X86::VRNDSCALESDZrri_Int:
167 case X86::VRNDSCALESDZrmi_Int:
168 case X86::VRNDSCALESSZrri_Int:
169 case X86::VRNDSCALESSZrmi_Int:
171 int64_t ImmVal = Imm.getImm();
173 if ((ImmVal & 0xf) != ImmVal)
193 auto IsRedundantNewDataDest = [&](
unsigned &
Opc) {
201 X86::isCFCMOVCC(
MI.getOpcode()))
208 if (!
Desc.isCommutable() ||
Desc.getNumOperands() < 3 ||
209 !
MI.getOperand(2).isReg() ||
MI.getOperand(2).getReg() != Reg0)
212 ST.getInstrInfo()->commuteInstruction(
MI,
false, 1, 2);
213 Opc =
MI.getOpcode();
228 unsigned Opc =
MI.getOpcode();
229 bool IsSetZUCCm =
Opc == X86::SETZUCCm;
233 bool IsNDLike = IsND ||
Opc == X86::MOVBE32rr ||
Opc == X86::MOVBE64rr;
234 bool IsRedundantNDD = IsNDLike ? IsRedundantNewDataDest(
Opc) :
false;
236 auto GetCompressedOpc = [&](
unsigned Opc) ->
unsigned {
239 if (
I == Table.
end() ||
I->OldOpc !=
Opc)
249 if (IsRedundantNDD) {
259 if (
MI.definesRegister(Super,
nullptr))
260 IsRedundantNDD =
false;
268 "Unexpected NDD instruction with relocation!");
269 }
else if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND ||
270 Opc == X86::ADD32rr_ND ||
Opc == X86::ADD64rr_ND) {
275 MI.registerDefIsDead(X86::EFLAGS,
nullptr)) {
278 bool Is32BitReg =
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD32rr_ND;
280 ST.getInstrInfo()->get(Is32BitReg ? X86::LEA64_32r : X86::LEA64r);
286 if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND)
293 MI.removeFromParent();
300 unsigned NewOpc = IsRedundantNDD
302 : ((IsNDLike && ST.hasNF() &&
303 MI.registerDefIsDead(X86::EFLAGS,
nullptr))
305 : GetCompressedOpc(
Opc));
310 const MCInstrDesc &NewDesc = ST.getInstrInfo()->get(NewOpc);
323 "Unknown EVEX2EVEX compression");
328 MI.setAsmPrinterFlag(AsmComment);
330 MI.tieOperands(0, 1);
339 static std::atomic<bool> TableChecked(
false);
340 if (!TableChecked.load(std::memory_order_relaxed)) {
342 "X86CompressEVEXTable is not sorted!");
343 TableChecked.store(
true, std::memory_order_relaxed);
347 if (!ST.hasAVX512() && !ST.hasEGPR() && !ST.hasNDD() && !ST.hasZU())
365 return new CompressEVEXLegacy();
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)
cl::opt< bool > X86EnableAPXForRelocation
static bool runOnMF(MachineFunction &MF)
static bool CompressEVEXImpl(MachineInstr &MI, MachineBasicBlock &MBB, const X86Subtarget &ST)
static bool usesExtendedRegister(const MachineInstr &MI)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Represents analyses that only rely on functions' control flow.
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...
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.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
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.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
StringRef - Represent a constant reference to a string, i.e.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Pass manager infrastructure for declaring and invalidating analyses.
#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.
bool isZMMReg(MCRegister Reg)
bool hasNewDataDest(uint64_t TSFlags)
@ 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 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.
FunctionPass * createX86CompressEVEXLegacyPass()
static bool isAddMemInstrWithRelocation(const MachineInstr &MI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MCRegister getX86SubSuperRegister(MCRegister Reg, unsigned Size, bool High=false)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
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...
ArrayRef(const T &OneElt) -> ArrayRef< T >