63#define COMP_EVEX_DESC "Compressing EVEX instrs when possible"
64#define COMP_EVEX_NAME "x86-compress-evex"
66#define DEBUG_TYPE COMP_EVEX_NAME
70#define GET_X86_COMPRESS_EVEX_TABLE
71#include "X86GenInstrMapping.inc"
89char CompressEVEXLegacy::ID = 0;
94 if (
Reg >= X86::XMM16 &&
Reg <= X86::XMM31)
97 if (
Reg >= X86::YMM16 &&
Reg <= X86::YMM31)
113 "ZMM instructions should not be in the EVEX->VEX tables");
137 int64_t Val = Disp.
getImm();
144 unsigned Opc =
MI.getOpcode();
146 case X86::VALIGNDZ128rri:
147 case X86::VALIGNDZ128rmi:
148 case X86::VALIGNQZ128rri:
149 case X86::VALIGNQZ128rmi: {
150 assert((NewOpc == X86::VPALIGNRrri || NewOpc == X86::VPALIGNRrmi) &&
151 "Unexpected new opcode!");
153 (
Opc == X86::VALIGNQZ128rri ||
Opc == X86::VALIGNQZ128rmi) ? 8 : 4;
155 Imm.setImm(
Imm.getImm() * Scale);
158 case X86::VSHUFF32X4Z256rmi:
159 case X86::VSHUFF32X4Z256rri:
160 case X86::VSHUFF64X2Z256rmi:
161 case X86::VSHUFF64X2Z256rri:
162 case X86::VSHUFI32X4Z256rmi:
163 case X86::VSHUFI32X4Z256rri:
164 case X86::VSHUFI64X2Z256rmi:
165 case X86::VSHUFI64X2Z256rri: {
166 assert((NewOpc == X86::VPERM2F128rri || NewOpc == X86::VPERM2I128rri ||
167 NewOpc == X86::VPERM2F128rmi || NewOpc == X86::VPERM2I128rmi) &&
168 "Unexpected new opcode!");
170 int64_t ImmVal =
Imm.getImm();
172 Imm.setImm(0x20 | ((ImmVal & 2) << 3) | (ImmVal & 1));
175 case X86::VRNDSCALEPDZ128rri:
176 case X86::VRNDSCALEPDZ128rmi:
177 case X86::VRNDSCALEPSZ128rri:
178 case X86::VRNDSCALEPSZ128rmi:
179 case X86::VRNDSCALEPDZ256rri:
180 case X86::VRNDSCALEPDZ256rmi:
181 case X86::VRNDSCALEPSZ256rri:
182 case X86::VRNDSCALEPSZ256rmi:
183 case X86::VRNDSCALESDZrri:
184 case X86::VRNDSCALESDZrmi:
185 case X86::VRNDSCALESSZrri:
186 case X86::VRNDSCALESSZrmi:
187 case X86::VRNDSCALESDZrri_Int:
188 case X86::VRNDSCALESDZrmi_Int:
189 case X86::VRNDSCALESSZrri_Int:
190 case X86::VRNDSCALESSZrmi_Int:
192 int64_t ImmVal =
Imm.getImm();
194 if ((ImmVal & 0xf) != ImmVal)
204 case X86::VPMOVQ2MZ128kr:
205 case X86::VPCMPQZ128rri:
207 case X86::VPMOVQ2MZ256kr:
208 case X86::VPMOVD2MZ128kr:
209 case X86::VPCMPQZ256rri:
210 case X86::VPCMPDZ128rri:
212 case X86::VPMOVD2MZ256kr:
213 case X86::VPCMPDZ256rri:
215 case X86::VPMOVB2MZ128kr:
216 case X86::VPCMPBZ128rri:
218 case X86::VPMOVB2MZ256kr:
219 case X86::VPCMPBZ256rri:
227 unsigned KMOVSize = 0;
242 return KMOVSize < MaskBits;
246 switch (
MI.getOpcode()) {
251 return MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
258 switch (
MI.getOpcode()) {
259 case X86::VPCMPEQDrr:
260 return !Is256Bit &&
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
261 case X86::VPCMPEQDYrr:
262 return MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
269 bool IsZero,
bool Is256Bit,
286 case X86::VBLENDVPSrrr:
288 case X86::VMOVAPSZ128rrk:
289 case X86::VMOVUPSZ128rrk:
290 case X86::VMOVDQA32Z128rrk:
291 case X86::VMOVDQU32Z128rrk:
296 case X86::VBLENDVPSYrrr:
298 case X86::VMOVAPSZ256rrk:
299 case X86::VMOVUPSZ256rrk:
300 case X86::VMOVDQA32Z256rrk:
301 case X86::VMOVDQU32Z256rrk:
306 case X86::VBLENDVPDrrr:
308 case X86::VMOVAPDZ128rrk:
309 case X86::VMOVUPDZ128rrk:
310 case X86::VMOVDQA64Z128rrk:
311 case X86::VMOVDQU64Z128rrk:
316 case X86::VBLENDVPDYrrr:
318 case X86::VMOVAPDZ256rrk:
319 case X86::VMOVUPDZ256rrk:
320 case X86::VMOVDQA64Z256rrk:
321 case X86::VMOVDQU64Z256rrk:
326 case X86::VPBLENDVBrrr:
327 return UseOpc == X86::VMOVDQU8Z128rrk;
328 case X86::VPBLENDVBYrrr:
329 return UseOpc == X86::VMOVDQU8Z256rrk;
337 case X86::VBLENDVPSrrr:
338 return UseOpc == X86::VPBLENDMDZ128rrk || UseOpc == X86::VBLENDMPSZ128rrk;
339 case X86::VBLENDVPSYrrr:
340 return UseOpc == X86::VPBLENDMDZ256rrk || UseOpc == X86::VBLENDMPSZ256rrk;
341 case X86::VBLENDVPDrrr:
342 return UseOpc == X86::VPBLENDMQZ128rrk || UseOpc == X86::VBLENDMPDZ128rrk;
343 case X86::VBLENDVPDYrrr:
344 return UseOpc == X86::VPBLENDMQZ256rrk || UseOpc == X86::VBLENDMPDZ256rrk;
368 unsigned Opc =
MI.getOpcode();
369 bool IsSignMaskCmp =
Opc == X86::VPCMPBZ128rri ||
Opc == X86::VPCMPBZ256rri ||
370 Opc == X86::VPCMPDZ128rri ||
Opc == X86::VPCMPDZ256rri ||
371 Opc == X86::VPCMPQZ128rri ||
Opc == X86::VPCMPQZ256rri;
372 if (!IsSignMaskCmp &&
Opc != X86::VPMOVD2MZ128kr &&
373 Opc != X86::VPMOVD2MZ256kr &&
Opc != X86::VPMOVQ2MZ128kr &&
374 Opc != X86::VPMOVQ2MZ256kr &&
Opc != X86::VPMOVB2MZ128kr &&
375 Opc != X86::VPMOVB2MZ256kr)
382 Register SrcVecReg =
MI.getOperand(1).getReg();
384 bool ConstantDefOnlyFeedsCmp =
false;
387 int64_t Pred =
MI.getOperand(3).getImm();
389 if (Pred != 5 && Pred != 6)
391 Register ConstantReg =
MI.getOperand(2).getReg();
392 bool Is256Bit =
Opc == X86::VPCMPBZ256rri ||
Opc == X86::VPCMPDZ256rri ||
393 Opc == X86::VPCMPQZ256rri;
401 ConstantDefOnlyFeedsCmp = !
TRI->regsOverlap(ConstantReg, SrcVecReg);
405 if (
UseMI.readsRegister(ConstantReg,
TRI)) {
406 ConstantDefOnlyFeedsCmp =
false;
411 unsigned MovMskOpc = 0;
412 unsigned BlendOpc = 0;
414 case X86::VPCMPDZ128rri:
415 case X86::VPMOVD2MZ128kr:
416 MovMskOpc = X86::VMOVMSKPSrr;
417 BlendOpc = X86::VBLENDVPSrrr;
419 case X86::VPCMPDZ256rri:
420 case X86::VPMOVD2MZ256kr:
421 MovMskOpc = X86::VMOVMSKPSYrr;
422 BlendOpc = X86::VBLENDVPSYrrr;
424 case X86::VPCMPQZ128rri:
425 case X86::VPMOVQ2MZ128kr:
426 MovMskOpc = X86::VMOVMSKPDrr;
427 BlendOpc = X86::VBLENDVPDrrr;
429 case X86::VPCMPQZ256rri:
430 case X86::VPMOVQ2MZ256kr:
431 MovMskOpc = X86::VMOVMSKPDYrr;
432 BlendOpc = X86::VBLENDVPDYrrr;
434 case X86::VPCMPBZ128rri:
435 case X86::VPMOVB2MZ128kr:
436 MovMskOpc = X86::VPMOVMSKBrr;
437 BlendOpc = X86::VPBLENDVBrrr;
439 case X86::VPCMPBZ256rri:
440 case X86::VPMOVB2MZ256kr:
441 MovMskOpc = X86::VPMOVMSKBYrr;
442 BlendOpc = X86::VPBLENDVBYrrr;
450 bool BlendIsMaskedBlend =
false;
454 if (CurMI.readsRegister(MaskReg,
TRI)) {
455 if (KMovMI || BlendMI)
458 unsigned UseOpc = CurMI.getOpcode();
459 bool IsKMOV = UseOpc == X86::KMOVBrk || UseOpc == X86::KMOVWrk ||
460 UseOpc == X86::KMOVDrk;
462 if (IsKMOV && CurMI.getOperand(1).getReg() == MaskReg &&
474 if (!IsMaskedMove && !IsMaskedBlend)
477 unsigned MaskOpIdx = IsMaskedBlend ? 1 : 2;
478 if (CurMI.getOperand(MaskOpIdx).getReg() == MaskReg &&
481 BlendIsMaskedBlend = IsMaskedBlend;
488 if (CurMI.modifiesRegister(MaskReg,
TRI)) {
489 if (!KMovMI && !BlendMI)
499 if (!KMovMI && !BlendMI)
505 if (IsSignMaskCmp && KMovMI) {
508 MBB.computeRegisterLiveness(
533 int64_t ComplementMask =
535 unsigned ComplementOpc =
538 : (
isInt<8>(ComplementMask) ? X86::XOR32ri8 : X86::XOR32ri);
542 if (MovMskBits != 32) {
543 MIB.addImm(ComplementMask);
544 MIB->findRegisterDefOperand(X86::EFLAGS,
TRI)->setIsDead();
548 }
else if (BlendMI) {
552 BlendMI->
getOperand(BlendIsMaskedBlend ? 2 : 1);
566 assert(NewMI &&
"Expected a compressed instruction");
569 if (ConstantDefOnlyFeedsCmp &&
MI.getOperand(2).isKill())
595 auto IsRedundantNewDataDest = [&](
unsigned &
Opc) {
603 X86::isCFCMOVCC(
MI.getOpcode()))
610 if (!
Desc.isCommutable() ||
Desc.getNumOperands() < 3 ||
611 !
MI.getOperand(2).isReg() ||
MI.getOperand(2).getReg() != Reg0)
614 ST.getInstrInfo()->commuteInstruction(
MI,
false, 1, 2);
615 Opc =
MI.getOpcode();
630 unsigned Opc =
MI.getOpcode();
631 bool IsSetZUCCm =
Opc == X86::SETZUCCm;
635 bool IsNDLike = IsND ||
Opc == X86::MOVBE32rr ||
Opc == X86::MOVBE64rr;
636 bool IsRedundantNDD = IsNDLike ? IsRedundantNewDataDest(
Opc) :
false;
638 auto GetCompressedOpc = [&](
unsigned Opc) ->
unsigned {
651 if (IsRedundantNDD) {
661 if (
MI.definesRegister(Super,
nullptr))
662 IsRedundantNDD =
false;
668 if (!ST.getCLOpts().enable_apx_for_relocation)
670 "Unexpected NDD instruction with relocation!");
671 }
else if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND ||
672 Opc == X86::ADD32rr_ND ||
Opc == X86::ADD64rr_ND) {
677 MI.registerDefIsDead(X86::EFLAGS,
nullptr)) {
680 bool Is32BitReg =
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD32rr_ND;
682 ST.getInstrInfo()->get(Is32BitReg ? X86::LEA64_32r : X86::LEA64r);
688 if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND)
695 MI.removeFromParent();
702 unsigned NewOpc = IsRedundantNDD
704 : ((IsNDLike && ST.hasNF() &&
705 MI.registerDefIsDead(X86::EFLAGS,
nullptr))
707 : GetCompressedOpc(
Opc));
714 "Unexpected to compress NF instructions without ND.");
716 const MCInstrDesc &NewDesc = ST.getInstrInfo()->get(NewOpc);
729 "Unknown EVEX2EVEX compression");
734 MI.setAsmPrinterFlag(AsmComment);
736 MI.tieOperands(0, 1);
745 static std::atomic<bool> TableChecked(
false);
746 if (!TableChecked.load(std::memory_order_relaxed)) {
748 "X86CompressEVEXTable is not sorted!");
749 TableChecked.store(
true, std::memory_order_relaxed);
753 if (!ST.hasAVX512() && !ST.hasEGPR() && !ST.hasNDD() && !ST.hasZU())
766 MI->eraseFromParent();
777 return new CompressEVEXLegacy();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallVector class.
static bool performCustomAdjustments(MachineInstr &MI, unsigned NewOpc)
static bool CompressEVEXImpl(MachineInstr &MI, MachineBasicBlock &MBB, const X86Subtarget &ST, SmallVectorImpl< MachineInstr * > &ToErase)
static bool isKMovNarrowing(unsigned MaskBits, unsigned KMOVOpc)
static bool isCompressibleMaskedBlendUse(unsigned BlendOpc, unsigned UseOpc)
static unsigned getMovMskBits(unsigned Opc)
static bool isZeroVector(const MachineInstr &MI)
static bool isAllOnesVector(const MachineInstr &MI, bool Is256Bit)
static bool isCompressibleBlendVUse(unsigned BlendOpc, unsigned UseOpc)
static bool tryCompressMaskProducer(MachineInstr &MI, MachineBasicBlock &MBB, const X86Subtarget &ST, SmallVectorImpl< MachineInstr * > &ToErase)
static bool runOnMF(MachineFunction &MF)
static bool hasShorterEVEXViaCDisp8(const MachineInstr &MI)
static MachineInstr * getSignMaskConstantDef(MachineInstr &MI, Register Reg, bool IsZero, bool Is256Bit, const TargetRegisterInfo *TRI)
static bool usesExtendedRegister(const MachineInstr &MI)
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
int64_t getSExtValue() const
Get sign extended value.
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.
MachineInstrBundleIterator< const MachineInstr > const_iterator
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
void setAsmPrinterFlag(AsmPrinterFlagTy Flag)
Set a flag for the AsmPrinter.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
LLVM_ABI bool isRenamable() const
isRenamable - Returns true if this register may be renamed, i.e.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
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.
bool isDispOrCDisp8(uint64_t TSFlags, int64_t Value, int *ImmOffset=nullptr)
Determine if this immediate can fit in a disp8 or a compressed disp8 for EVEX instructions.
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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Kill
The last use of a register.
MCRegister getX86SubSuperRegister(MCRegister Reg, unsigned Size, bool High=false)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
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.
auto reverse(ContainerTy &&C)
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...
RegState getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
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 >