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
72#define GET_X86_COMPRESS_EVEX_TABLE
73#include "X86GenInstrMapping.inc"
91char CompressEVEXLegacy::ID = 0;
96 if (
Reg >= X86::XMM16 &&
Reg <= X86::XMM31)
99 if (
Reg >= X86::YMM16 &&
Reg <= X86::YMM31)
115 "ZMM instructions should not be in the EVEX->VEX tables");
139 int64_t Val = Disp.
getImm();
146 unsigned Opc =
MI.getOpcode();
148 case X86::VALIGNDZ128rri:
149 case X86::VALIGNDZ128rmi:
150 case X86::VALIGNQZ128rri:
151 case X86::VALIGNQZ128rmi: {
152 assert((NewOpc == X86::VPALIGNRrri || NewOpc == X86::VPALIGNRrmi) &&
153 "Unexpected new opcode!");
155 (
Opc == X86::VALIGNQZ128rri ||
Opc == X86::VALIGNQZ128rmi) ? 8 : 4;
157 Imm.setImm(
Imm.getImm() * Scale);
160 case X86::VSHUFF32X4Z256rmi:
161 case X86::VSHUFF32X4Z256rri:
162 case X86::VSHUFF64X2Z256rmi:
163 case X86::VSHUFF64X2Z256rri:
164 case X86::VSHUFI32X4Z256rmi:
165 case X86::VSHUFI32X4Z256rri:
166 case X86::VSHUFI64X2Z256rmi:
167 case X86::VSHUFI64X2Z256rri: {
168 assert((NewOpc == X86::VPERM2F128rri || NewOpc == X86::VPERM2I128rri ||
169 NewOpc == X86::VPERM2F128rmi || NewOpc == X86::VPERM2I128rmi) &&
170 "Unexpected new opcode!");
172 int64_t ImmVal =
Imm.getImm();
174 Imm.setImm(0x20 | ((ImmVal & 2) << 3) | (ImmVal & 1));
177 case X86::VRNDSCALEPDZ128rri:
178 case X86::VRNDSCALEPDZ128rmi:
179 case X86::VRNDSCALEPSZ128rri:
180 case X86::VRNDSCALEPSZ128rmi:
181 case X86::VRNDSCALEPDZ256rri:
182 case X86::VRNDSCALEPDZ256rmi:
183 case X86::VRNDSCALEPSZ256rri:
184 case X86::VRNDSCALEPSZ256rmi:
185 case X86::VRNDSCALESDZrri:
186 case X86::VRNDSCALESDZrmi:
187 case X86::VRNDSCALESSZrri:
188 case X86::VRNDSCALESSZrmi:
189 case X86::VRNDSCALESDZrri_Int:
190 case X86::VRNDSCALESDZrmi_Int:
191 case X86::VRNDSCALESSZrri_Int:
192 case X86::VRNDSCALESSZrmi_Int:
194 int64_t ImmVal =
Imm.getImm();
196 if ((ImmVal & 0xf) != ImmVal)
206 case X86::VPMOVQ2MZ128kr:
207 case X86::VPCMPQZ128rri:
209 case X86::VPMOVQ2MZ256kr:
210 case X86::VPMOVD2MZ128kr:
211 case X86::VPCMPQZ256rri:
212 case X86::VPCMPDZ128rri:
214 case X86::VPMOVD2MZ256kr:
215 case X86::VPCMPDZ256rri:
217 case X86::VPMOVB2MZ128kr:
218 case X86::VPCMPBZ128rri:
220 case X86::VPMOVB2MZ256kr:
221 case X86::VPCMPBZ256rri:
229 unsigned KMOVSize = 0;
244 return KMOVSize < MaskBits;
248 switch (
MI.getOpcode()) {
253 return MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
260 switch (
MI.getOpcode()) {
261 case X86::VPCMPEQDrr:
262 return !Is256Bit &&
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
263 case X86::VPCMPEQDYrr:
264 return MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
271 bool IsZero,
bool Is256Bit,
288 case X86::VBLENDVPSrrr:
290 case X86::VMOVAPSZ128rrk:
291 case X86::VMOVUPSZ128rrk:
292 case X86::VMOVDQA32Z128rrk:
293 case X86::VMOVDQU32Z128rrk:
298 case X86::VBLENDVPSYrrr:
300 case X86::VMOVAPSZ256rrk:
301 case X86::VMOVUPSZ256rrk:
302 case X86::VMOVDQA32Z256rrk:
303 case X86::VMOVDQU32Z256rrk:
308 case X86::VBLENDVPDrrr:
310 case X86::VMOVAPDZ128rrk:
311 case X86::VMOVUPDZ128rrk:
312 case X86::VMOVDQA64Z128rrk:
313 case X86::VMOVDQU64Z128rrk:
318 case X86::VBLENDVPDYrrr:
320 case X86::VMOVAPDZ256rrk:
321 case X86::VMOVUPDZ256rrk:
322 case X86::VMOVDQA64Z256rrk:
323 case X86::VMOVDQU64Z256rrk:
328 case X86::VPBLENDVBrrr:
329 return UseOpc == X86::VMOVDQU8Z128rrk;
330 case X86::VPBLENDVBYrrr:
331 return UseOpc == X86::VMOVDQU8Z256rrk;
339 case X86::VBLENDVPSrrr:
340 return UseOpc == X86::VPBLENDMDZ128rrk || UseOpc == X86::VBLENDMPSZ128rrk;
341 case X86::VBLENDVPSYrrr:
342 return UseOpc == X86::VPBLENDMDZ256rrk || UseOpc == X86::VBLENDMPSZ256rrk;
343 case X86::VBLENDVPDrrr:
344 return UseOpc == X86::VPBLENDMQZ128rrk || UseOpc == X86::VBLENDMPDZ128rrk;
345 case X86::VBLENDVPDYrrr:
346 return UseOpc == X86::VPBLENDMQZ256rrk || UseOpc == X86::VBLENDMPDZ256rrk;
370 unsigned Opc =
MI.getOpcode();
371 bool IsSignMaskCmp =
Opc == X86::VPCMPBZ128rri ||
Opc == X86::VPCMPBZ256rri ||
372 Opc == X86::VPCMPDZ128rri ||
Opc == X86::VPCMPDZ256rri ||
373 Opc == X86::VPCMPQZ128rri ||
Opc == X86::VPCMPQZ256rri;
374 if (!IsSignMaskCmp &&
Opc != X86::VPMOVD2MZ128kr &&
375 Opc != X86::VPMOVD2MZ256kr &&
Opc != X86::VPMOVQ2MZ128kr &&
376 Opc != X86::VPMOVQ2MZ256kr &&
Opc != X86::VPMOVB2MZ128kr &&
377 Opc != X86::VPMOVB2MZ256kr)
384 Register SrcVecReg =
MI.getOperand(1).getReg();
386 bool ConstantDefOnlyFeedsCmp =
false;
389 int64_t Pred =
MI.getOperand(3).getImm();
391 if (Pred != 5 && Pred != 6)
393 Register ConstantReg =
MI.getOperand(2).getReg();
394 bool Is256Bit =
Opc == X86::VPCMPBZ256rri ||
Opc == X86::VPCMPDZ256rri ||
395 Opc == X86::VPCMPQZ256rri;
403 ConstantDefOnlyFeedsCmp = !
TRI->regsOverlap(ConstantReg, SrcVecReg);
407 if (
UseMI.readsRegister(ConstantReg,
TRI)) {
408 ConstantDefOnlyFeedsCmp =
false;
413 unsigned MovMskOpc = 0;
414 unsigned BlendOpc = 0;
416 case X86::VPCMPDZ128rri:
417 case X86::VPMOVD2MZ128kr:
418 MovMskOpc = X86::VMOVMSKPSrr;
419 BlendOpc = X86::VBLENDVPSrrr;
421 case X86::VPCMPDZ256rri:
422 case X86::VPMOVD2MZ256kr:
423 MovMskOpc = X86::VMOVMSKPSYrr;
424 BlendOpc = X86::VBLENDVPSYrrr;
426 case X86::VPCMPQZ128rri:
427 case X86::VPMOVQ2MZ128kr:
428 MovMskOpc = X86::VMOVMSKPDrr;
429 BlendOpc = X86::VBLENDVPDrrr;
431 case X86::VPCMPQZ256rri:
432 case X86::VPMOVQ2MZ256kr:
433 MovMskOpc = X86::VMOVMSKPDYrr;
434 BlendOpc = X86::VBLENDVPDYrrr;
436 case X86::VPCMPBZ128rri:
437 case X86::VPMOVB2MZ128kr:
438 MovMskOpc = X86::VPMOVMSKBrr;
439 BlendOpc = X86::VPBLENDVBrrr;
441 case X86::VPCMPBZ256rri:
442 case X86::VPMOVB2MZ256kr:
443 MovMskOpc = X86::VPMOVMSKBYrr;
444 BlendOpc = X86::VPBLENDVBYrrr;
452 bool BlendIsMaskedBlend =
false;
456 if (CurMI.readsRegister(MaskReg,
TRI)) {
457 if (KMovMI || BlendMI)
460 unsigned UseOpc = CurMI.getOpcode();
461 bool IsKMOV = UseOpc == X86::KMOVBrk || UseOpc == X86::KMOVWrk ||
462 UseOpc == X86::KMOVDrk;
464 if (IsKMOV && CurMI.getOperand(1).getReg() == MaskReg &&
476 if (!IsMaskedMove && !IsMaskedBlend)
479 unsigned MaskOpIdx = IsMaskedBlend ? 1 : 2;
480 if (CurMI.getOperand(MaskOpIdx).getReg() == MaskReg &&
483 BlendIsMaskedBlend = IsMaskedBlend;
490 if (CurMI.modifiesRegister(MaskReg,
TRI)) {
491 if (!KMovMI && !BlendMI)
501 if (!KMovMI && !BlendMI)
507 if (IsSignMaskCmp && KMovMI) {
510 MBB.computeRegisterLiveness(
535 int64_t ComplementMask =
537 unsigned ComplementOpc =
540 : (
isInt<8>(ComplementMask) ? X86::XOR32ri8 : X86::XOR32ri);
544 if (MovMskBits != 32) {
545 MIB.addImm(ComplementMask);
546 MIB->findRegisterDefOperand(X86::EFLAGS,
TRI)->setIsDead();
550 }
else if (BlendMI) {
554 BlendMI->
getOperand(BlendIsMaskedBlend ? 2 : 1);
568 assert(NewMI &&
"Expected a compressed instruction");
571 if (ConstantDefOnlyFeedsCmp &&
MI.getOperand(2).isKill())
597 auto IsRedundantNewDataDest = [&](
unsigned &
Opc) {
605 X86::isCFCMOVCC(
MI.getOpcode()))
612 if (!
Desc.isCommutable() ||
Desc.getNumOperands() < 3 ||
613 !
MI.getOperand(2).isReg() ||
MI.getOperand(2).getReg() != Reg0)
616 ST.getInstrInfo()->commuteInstruction(
MI,
false, 1, 2);
617 Opc =
MI.getOpcode();
632 unsigned Opc =
MI.getOpcode();
633 bool IsSetZUCCm =
Opc == X86::SETZUCCm;
637 bool IsNDLike = IsND ||
Opc == X86::MOVBE32rr ||
Opc == X86::MOVBE64rr;
638 bool IsRedundantNDD = IsNDLike ? IsRedundantNewDataDest(
Opc) :
false;
640 auto GetCompressedOpc = [&](
unsigned Opc) ->
unsigned {
653 if (IsRedundantNDD) {
663 if (
MI.definesRegister(Super,
nullptr))
664 IsRedundantNDD =
false;
672 "Unexpected NDD instruction with relocation!");
673 }
else if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND ||
674 Opc == X86::ADD32rr_ND ||
Opc == X86::ADD64rr_ND) {
679 MI.registerDefIsDead(X86::EFLAGS,
nullptr)) {
682 bool Is32BitReg =
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD32rr_ND;
684 ST.getInstrInfo()->get(Is32BitReg ? X86::LEA64_32r : X86::LEA64r);
690 if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND)
697 MI.removeFromParent();
704 unsigned NewOpc = IsRedundantNDD
706 : ((IsNDLike && ST.hasNF() &&
707 MI.registerDefIsDead(X86::EFLAGS,
nullptr))
709 : GetCompressedOpc(
Opc));
716 "Unexpected to compress NF instructions without ND.");
718 const MCInstrDesc &NewDesc = ST.getInstrInfo()->get(NewOpc);
731 "Unknown EVEX2EVEX compression");
736 MI.setAsmPrinterFlag(AsmComment);
738 MI.tieOperands(0, 1);
747 static std::atomic<bool> TableChecked(
false);
748 if (!TableChecked.load(std::memory_order_relaxed)) {
750 "X86CompressEVEXTable is not sorted!");
751 TableChecked.store(
true, std::memory_order_relaxed);
755 if (!ST.hasAVX512() && !ST.hasEGPR() && !ST.hasNDD() && !ST.hasZU())
768 MI->eraseFromParent();
779 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)
cl::opt< bool > X86EnableAPXForRelocation
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 >