Skip to content

Commit 37ab03e

Browse files
committed
[X86] Resolve FIXME: Create cld only when needed
1 parent 98db8d0 commit 37ab03e

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,13 +2194,35 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
21942194
// flag (DF in EFLAGS register). Clear this flag by creating "cld" instruction
21952195
// in each prologue of interrupt handler function.
21962196
//
2197-
// FIXME: Create "cld" instruction only in these cases:
2197+
// Create "cld" instruction only in these cases:
21982198
// 1. The interrupt handling function uses any of the "rep" instructions.
21992199
// 2. Interrupt handling function calls another function.
22002200
//
2201-
if (Fn.getCallingConv() == CallingConv::X86_INTR)
2202-
BuildMI(MBB, MBBI, DL, TII.get(X86::CLD))
2203-
.setMIFlag(MachineInstr::FrameSetup);
2201+
if (Fn.getCallingConv() == CallingConv::X86_INTR) {
2202+
bool NeedsCLD = false;
2203+
2204+
// Check if the function calls another function.
2205+
for (const BasicBlock &BB : Fn) {
2206+
for (const Instruction &I : BB) {
2207+
if (isa<CallInst>(I)) {
2208+
NeedsCLD = true;
2209+
break;
2210+
}
2211+
2212+
// Check for rep opcode.
2213+
unsigned Opcode = I.getOpcode();
2214+
if (X86::REP_MOVSB_32 <= Opcode && Opcode <= X86::REP_STOSW_64) {
2215+
NeedsCLD = true;
2216+
break;
2217+
}
2218+
}
2219+
}
2220+
2221+
if (NeedsCLD) {
2222+
BuildMI(MBB, MBBI, DL, TII.get(X86::CLD))
2223+
.setMIFlag(MachineInstr::FrameSetup);
2224+
}
2225+
}
22042226

22052227
// At this point we know if the function has WinCFI or not.
22062228
MF.setHasWinCFI(HasWinCFI);

llvm/test/CodeGen/X86/cld.ll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; RUN: opt < %s -x86-flags-copy-lowering -S | FileCheck %s
2+
; Test that the 'cld' instruction is created only when needed.
3+
4+
define void @test1() {
5+
; CHECK-LABEL: @test1
6+
; CHECK-NOT: call void asm sideeffect "cld"
7+
ret void
8+
}
9+
10+
define void @test2() {
11+
; CHECK-LABEL: @test2
12+
; CHECK: call void asm sideeffect "cld"
13+
call void @external()
14+
ret void
15+
}
16+
17+
declare void @external()
18+
19+
define void @test3() {
20+
; CHECK-LABEL: @test3
21+
; CHECK: call void asm sideeffect "cld"
22+
%1 = alloca [100 x i8], align 16
23+
%2 = getelementptr inbounds [100 x i8], [100 x i8]* %1, i64 0, i64 0
24+
call void @llvm.memset.p0i8.i64(i8* nonnull align 16 dereferenceable(100) %2, i8 0, i64 100, i1 false)
25+
ret void
26+
}
27+
28+
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #1

0 commit comments

Comments
 (0)