Skip to content

Commit

Permalink
[X86] Teach fastisel to select calls to dllimport functions
Browse files Browse the repository at this point in the history
Summary:
Direct calls to dllimport functions are very common Windows. We should
add them to the -O0 fast path.

Reviewers: rafael

Subscribers: llvm-commits, hiraditya

Differential Revision: https://reviews.llvm.org/D36197

llvm-svn: 310152
  • Loading branch information
rnk committed Aug 5, 2017
1 parent a84a6c1 commit 7662d50
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 34 deletions.
22 changes: 14 additions & 8 deletions llvm/lib/Target/X86/X86FastISel.cpp
Expand Up @@ -1077,10 +1077,6 @@ bool X86FastISel::X86SelectCallAddress(const Value *V, X86AddressMode &AM) {
(AM.Base.Reg != 0 || AM.IndexReg != 0))
return false;

// Can't handle DLL Import.
if (GV->hasDLLImportStorageClass())
return false;

// Can't handle TLS.
if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
if (GVar->isThreadLocal())
Expand All @@ -1089,8 +1085,9 @@ bool X86FastISel::X86SelectCallAddress(const Value *V, X86AddressMode &AM) {
// Okay, we've committed to selecting this global. Set up the basic address.
AM.GV = GV;

// No ABI requires an extra load for anything other than DLLImport, which
// we rejected above. Return a direct reference to the global.
// Return a direct reference to the global. Fastisel can handle calls to
// functions that require loads, such as dllimport and nonlazybind
// functions.
if (Subtarget->isPICStyleRIPRel()) {
// Use rip-relative addressing if we can. Above we verified that the
// base and index registers are unused.
Expand Down Expand Up @@ -3455,19 +3452,28 @@ bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
} else {
// Direct call.
assert(GV && "Not a direct call");
unsigned CallOpc = Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32;

// See if we need any target-specific flags on the GV operand.
unsigned char OpFlags = Subtarget->classifyGlobalFunctionReference(GV);
// Ignore NonLazyBind attribute in FastISel
if (OpFlags == X86II::MO_GOTPCREL)
OpFlags = 0;

// This will be a direct call, or an indirect call through memory for
// NonLazyBind calls or dllimport calls.
bool NeedLoad = OpFlags == X86II::MO_DLLIMPORT;
unsigned CallOpc = NeedLoad
? (Is64Bit ? X86::CALL64m : X86::CALL32m)
: (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32);

MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(CallOpc));
if (NeedLoad)
MIB.addReg(Is64Bit ? X86::RIP : 0).addImm(1).addReg(0);
if (Symbol)
MIB.addSym(Symbol, OpFlags);
else
MIB.addGlobalAddress(GV, 0, OpFlags);
if (NeedLoad)
MIB.addReg(0);
}

// Add a register mask operand representing the call-preserved registers.
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/X86/X86Subtarget.cpp
Expand Up @@ -147,7 +147,12 @@ X86Subtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
if (TM.shouldAssumeDSOLocal(M, GV))
return X86II::MO_NO_FLAG;

assert(!isTargetCOFF());
if (isTargetCOFF()) {
assert(GV->hasDLLImportStorageClass() &&
"shouldAssumeDSOLocal gave inconsistent answer");
return X86II::MO_DLLIMPORT;
}

const Function *F = dyn_cast_or_null<Function>(GV);

if (isTargetELF()) {
Expand Down
5 changes: 2 additions & 3 deletions llvm/test/CodeGen/X86/dllimport-x86_64.ll
@@ -1,7 +1,8 @@
; RUN: llc -mtriple x86_64-pc-win32 < %s | FileCheck %s
; RUN: llc -mtriple x86_64-pc-mingw32 < %s | FileCheck %s
;
; RUN: llc -mtriple x86_64-pc-mingw32 -O0 < %s | FileCheck %s -check-prefix=FAST
; RUN: llc -mtriple x86_64-pc-mingw32 -O0 < %s | FileCheck %s
; RUN: llc -mtriple x86_64-pc-windows-msvc -O0 < %s | FileCheck %s
; PR6275
;
; RUN: opt -mtriple x86_64-pc-win32 -O3 -S < %s | FileCheck %s -check-prefix=OPT
Expand All @@ -23,8 +24,6 @@ declare void @dummy(...)

define void @use() nounwind {
; CHECK: callq *__imp_fun(%rip)
; FAST: movq __imp_fun(%rip), [[R:%[a-z]{3}]]
; FAST-NEXT: callq *[[R]]
call void @fun()

; CHECK: callq *__imp_inline1(%rip)
Expand Down
5 changes: 2 additions & 3 deletions llvm/test/CodeGen/X86/dllimport.ll
@@ -1,7 +1,8 @@
; RUN: llc -mtriple i386-pc-win32 < %s | FileCheck %s
; RUN: llc -mtriple i386-pc-mingw32 < %s | FileCheck %s
;
; RUN: llc -mtriple i386-pc-mingw32 -O0 < %s | FileCheck %s -check-prefix=FAST
; RUN: llc -mtriple i386-pc-mingw32 -O0 < %s | FileCheck %s
; RUN: llc -mtriple i386-pc-windows-msvc -O0 < %s | FileCheck %s
; PR6275
;
; RUN: opt -mtriple i386-pc-win32 -O3 -S < %s | FileCheck %s -check-prefix=OPT
Expand All @@ -27,8 +28,6 @@ declare void @dummy(...)

define void @use() nounwind {
; CHECK: calll *__imp__fun
; FAST: movl __imp__fun, [[R:%[a-z]{3}]]
; FAST-NEXT: calll *[[R]]
call void @fun()

; CHECK: calll *__imp__inline1
Expand Down
19 changes: 19 additions & 0 deletions llvm/test/CodeGen/X86/fast-isel-call-cleanup.ll
@@ -0,0 +1,19 @@
; RUN: llc -fast-isel -O0 -code-model=large -mcpu=generic -mtriple=x86_64-apple-darwin10 -relocation-model=pic < %s | FileCheck %s

; Check that fast-isel cleans up when it fails to lower a call instruction.
define void @fastiselcall() {
entry:
%call = call i32 @targetfn(i32 42)
ret void
; CHECK-LABEL: test5:
; Local value area is still there:
; CHECK: movl $42, {{%[a-z]+}}
; Fast-ISel's arg mov is not here:
; CHECK-NOT: movl $42, (%esp)
; SDag-ISel's arg mov:
; CHECK: movabsq $_targetfn, %[[REG:[^ ]*]]
; CHECK: movl $42, %edi
; CHECK: callq *%[[REG]]

}
declare i32 @targetfn(i32)
19 changes: 0 additions & 19 deletions llvm/test/CodeGen/X86/fast-isel-x86.ll
Expand Up @@ -88,22 +88,3 @@ entry:
; CHECK: addl $28
}
declare fastcc void @test4fastccsret(%struct.a* sret)


; Check that fast-isel cleans up when it fails to lower a call instruction.
define void @test5() {
entry:
%call = call i32 @test5dllimport(i32 42)
ret void
; CHECK-LABEL: test5:
; Local value area is still there:
; CHECK: movl $42, {{%[a-z]+}}
; Fast-ISel's arg push is not here:
; CHECK-NOT: movl $42, (%esp)
; SDag-ISel's arg push:
; CHECK: movl %esp, [[REGISTER:%[a-z]+]]
; CHECK: movl $42, ([[REGISTER]])
; CHECK: movl L_test5dllimport$non_lazy_ptr-L8$pb(%eax), %eax

}
declare dllimport i32 @test5dllimport(i32)

0 comments on commit 7662d50

Please sign in to comment.