[llvm] [X86] Refine CLD insertion to trigger only when the direction flag is used (PR #86557)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 25 11:26:03 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: AtariDreams (AtariDreams)
<details>
<summary>Changes</summary>
=Rather than try to update every instruction that is affected by the direction flag, we could instead use findRegisterUseOperand.
---
Full diff: https://github.com/llvm/llvm-project/pull/86557.diff
1 Files Affected:
- (modified) llvm/lib/Target/X86/X86FrameLowering.cpp (+28-39)
``````````diff
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index d914e1b61ab075..9302d0d2e27573 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -1418,34 +1418,6 @@ bool X86FrameLowering::needsDwarfCFI(const MachineFunction &MF) const {
return !isWin64Prologue(MF) && MF.needsFrameMoves();
}
-/// Return true if an opcode is part of the REP group of instructions
-static bool isOpcodeRep(unsigned Opcode) {
- switch (Opcode) {
- case X86::REPNE_PREFIX:
- case X86::REP_MOVSB_32:
- case X86::REP_MOVSB_64:
- case X86::REP_MOVSD_32:
- case X86::REP_MOVSD_64:
- case X86::REP_MOVSQ_32:
- case X86::REP_MOVSQ_64:
- case X86::REP_MOVSW_32:
- case X86::REP_MOVSW_64:
- case X86::REP_PREFIX:
- case X86::REP_STOSB_32:
- case X86::REP_STOSB_64:
- case X86::REP_STOSD_32:
- case X86::REP_STOSD_64:
- case X86::REP_STOSQ_32:
- case X86::REP_STOSQ_64:
- case X86::REP_STOSW_32:
- case X86::REP_STOSW_64:
- return true;
- default:
- break;
- }
- return false;
-}
-
/// emitPrologue - Push callee-saved registers onto the stack, which
/// automatically adjust the stack pointer. Adjust the stack pointer to allocate
/// space for local variables. Also emit labels used by the exception handler to
@@ -2225,33 +2197,50 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
// Create "cld" instruction only in these cases:
// 1. The interrupt handling function uses any of the "rep" instructions.
// 2. Interrupt handling function calls another function.
- // 3. If there are any inline asm blocks, as we do not know what they do
+ // 3. If DF is clobbered by any instruction.
//
- // TODO: We should also emit cld if we detect the use of std, but as of now,
- // the compiler does not even emit that instruction or even define it, so in
- // practice, this would only happen with inline asm, which we cover anyway.
if (Fn.getCallingConv() == CallingConv::X86_INTR) {
bool NeedsCLD = false;
for (const MachineBasicBlock &B : MF) {
for (const MachineInstr &MI : B) {
- if (MI.isCall()) {
+ if (MI.isInlineAsm()) {
NeedsCLD = true;
break;
}
- if (isOpcodeRep(MI.getOpcode())) {
- NeedsCLD = true;
+ if (MI.findRegisterDefOperand(X86::DF)) {
+ // We do not need CLD because we clobber DF anyway before the flag is
+ // even used.
+ // FIXME: Is this even possible? Only cld and std can do this.
+ NeedsCLD = false;
break;
}
- if (MI.isInlineAsm()) {
- // TODO: Parse asm for rep instructions or call sites?
- // For now, let's play it safe and emit a cld instruction
- // just in case.
+ if (MI.isCall()) {
NeedsCLD = true;
break;
}
+
+ if (MI.findRegisterUseOperand(X86::DF)) {
+ // Because eflags being pushed and popped save the instruction, it
+ // counts as a use, but we ignore them because the purpose is to
+ // preserve eflags.
+ switch (MI.getOpcode()) {
+ case X86::PUSHF16:
+ case X86::PUSHF32:
+ case X86::PUSHF64:
+ case X86::PUSHFS16:
+ case X86::PUSHFS32:
+ case X86::PUSHFS64:
+ break;
+ default:
+ NeedsCLD = true;
+ break;
+ }
+ if (NeedsCLD)
+ break;
+ }
}
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/86557
More information about the llvm-commits
mailing list