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");
126 unsigned Opc =
MI.getOpcode();
128 case X86::VALIGNDZ128rri:
129 case X86::VALIGNDZ128rmi:
130 case X86::VALIGNQZ128rri:
131 case X86::VALIGNQZ128rmi: {
132 assert((NewOpc == X86::VPALIGNRrri || NewOpc == X86::VPALIGNRrmi) &&
133 "Unexpected new opcode!");
135 (
Opc == X86::VALIGNQZ128rri ||
Opc == X86::VALIGNQZ128rmi) ? 8 : 4;
137 Imm.setImm(
Imm.getImm() * Scale);
140 case X86::VSHUFF32X4Z256rmi:
141 case X86::VSHUFF32X4Z256rri:
142 case X86::VSHUFF64X2Z256rmi:
143 case X86::VSHUFF64X2Z256rri:
144 case X86::VSHUFI32X4Z256rmi:
145 case X86::VSHUFI32X4Z256rri:
146 case X86::VSHUFI64X2Z256rmi:
147 case X86::VSHUFI64X2Z256rri: {
148 assert((NewOpc == X86::VPERM2F128rri || NewOpc == X86::VPERM2I128rri ||
149 NewOpc == X86::VPERM2F128rmi || NewOpc == X86::VPERM2I128rmi) &&
150 "Unexpected new opcode!");
152 int64_t ImmVal =
Imm.getImm();
154 Imm.setImm(0x20 | ((ImmVal & 2) << 3) | (ImmVal & 1));
157 case X86::VRNDSCALEPDZ128rri:
158 case X86::VRNDSCALEPDZ128rmi:
159 case X86::VRNDSCALEPSZ128rri:
160 case X86::VRNDSCALEPSZ128rmi:
161 case X86::VRNDSCALEPDZ256rri:
162 case X86::VRNDSCALEPDZ256rmi:
163 case X86::VRNDSCALEPSZ256rri:
164 case X86::VRNDSCALEPSZ256rmi:
165 case X86::VRNDSCALESDZrri:
166 case X86::VRNDSCALESDZrmi:
167 case X86::VRNDSCALESSZrri:
168 case X86::VRNDSCALESSZrmi:
169 case X86::VRNDSCALESDZrri_Int:
170 case X86::VRNDSCALESDZrmi_Int:
171 case X86::VRNDSCALESSZrri_Int:
172 case X86::VRNDSCALESSZrmi_Int:
174 int64_t ImmVal =
Imm.getImm();
176 if ((ImmVal & 0xf) != ImmVal)
186 case X86::VPMOVQ2MZ128kr:
187 case X86::VPCMPQZ128rri:
189 case X86::VPMOVQ2MZ256kr:
190 case X86::VPMOVD2MZ128kr:
191 case X86::VPCMPQZ256rri:
192 case X86::VPCMPDZ128rri:
194 case X86::VPMOVD2MZ256kr:
195 case X86::VPCMPDZ256rri:
197 case X86::VPMOVB2MZ128kr:
198 case X86::VPCMPBZ128rri:
200 case X86::VPMOVB2MZ256kr:
201 case X86::VPCMPBZ256rri:
209 unsigned KMOVSize = 0;
224 return KMOVSize < MaskBits;
228 switch (
MI.getOpcode()) {
233 return MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
240 switch (
MI.getOpcode()) {
241 case X86::VPCMPEQDrr:
242 return !Is256Bit &&
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
243 case X86::VPCMPEQDYrr:
244 return MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
251 bool IsZero,
bool Is256Bit,
268 case X86::VBLENDVPSrrr:
270 case X86::VMOVAPSZ128rrk:
271 case X86::VMOVUPSZ128rrk:
272 case X86::VMOVDQA32Z128rrk:
273 case X86::VMOVDQU32Z128rrk:
278 case X86::VBLENDVPSYrrr:
280 case X86::VMOVAPSZ256rrk:
281 case X86::VMOVUPSZ256rrk:
282 case X86::VMOVDQA32Z256rrk:
283 case X86::VMOVDQU32Z256rrk:
288 case X86::VBLENDVPDrrr:
290 case X86::VMOVAPDZ128rrk:
291 case X86::VMOVUPDZ128rrk:
292 case X86::VMOVDQA64Z128rrk:
293 case X86::VMOVDQU64Z128rrk:
298 case X86::VBLENDVPDYrrr:
300 case X86::VMOVAPDZ256rrk:
301 case X86::VMOVUPDZ256rrk:
302 case X86::VMOVDQA64Z256rrk:
303 case X86::VMOVDQU64Z256rrk:
308 case X86::VPBLENDVBrrr:
309 return UseOpc == X86::VMOVDQU8Z128rrk;
310 case X86::VPBLENDVBYrrr:
311 return UseOpc == X86::VMOVDQU8Z256rrk;
335 unsigned Opc =
MI.getOpcode();
336 bool IsSignMaskCmp =
Opc == X86::VPCMPBZ128rri ||
Opc == X86::VPCMPBZ256rri ||
337 Opc == X86::VPCMPDZ128rri ||
Opc == X86::VPCMPDZ256rri ||
338 Opc == X86::VPCMPQZ128rri ||
Opc == X86::VPCMPQZ256rri;
339 if (!IsSignMaskCmp &&
Opc != X86::VPMOVD2MZ128kr &&
340 Opc != X86::VPMOVD2MZ256kr &&
Opc != X86::VPMOVQ2MZ128kr &&
341 Opc != X86::VPMOVQ2MZ256kr &&
Opc != X86::VPMOVB2MZ128kr &&
342 Opc != X86::VPMOVB2MZ256kr)
349 Register SrcVecReg =
MI.getOperand(1).getReg();
351 bool ConstantDefOnlyFeedsCmp =
false;
354 int64_t Pred =
MI.getOperand(3).getImm();
356 if (Pred != 5 && Pred != 6)
358 Register ConstantReg =
MI.getOperand(2).getReg();
359 bool Is256Bit =
Opc == X86::VPCMPBZ256rri ||
Opc == X86::VPCMPDZ256rri ||
360 Opc == X86::VPCMPQZ256rri;
368 ConstantDefOnlyFeedsCmp = !
TRI->regsOverlap(ConstantReg, SrcVecReg);
372 if (
UseMI.readsRegister(ConstantReg,
TRI)) {
373 ConstantDefOnlyFeedsCmp =
false;
378 unsigned MovMskOpc = 0;
379 unsigned BlendOpc = 0;
381 case X86::VPCMPDZ128rri:
382 case X86::VPMOVD2MZ128kr:
383 MovMskOpc = X86::VMOVMSKPSrr;
384 BlendOpc = X86::VBLENDVPSrrr;
386 case X86::VPCMPDZ256rri:
387 case X86::VPMOVD2MZ256kr:
388 MovMskOpc = X86::VMOVMSKPSYrr;
389 BlendOpc = X86::VBLENDVPSYrrr;
391 case X86::VPCMPQZ128rri:
392 case X86::VPMOVQ2MZ128kr:
393 MovMskOpc = X86::VMOVMSKPDrr;
394 BlendOpc = X86::VBLENDVPDrrr;
396 case X86::VPCMPQZ256rri:
397 case X86::VPMOVQ2MZ256kr:
398 MovMskOpc = X86::VMOVMSKPDYrr;
399 BlendOpc = X86::VBLENDVPDYrrr;
401 case X86::VPCMPBZ128rri:
402 case X86::VPMOVB2MZ128kr:
403 MovMskOpc = X86::VPMOVMSKBrr;
404 BlendOpc = X86::VPBLENDVBrrr;
406 case X86::VPCMPBZ256rri:
407 case X86::VPMOVB2MZ256kr:
408 MovMskOpc = X86::VPMOVMSKBYrr;
409 BlendOpc = X86::VPBLENDVBYrrr;
420 if (CurMI.readsRegister(MaskReg,
TRI)) {
421 if (KMovMI || BlendMI)
424 unsigned UseOpc = CurMI.getOpcode();
425 bool IsKMOV = UseOpc == X86::KMOVBrk || UseOpc == X86::KMOVWrk ||
426 UseOpc == X86::KMOVDrk;
428 if (IsKMOV && CurMI.getOperand(1).getReg() == MaskReg &&
435 CurMI.getOperand(2).getReg() == MaskReg &&
437 checkPredicate(BlendOpc, &ST)) {
444 if (CurMI.modifiesRegister(MaskReg,
TRI)) {
445 if (!KMovMI && !BlendMI)
455 if (!KMovMI && !BlendMI)
461 if (IsSignMaskCmp && KMovMI) {
464 MBB.computeRegisterLiveness(
489 int64_t ComplementMask =
491 unsigned ComplementOpc =
494 : (
isInt<8>(ComplementMask) ? X86::XOR32ri8 : X86::XOR32ri);
498 if (MovMskBits != 32) {
499 MIB.addImm(ComplementMask);
500 MIB->findRegisterDefOperand(X86::EFLAGS,
TRI)->setIsDead();
504 }
else if (BlendMI) {
522 assert(NewMI &&
"Expected a compressed instruction");
525 if (ConstantDefOnlyFeedsCmp &&
MI.getOperand(2).isKill())
547 auto IsRedundantNewDataDest = [&](
unsigned &
Opc) {
555 X86::isCFCMOVCC(
MI.getOpcode()))
562 if (!
Desc.isCommutable() ||
Desc.getNumOperands() < 3 ||
563 !
MI.getOperand(2).isReg() ||
MI.getOperand(2).getReg() != Reg0)
566 ST.getInstrInfo()->commuteInstruction(
MI,
false, 1, 2);
567 Opc =
MI.getOpcode();
582 unsigned Opc =
MI.getOpcode();
583 bool IsSetZUCCm =
Opc == X86::SETZUCCm;
587 bool IsNDLike = IsND ||
Opc == X86::MOVBE32rr ||
Opc == X86::MOVBE64rr;
588 bool IsRedundantNDD = IsNDLike ? IsRedundantNewDataDest(
Opc) :
false;
590 auto GetCompressedOpc = [&](
unsigned Opc) ->
unsigned {
603 if (IsRedundantNDD) {
613 if (
MI.definesRegister(Super,
nullptr))
614 IsRedundantNDD =
false;
622 "Unexpected NDD instruction with relocation!");
623 }
else if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND ||
624 Opc == X86::ADD32rr_ND ||
Opc == X86::ADD64rr_ND) {
629 MI.registerDefIsDead(X86::EFLAGS,
nullptr)) {
632 bool Is32BitReg =
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD32rr_ND;
634 ST.getInstrInfo()->get(Is32BitReg ? X86::LEA64_32r : X86::LEA64r);
640 if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND)
647 MI.removeFromParent();
654 unsigned NewOpc = IsRedundantNDD
656 : ((IsNDLike && ST.hasNF() &&
657 MI.registerDefIsDead(X86::EFLAGS,
nullptr))
659 : GetCompressedOpc(
Opc));
666 "Unexpected to compress NF instructions without ND.");
668 const MCInstrDesc &NewDesc = ST.getInstrInfo()->get(NewOpc);
681 "Unknown EVEX2EVEX compression");
686 MI.setAsmPrinterFlag(AsmComment);
688 MI.tieOperands(0, 1);
697 static std::atomic<bool> TableChecked(
false);
698 if (!TableChecked.load(std::memory_order_relaxed)) {
700 "X86CompressEVEXTable is not sorted!");
701 TableChecked.store(
true, std::memory_order_relaxed);
705 if (!ST.hasAVX512() && !ST.hasEGPR() && !ST.hasNDD() && !ST.hasZU())
718 MI->eraseFromParent();
729 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 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 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.
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 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 >