Skip to content

Commit bdc7840

Browse files
committed
[X86][CodeGen] Share code between CompressEVEX pass and ND2NonND transform, NFCI
1 parent c38b1fa commit bdc7840

File tree

5 files changed

+115
-86
lines changed

5 files changed

+115
-86
lines changed

llvm/lib/Target/X86/X86CompressEVEX.cpp

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -174,29 +174,6 @@ static bool performCustomAdjustments(MachineInstr &MI, unsigned NewOpc) {
174174
return true;
175175
}
176176

177-
static bool isRedundantNewDataDest(MachineInstr &MI, const X86Subtarget &ST) {
178-
// $rbx = ADD64rr_ND $rbx, $rax / $rbx = ADD64rr_ND $rax, $rbx
179-
// ->
180-
// $rbx = ADD64rr $rbx, $rax
181-
const MCInstrDesc &Desc = MI.getDesc();
182-
Register Reg0 = MI.getOperand(0).getReg();
183-
const MachineOperand &Op1 = MI.getOperand(1);
184-
if (!Op1.isReg() || X86::getFirstAddrOperandIdx(MI) == 1 ||
185-
X86::isCFCMOVCC(MI.getOpcode()))
186-
return false;
187-
Register Reg1 = Op1.getReg();
188-
if (Reg1 == Reg0)
189-
return true;
190-
191-
// Op1 and Op2 may be commutable for ND instructions.
192-
if (!Desc.isCommutable() || Desc.getNumOperands() < 3 ||
193-
!MI.getOperand(2).isReg() || MI.getOperand(2).getReg() != Reg0)
194-
return false;
195-
// Opcode may change after commute, e.g. SHRD -> SHLD
196-
ST.getInstrInfo()->commuteInstruction(MI, false, 1, 2);
197-
return true;
198-
}
199-
200177
static bool CompressEVEXImpl(MachineInstr &MI, const X86Subtarget &ST) {
201178
uint64_t TSFlags = MI.getDesc().TSFlags;
202179

@@ -208,6 +185,30 @@ static bool CompressEVEXImpl(MachineInstr &MI, const X86Subtarget &ST) {
208185
if (TSFlags & (X86II::EVEX_K | X86II::EVEX_L2))
209186
return false;
210187

188+
auto IsRedundantNewDataDest = [&](unsigned &Opc) {
189+
// $rbx = ADD64rr_ND $rbx, $rax / $rbx = ADD64rr_ND $rax, $rbx
190+
// ->
191+
// $rbx = ADD64rr $rbx, $rax
192+
const MCInstrDesc &Desc = MI.getDesc();
193+
Register Reg0 = MI.getOperand(0).getReg();
194+
const MachineOperand &Op1 = MI.getOperand(1);
195+
if (!Op1.isReg() || X86::getFirstAddrOperandIdx(MI) == 1 ||
196+
X86::isCFCMOVCC(MI.getOpcode()))
197+
return false;
198+
Register Reg1 = Op1.getReg();
199+
if (Reg1 == Reg0)
200+
return true;
201+
202+
// Op1 and Op2 may be commutable for ND instructions.
203+
if (!Desc.isCommutable() || Desc.getNumOperands() < 3 ||
204+
!MI.getOperand(2).isReg() || MI.getOperand(2).getReg() != Reg0)
205+
return false;
206+
// Opcode may change after commute, e.g. SHRD -> SHLD
207+
ST.getInstrInfo()->commuteInstruction(MI, false, 1, 2);
208+
Opc = MI.getOpcode();
209+
return true;
210+
};
211+
211212
// EVEX_B has several meanings.
212213
// AVX512:
213214
// register form: rounding control or SAE
@@ -218,40 +219,36 @@ static bool CompressEVEXImpl(MachineInstr &MI, const X86Subtarget &ST) {
218219
//
219220
// For AVX512 cases, EVEX prefix is needed in order to carry this information
220221
// thus preventing the transformation to VEX encoding.
221-
unsigned Opc = MI.getOpcode();
222222
bool IsND = X86II::hasNewDataDest(TSFlags);
223223
if (TSFlags & X86II::EVEX_B && !IsND)
224224
return false;
225+
unsigned Opc = MI.getOpcode();
225226
// MOVBE*rr is special because it has semantic of NDD but not set EVEX_B.
226227
bool IsNDLike = IsND || Opc == X86::MOVBE32rr || Opc == X86::MOVBE64rr;
227-
bool IsRedundantNDD = IsNDLike ? isRedundantNewDataDest(MI, ST) : false;
228-
// NonNF -> NF only if it's not a compressible NDD instruction and eflags is
229-
// dead.
230-
unsigned NFOpc = (ST.hasNF() && !IsRedundantNDD &&
231-
MI.registerDefIsDead(X86::EFLAGS, /*TRI=*/nullptr))
232-
? X86::getNFVariant(Opc)
233-
: 0U;
234-
if (IsNDLike && !IsRedundantNDD && !NFOpc)
235-
return false;
228+
bool IsRedundantNDD = IsNDLike ? IsRedundantNewDataDest(Opc) : false;
236229

237-
unsigned NewOpc = NFOpc;
238-
if (!NewOpc) {
230+
auto GetCompressedOpc = [&](unsigned Opc) -> unsigned {
239231
ArrayRef<X86TableEntry> Table = ArrayRef(X86CompressEVEXTable);
240-
241-
Opc = MI.getOpcode();
242232
const auto I = llvm::lower_bound(Table, Opc);
243-
if (I == Table.end() || I->OldOpc != Opc) {
244-
assert(!IsNDLike && "Missing entry for ND-like instruction");
245-
return false;
246-
}
247-
248-
if (!IsNDLike) {
249-
if (usesExtendedRegister(MI) || !checkPredicate(I->NewOpc, &ST) ||
250-
!performCustomAdjustments(MI, I->NewOpc))
251-
return false;
252-
}
253-
NewOpc = I->NewOpc;
254-
}
233+
if (I == Table.end() || I->OldOpc != Opc)
234+
return 0;
235+
236+
if (usesExtendedRegister(MI) || !checkPredicate(I->NewOpc, &ST) ||
237+
!performCustomAdjustments(MI, I->NewOpc))
238+
return 0;
239+
return I->NewOpc;
240+
};
241+
// NonNF -> NF only if it's not a compressible NDD instruction and eflags is
242+
// dead.
243+
unsigned NewOpc = IsRedundantNDD
244+
? X86::getNonNDVariant(Opc)
245+
: ((IsNDLike && ST.hasNF() &&
246+
MI.registerDefIsDead(X86::EFLAGS, /*TRI=*/nullptr))
247+
? X86::getNFVariant(Opc)
248+
: GetCompressedOpc(Opc));
249+
250+
if (!NewOpc)
251+
return false;
255252

256253
const MCInstrDesc &NewDesc = ST.getInstrInfo()->get(NewOpc);
257254
MI.setDesc(NewDesc);

llvm/lib/Target/X86/X86InstrInfo.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3224,18 +3224,18 @@ int X86::getCCMPCondFlagsFromCondCode(X86::CondCode CC) {
32243224
#define GET_X86_NF_TRANSFORM_TABLE
32253225
#define GET_X86_ND2NONND_TABLE
32263226
#include "X86GenInstrMapping.inc"
3227-
unsigned X86::getNFVariant(unsigned Opc) {
3228-
ArrayRef<X86TableEntry> Table = ArrayRef(X86NFTransformTable);
3227+
3228+
static unsigned getNewOpcFromTable(ArrayRef<X86TableEntry> Table,
3229+
unsigned Opc) {
32293230
const auto I = llvm::lower_bound(Table, Opc);
32303231
return (I == Table.end() || I->OldOpc != Opc) ? 0U : I->NewOpc;
32313232
}
3233+
unsigned X86::getNFVariant(unsigned Opc) {
3234+
return getNewOpcFromTable(X86NFTransformTable, Opc);
3235+
}
32323236

3233-
static unsigned getNonNDVariant(unsigned Opc, const X86Subtarget &STI) {
3234-
if (!STI.hasNDD())
3235-
return 0U;
3236-
ArrayRef<X86TableEntry> Table = ArrayRef(X86ND2NonNDTable);
3237-
const auto I = llvm::lower_bound(Table, Opc);
3238-
return (I == Table.end() || I->OldOpc != Opc) ? 0U : I->NewOpc;
3237+
unsigned X86::getNonNDVariant(unsigned Opc) {
3238+
return getNewOpcFromTable(X86ND2NonNDTable, Opc);
32393239
}
32403240

32413241
/// Return the inverse of the specified condition,
@@ -7393,7 +7393,7 @@ MachineInstr *X86InstrInfo::foldMemoryOperandImpl(
73937393
// replacing the *two* registers with the memory location.
73947394
//
73957395
// Utilize the mapping NonNDD -> RMW for the NDD variant.
7396-
unsigned NonNDOpc = getNonNDVariant(Opc, Subtarget);
7396+
unsigned NonNDOpc = Subtarget.hasNDD() ? X86::getNonNDVariant(Opc) : 0U;
73977397
const X86FoldTableEntry *I =
73987398
IsTwoAddr ? lookupTwoAddrFoldTable(NonNDOpc ? NonNDOpc : Opc)
73997399
: lookupFoldTable(Opc, OpNum);
@@ -7514,7 +7514,8 @@ MachineInstr *X86InstrInfo::foldMemoryOperandImpl(
75147514
switch (Opc) {
75157515
default:
75167516
// NDD can be folded into RMW though its Op0 and Op1 are not tied.
7517-
return getNonNDVariant(Opc, Subtarget) ? Impl() : nullptr;
7517+
return (Subtarget.hasNDD() ? X86::getNonNDVariant(Opc) : 0U) ? Impl()
7518+
: nullptr;
75187519
case X86::TEST8rr:
75197520
NewOpc = X86::CMP8ri;
75207521
RCSize = 1;

llvm/lib/Target/X86/X86InstrInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ int getCCMPCondFlagsFromCondCode(CondCode CC);
8080
// Get the opcode of corresponding NF variant.
8181
unsigned getNFVariant(unsigned Opc);
8282

83+
// Get the opcode of corresponding NonND variant.
84+
unsigned getNonNDVariant(unsigned Opc);
85+
8386
/// GetOppositeBranchCondition - Return the inverse of the specified cond,
8487
/// e.g. turning COND_E to COND_NE.
8588
CondCode GetOppositeBranchCondition(CondCode CC);

llvm/utils/TableGen/X86InstrMappingEmitter.cpp

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,6 @@ using namespace X86Disassembler;
2525

2626
namespace {
2727

28-
const std::map<StringRef, StringRef> ManualMap = {
29-
#define ENTRY(OLD, NEW) {#OLD, #NEW},
30-
#include "X86ManualCompressEVEXTables.def"
31-
};
32-
const std::set<StringRef> NoCompressSet = {
33-
#define NOCOMP(INSN) #INSN,
34-
#include "X86ManualCompressEVEXTables.def"
35-
};
36-
3728
class X86InstrMappingEmitter {
3829
RecordKeeper &Records;
3930
CodeGenTarget Target;
@@ -176,6 +167,16 @@ static bool isInteresting(const Record *Rec) {
176167

177168
void X86InstrMappingEmitter::emitCompressEVEXTable(
178169
ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) {
170+
171+
const std::map<StringRef, StringRef> ManualMap = {
172+
#define ENTRY(OLD, NEW) {#OLD, #NEW},
173+
#include "X86ManualInstrMapping.def"
174+
};
175+
const std::set<StringRef> NoCompressSet = {
176+
#define NOCOMP(INSN) #INSN,
177+
#include "X86ManualInstrMapping.def"
178+
};
179+
179180
for (const CodeGenInstruction *Inst : Insts) {
180181
const Record *Rec = Inst->TheDef;
181182
StringRef Name = Rec->getName();
@@ -219,13 +220,10 @@ void X86InstrMappingEmitter::emitCompressEVEXTable(
219220
} else if (Name.ends_with("_EVEX")) {
220221
if (auto *NewRec = Records.getDef(Name.drop_back(5)))
221222
NewInst = &Target.getInstruction(NewRec);
222-
} else if (Name.ends_with("_ND")) {
223-
if (auto *NewRec = Records.getDef(Name.drop_back(3))) {
224-
auto &TempInst = Target.getInstruction(NewRec);
225-
if (isRegisterOperand(TempInst.Operands[0].Rec))
226-
NewInst = &TempInst;
227-
}
228-
} else {
223+
} else if (Name.ends_with("_ND"))
224+
// Leave it to ND2NONND table.
225+
continue;
226+
else {
229227
// For each pre-compression instruction look for a match in the
230228
// appropriate vector (instructions with the same opcode) using function
231229
// object IsMatch.
@@ -301,11 +299,31 @@ void X86InstrMappingEmitter::emitNFTransformTable(
301299

302300
void X86InstrMappingEmitter::emitND2NonNDTable(
303301
ArrayRef<const CodeGenInstruction *> Insts, raw_ostream &OS) {
302+
303+
const std::map<StringRef, StringRef> ManualMap = {
304+
#define ENTRY_ND(OLD, NEW) {#OLD, #NEW},
305+
#include "X86ManualInstrMapping.def"
306+
};
307+
const std::set<StringRef> NoCompressSet = {
308+
#define NOCOMP_ND(INSN) #INSN,
309+
#include "X86ManualInstrMapping.def"
310+
};
311+
304312
std::vector<Entry> Table;
305313
for (const CodeGenInstruction *Inst : Insts) {
306314
const Record *Rec = Inst->TheDef;
307315
StringRef Name = Rec->getName();
308-
if (!isInteresting(Rec) || !Name.ends_with("_ND"))
316+
if (!isInteresting(Rec) || NoCompressSet.find(Name) != NoCompressSet.end())
317+
continue;
318+
if (ManualMap.find(Name) != ManualMap.end()) {
319+
auto *NewRec = Records.getDef(ManualMap.at(Rec->getName()));
320+
assert(NewRec && "Instruction not found!");
321+
auto &NewInst = Target.getInstruction(NewRec);
322+
Table.push_back(std::pair(Inst, &NewInst));
323+
continue;
324+
}
325+
326+
if (!Name.ends_with("_ND"))
309327
continue;
310328
auto *NewRec = Records.getDef(Name.drop_back(3));
311329
if (!NewRec)

llvm/utils/TableGen/X86ManualCompressEVEXTables.def renamed to llvm/utils/TableGen/X86ManualInstrMapping.def

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,6 @@ NOCOMP(VPSRAQZ256ri)
4848
NOCOMP(VPSRAQZ256rm)
4949
NOCOMP(VPSRAQZ256rr)
5050
NOCOMP(VSCALEFPSZ256rm)
51-
// When condition evaluates to false, the destination register is zeroed for
52-
// nonNDD CFCMOV but not for NDD CFCMOV.
53-
NOCOMP(CFCMOV16rm_ND)
54-
NOCOMP(CFCMOV16rr_ND)
55-
NOCOMP(CFCMOV32rm_ND)
56-
NOCOMP(CFCMOV32rr_ND)
57-
NOCOMP(CFCMOV64rm_ND)
58-
NOCOMP(CFCMOV64rr_ND)
5951
#undef NOCOMP
6052

6153
#ifndef ENTRY
@@ -336,6 +328,24 @@ ENTRY(VBROADCASTSDZ256rm, VBROADCASTSDYrm)
336328
ENTRY(VBROADCASTSDZ256rr, VBROADCASTSDYrr)
337329
ENTRY(VPBROADCASTQZ256rm, VPBROADCASTQYrm)
338330
ENTRY(VPBROADCASTQZ256rr, VPBROADCASTQYrr)
339-
ENTRY(MOVBE32rr, BSWAP32r)
340-
ENTRY(MOVBE64rr, BSWAP64r)
341331
#undef ENTRY
332+
333+
#ifndef NOCOMP_ND
334+
#define NOCOMP_ND(INSN)
335+
#endif
336+
// When condition evaluates to false, the destination register is zeroed for
337+
// nonNDD CFCMOV but not for NDD CFCMOV.
338+
NOCOMP_ND(CFCMOV16rm_ND)
339+
NOCOMP_ND(CFCMOV16rr_ND)
340+
NOCOMP_ND(CFCMOV32rm_ND)
341+
NOCOMP_ND(CFCMOV32rr_ND)
342+
NOCOMP_ND(CFCMOV64rm_ND)
343+
NOCOMP_ND(CFCMOV64rr_ND)
344+
#undef NOCOMP_ND
345+
346+
#ifndef ENTRY_ND
347+
#define ENTRY_ND(OLD, NEW)
348+
#endif
349+
ENTRY_ND(MOVBE32rr, BSWAP32r)
350+
ENTRY_ND(MOVBE64rr, BSWAP64r)
351+
#undef ENTRY_ND

0 commit comments

Comments
 (0)