[llvm] Resolve fixme: create cld only when needed (PR #82415)

via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 20 16:40:09 PST 2024


https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/82415

>From 37ab03ec8e1a460733c35a6f84c2f922a99349e2 Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Tue, 20 Feb 2024 15:22:01 -0500
Subject: [PATCH] [X86] Resolve FIXME: Create cld only when needed

---
 llvm/lib/Target/X86/X86FrameLowering.cpp | 30 ++++++++++++++++++++----
 llvm/test/CodeGen/X86/cld.ll             | 28 ++++++++++++++++++++++
 2 files changed, 54 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/cld.ll

diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index be416fb0db0695..b235942d66c26f 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -2194,13 +2194,35 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
   // flag (DF in EFLAGS register). Clear this flag by creating "cld" instruction
   // in each prologue of interrupt handler function.
   //
-  // FIXME: Create "cld" instruction only in these cases:
+  // 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.
   //
-  if (Fn.getCallingConv() == CallingConv::X86_INTR)
-    BuildMI(MBB, MBBI, DL, TII.get(X86::CLD))
-        .setMIFlag(MachineInstr::FrameSetup);
+  if (Fn.getCallingConv() == CallingConv::X86_INTR) {
+    bool NeedsCLD = false;
+
+    // Check if the function calls another function.
+    for (const BasicBlock &BB : Fn) {
+      for (const Instruction &I : BB) {
+        if (isa<CallInst>(I)) {
+          NeedsCLD = true;
+          break;
+        }
+
+        // Check for rep opcode.
+        unsigned Opcode = I.getOpcode();
+        if (X86::REP_MOVSB_32 <= Opcode && Opcode <= X86::REP_STOSW_64) {
+          NeedsCLD = true;
+          break;
+        }
+      }
+    }
+
+    if (NeedsCLD) {
+      BuildMI(MBB, MBBI, DL, TII.get(X86::CLD))
+          .setMIFlag(MachineInstr::FrameSetup);
+    }
+  }
 
   // At this point we know if the function has WinCFI or not.
   MF.setHasWinCFI(HasWinCFI);
diff --git a/llvm/test/CodeGen/X86/cld.ll b/llvm/test/CodeGen/X86/cld.ll
new file mode 100644
index 00000000000000..45f62fc1185f4a
--- /dev/null
+++ b/llvm/test/CodeGen/X86/cld.ll
@@ -0,0 +1,28 @@
+; RUN: opt < %s -x86-flags-copy-lowering -S | FileCheck %s
+; Test that the 'cld' instruction is created only when needed.
+
+define void @test1() {
+; CHECK-LABEL: @test1
+; CHECK-NOT: call void asm sideeffect "cld"
+  ret void
+}
+
+define void @test2() {
+; CHECK-LABEL: @test2
+; CHECK: call void asm sideeffect "cld"
+  call void @external()
+  ret void
+}
+
+declare void @external()
+
+define void @test3() {
+; CHECK-LABEL: @test3
+; CHECK: call void asm sideeffect "cld"
+  %1 = alloca [100 x i8], align 16
+  %2 = getelementptr inbounds [100 x i8], [100 x i8]* %1, i64 0, i64 0
+  call void @llvm.memset.p0i8.i64(i8* nonnull align 16 dereferenceable(100) %2, i8 0, i64 100, i1 false)
+  ret void
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #1



More information about the llvm-commits mailing list