Index: llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp =================================================================== --- llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -328,6 +328,89 @@ return FIK != X86::FirstMacroFusionInstKind::Invalid; } +/// X86 can reduce the bytes of NOP by padding instructions with prefixes to +/// get a better peformance in some cases. Here, we determine which prefix is +/// the most suitable. +/// +/// If the instruction has a segment override prefix, use the existing one. +/// If the target is 64-bit, use the CS. +/// If the target is 32-bit, +/// - If the instruction has a ESP/EBP base register, use SS. +/// - Otherwise use DS. +static uint8_t DeterminePaddingPrefix(const MCInst &Inst, + const MCInstrInfo &MCII, + const MCSubtargetInfo &STI) { + assert((STI.hasFeature(X86::Mode32Bit) || STI.hasFeature(X86::Mode64Bit)) && + "Prefixes can be added only in 32-bit or 64-bit mode."); + unsigned Opcode = Inst.getOpcode(); + const MCInstrDesc &Desc = MCII.get(Opcode); + uint64_t TSFlags = Desc.TSFlags; + + unsigned CurOp = X86II::getOperandBias(Desc); + + // Determine where the memory operand starts, if present. + int MemoryOperand = X86II::getMemoryOperandNo(TSFlags); + if (MemoryOperand != -1) + MemoryOperand += CurOp; + + unsigned SegmentReg = 0; + if (MemoryOperand >= 0) { + // Check for explicit segment override on memory operand. + SegmentReg = Inst.getOperand(MemoryOperand + X86::AddrSegmentReg).getReg(); + } + + uint64_t Form = TSFlags & X86II::FormMask; + switch (Form) { + default: + break; + case X86II::RawFrmDstSrc: { + // Check segment override opcode prefix as needed (not for %ds). + if (Inst.getOperand(2).getReg() != X86::DS) + SegmentReg = Inst.getOperand(2).getReg(); + break; + } + case X86II::RawFrmSrc: { + // Check segment override opcode prefix as needed (not for %ds). + if (Inst.getOperand(1).getReg() != X86::DS) + SegmentReg = Inst.getOperand(1).getReg(); + break; + } + case X86II::RawFrmMemOffs: { + // Check segment override opcode prefix as needed. + SegmentReg = Inst.getOperand(1).getReg(); + break; + } + } + + switch (SegmentReg) { + case 0: + break; + case X86::CS: + return X86::CS_Encoding; + case X86::DS: + return X86::DS_Encoding; + case X86::ES: + return X86::ES_Encoding; + case X86::FS: + return X86::FS_Encoding; + case X86::GS: + return X86::GS_Encoding; + case X86::SS: + return X86::SS_Encoding; + } + + if (STI.hasFeature(X86::Mode64Bit)) + return X86::CS_Encoding; + + if (MemoryOperand >= 0) { + unsigned BaseRegNum = MemoryOperand + X86::AddrBaseReg; + unsigned BaseReg = Inst.getOperand(BaseRegNum).getReg(); + if (BaseReg == X86::ESP || BaseReg == X86::EBP) + return X86::SS_Encoding; + } + return X86::DS_Encoding; +} + /// Check if the two instructions will be macro-fused on the target cpu. bool X86AsmBackend::isMacroFused(const MCInst &Cmp, const MCInst &Jcc) const { const MCInstrDesc &InstDesc = MCII->get(Jcc.getOpcode()); Index: llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h =================================================================== --- llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -383,6 +383,15 @@ AlignBranchRet = 1U << 4, AlignBranchIndirect = 1U << 5 }; + + enum EncodingOfSegmentOverridePrefix : uint8_t { + CS_Encoding = 0x2E, + DS_Encoding = 0x3E, + ES_Encoding = 0x26, + FS_Encoding = 0x64, + GS_Encoding = 0x65, + SS_Encoding = 0x36 + }; } // end namespace X86; /// X86II - This namespace holds all of the target specific flags that