Skip to content

Commit b3722de

Browse files
committed
[X86] Add a private member function determinePaddingPrefix for X86AsmBackend
Summary: X86 can reduce the bytes of NOP by padding instructions with prefixes to get a better peformance in some cases. So a private member function `determinePaddingPrefix` is added to determine which prefix is the most suitable. Reviewers: annita.zhang, reames, MaskRay, craig.topper, LuoYuanke, jyknight Reviewed By: reames Subscribers: llvm-commits, dexonsmith, hiraditya Tags: #llvm Differential Revision: https://reviews.llvm.org/D75357
1 parent 755c050 commit b3722de

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ class X86AsmBackend : public MCAsmBackend {
126126
X86AlignBranchKind AlignBranchType;
127127
Align AlignBoundary;
128128

129+
uint8_t determinePaddingPrefix(const MCInst &Inst) const;
130+
129131
bool isMacroFused(const MCInst &Cmp, const MCInst &Jcc) const;
130132

131133
bool needAlign(MCObjectStreamer &OS) const;
@@ -340,6 +342,83 @@ static bool isFirstMacroFusibleInst(const MCInst &Inst,
340342
return FIK != X86::FirstMacroFusionInstKind::Invalid;
341343
}
342344

345+
/// X86 can reduce the bytes of NOP by padding instructions with prefixes to
346+
/// get a better peformance in some cases. Here, we determine which prefix is
347+
/// the most suitable.
348+
///
349+
/// If the instruction has a segment override prefix, use the existing one.
350+
/// If the target is 64-bit, use the CS.
351+
/// If the target is 32-bit,
352+
/// - If the instruction has a ESP/EBP base register, use SS.
353+
/// - Otherwise use DS.
354+
uint8_t X86AsmBackend::determinePaddingPrefix(const MCInst &Inst) const {
355+
assert((STI.hasFeature(X86::Mode32Bit) || STI.hasFeature(X86::Mode64Bit)) &&
356+
"Prefixes can be added only in 32-bit or 64-bit mode.");
357+
const MCInstrDesc &Desc = MCII->get(Inst.getOpcode());
358+
uint64_t TSFlags = Desc.TSFlags;
359+
360+
// Determine where the memory operand starts, if present.
361+
int MemoryOperand = X86II::getMemoryOperandNo(TSFlags);
362+
if (MemoryOperand != -1)
363+
MemoryOperand += X86II::getOperandBias(Desc);
364+
365+
unsigned SegmentReg = 0;
366+
if (MemoryOperand >= 0) {
367+
// Check for explicit segment override on memory operand.
368+
SegmentReg = Inst.getOperand(MemoryOperand + X86::AddrSegmentReg).getReg();
369+
}
370+
371+
switch (TSFlags & X86II::FormMask) {
372+
default:
373+
break;
374+
case X86II::RawFrmDstSrc: {
375+
// Check segment override opcode prefix as needed (not for %ds).
376+
if (Inst.getOperand(2).getReg() != X86::DS)
377+
SegmentReg = Inst.getOperand(2).getReg();
378+
break;
379+
}
380+
case X86II::RawFrmSrc: {
381+
// Check segment override opcode prefix as needed (not for %ds).
382+
if (Inst.getOperand(1).getReg() != X86::DS)
383+
SegmentReg = Inst.getOperand(1).getReg();
384+
break;
385+
}
386+
case X86II::RawFrmMemOffs: {
387+
// Check segment override opcode prefix as needed.
388+
SegmentReg = Inst.getOperand(1).getReg();
389+
break;
390+
}
391+
}
392+
393+
switch (SegmentReg) {
394+
case 0:
395+
break;
396+
case X86::CS:
397+
return X86::CS_Encoding;
398+
case X86::DS:
399+
return X86::DS_Encoding;
400+
case X86::ES:
401+
return X86::ES_Encoding;
402+
case X86::FS:
403+
return X86::FS_Encoding;
404+
case X86::GS:
405+
return X86::GS_Encoding;
406+
case X86::SS:
407+
return X86::SS_Encoding;
408+
}
409+
410+
if (STI.hasFeature(X86::Mode64Bit))
411+
return X86::CS_Encoding;
412+
413+
if (MemoryOperand >= 0) {
414+
unsigned BaseRegNum = MemoryOperand + X86::AddrBaseReg;
415+
unsigned BaseReg = Inst.getOperand(BaseRegNum).getReg();
416+
if (BaseReg == X86::ESP || BaseReg == X86::EBP)
417+
return X86::SS_Encoding;
418+
}
419+
return X86::DS_Encoding;
420+
}
421+
343422
/// Check if the two instructions will be macro-fused on the target cpu.
344423
bool X86AsmBackend::isMacroFused(const MCInst &Cmp, const MCInst &Jcc) const {
345424
const MCInstrDesc &InstDesc = MCII->get(Jcc.getOpcode());

llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,16 @@ namespace X86 {
383383
AlignBranchRet = 1U << 4,
384384
AlignBranchIndirect = 1U << 5
385385
};
386+
387+
/// Defines the encoding values for segment override prefix.
388+
enum EncodingOfSegmentOverridePrefix : uint8_t {
389+
CS_Encoding = 0x2E,
390+
DS_Encoding = 0x3E,
391+
ES_Encoding = 0x26,
392+
FS_Encoding = 0x64,
393+
GS_Encoding = 0x65,
394+
SS_Encoding = 0x36
395+
};
386396
} // end namespace X86;
387397

388398
/// X86II - This namespace holds all of the target specific flags that

0 commit comments

Comments
 (0)