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)
189 auto IsRedundantNewDataDest = [&](
unsigned &
Opc) {
197 X86::isCFCMOVCC(
MI.getOpcode()))
204 if (!
Desc.isCommutable() ||
Desc.getNumOperands() < 3 ||
205 !
MI.getOperand(2).isReg() ||
MI.getOperand(2).getReg() != Reg0)
208 ST.getInstrInfo()->commuteInstruction(
MI,
false, 1, 2);
209 Opc =
MI.getOpcode();
226 unsigned Opc =
MI.getOpcode();
228 bool IsNDLike = IsND ||
Opc == X86::MOVBE32rr ||
Opc == X86::MOVBE64rr;
229 bool IsRedundantNDD = IsNDLike ? IsRedundantNewDataDest(
Opc) :
false;
231 auto GetCompressedOpc = [&](
unsigned Opc) ->
unsigned {
234 if (
I == Table.
end() ||
I->OldOpc !=
Opc)
244 if (IsRedundantNDD) {
254 if (
MI.definesRegister(Super,
nullptr))
255 IsRedundantNDD =
false;
263 "Unexpected NDD instruction with relocation!");
264 }
else if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND ||
265 Opc == X86::ADD32rr_ND ||
Opc == X86::ADD64rr_ND) {
270 MI.registerDefIsDead(X86::EFLAGS,
nullptr)) {
273 bool Is32BitReg =
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD32rr_ND;
275 ST.getInstrInfo()->get(Is32BitReg ? X86::LEA32r : X86::LEA64r);
281 if (
Opc == X86::ADD32ri_ND ||
Opc == X86::ADD64ri32_ND)
288 MI.removeFromParent();
295 unsigned NewOpc = IsRedundantNDD
297 : ((IsNDLike && ST.hasNF() &&
298 MI.registerDefIsDead(X86::EFLAGS,
nullptr))
300 : GetCompressedOpc(
Opc));
305 const MCInstrDesc &NewDesc = ST.getInstrInfo()->get(NewOpc);
318 "Unknown EVEX2EVEX compression");
323 MI.setAsmPrinterFlag(AsmComment);
325 MI.tieOperands(0, 1);
334 static std::atomic<bool> TableChecked(
false);
335 if (!TableChecked.load(std::memory_order_relaxed)) {
337 "X86CompressEVEXTable is not sorted!");
338 TableChecked.store(
true, std::memory_order_relaxed);
342 if (!
ST.hasAVX512() && !
ST.hasEGPR() && !
ST.hasNDD())
347 for (MachineBasicBlock &
MBB : MF) {
359 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)
cl::opt< bool > X86EnableAPXForRelocation
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),...
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.
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.
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.
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...
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...
ArrayRef(const T &OneElt) -> ArrayRef< T >